diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index d6f25cf56..8be760835 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -43015,8 +43015,9 @@ type=Enchantment [/card] [card] name=Shared Summons -aicode=activate target(creature[-share!name!]|mylibrary) moveto(myhand) -auto=name(search card) Reveal:type:*:mylibrary revealzone(mylibrary) optionone name(choose card) target(creature[-share!name!]|reveal) transforms((,newability[all(other *|reveal) moveto(mylibrary) and!(shuffle)!],newability[moveto(myhand)])) optiononeend optiontwo name(shuffle) bottomoflibrary target(<1>*|reveal) and!( all(*|reveal) bottomoflibrary and!(shuffle)! )! optiontwoend revealend +auto=if type(creature|mylibrary)~morethan~1 then choice name(Search 2 creatures) name(Search 2 creatures) target(creature|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( transforms((,newability[name(Search second creature) target(creature[notshare!name!]|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( ability$!name(Put in hand from library) name(Put in hand from library) target(<2>creature[fresh]|opponentlibrary) moveto(opponenthand) and!( shuffle opponent )! !$ opponent )! )!])) oneshot )! )! +auto=if type(creature|mylibrary)~morethan~0 then choice name(Search 1 creature) name(Search 1 creature) target(creature|mylibrary) moveto(myreveal) and!( moveto(mylibrary) and!( transforms((,newability[ability$!name(Put in hand from library) name(Put in hand from library) target(creature[fresh]|opponentlibrary) moveto(opponenthand) and!( shuffle opponent )! !$ opponent])) oneshot )! )! +auto=if type(creature|mylibrary)~morethan~0 then choice name(Don't search) name(Don't search) donothing text=Search your library for up to two creature cards with different names, reveal them, put them into your hand, then shuffle your library. mana={3}{G}{G} type=Instant diff --git a/projects/mtg/include/CardDescriptor.h b/projects/mtg/include/CardDescriptor.h index cfa938204..020deaa72 100644 --- a/projects/mtg/include/CardDescriptor.h +++ b/projects/mtg/include/CardDescriptor.h @@ -30,7 +30,9 @@ class CardDescriptor: public MTGCardInstance public: enum Operator{ CD_OR = 1, - CD_AND = 2 + CD_AND = 2, + CD_NOR = 3, + CD_NAND = 4 }; Operator mode; diff --git a/projects/mtg/include/DeckMetaData.h b/projects/mtg/include/DeckMetaData.h index 22617648d..eaf3d2304 100644 --- a/projects/mtg/include/DeckMetaData.h +++ b/projects/mtg/include/DeckMetaData.h @@ -24,7 +24,7 @@ private: int mDeckId; string mAvatarFilename; string mColorIndex; - + // statistical information int mGamesPlayed, mVictories, mPercentVictories, mDifficulty; int getAvatarId(); @@ -33,7 +33,7 @@ private: public: - + bool isCommanderDeck; //Added to read the command tag in deck's metafile. DeckMetaData(const string& filename, bool isAI = false); void LoadDeck(); void LoadStats(); diff --git a/projects/mtg/include/GameState.h b/projects/mtg/include/GameState.h index aa21d870a..12fe48024 100644 --- a/projects/mtg/include/GameState.h +++ b/projects/mtg/include/GameState.h @@ -73,14 +73,11 @@ public: // it makes it easier to manipulate the deck information menus. // generate the Deck Meta Data and build the menu items of the menu given - static vector fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL); - - // generate the Deck Meta Data and build the menu items of the menu given - // Will display up to maxDecks if maxDecks is non 0,all decks in path otherwise - static vector fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0); + // Will display up to maxDecks if maxDecks is non 0,all decks in path otherwise and it will show or not commander decks according to the current game type + static vector fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0, GameType type = GAME_TYPE_CLASSIC); // build a vector of decks with the information passsed in. - static vector BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0); + static vector BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0, GameType type = GAME_TYPE_CLASSIC); // build menu items based on the vector static void renderDeckMenu(SimpleMenu * _menu, const vector& deckMetaDataList); diff --git a/projects/mtg/include/MTGDeck.h b/projects/mtg/include/MTGDeck.h index a49896207..609a72072 100644 --- a/projects/mtg/include/MTGDeck.h +++ b/projects/mtg/include/MTGDeck.h @@ -217,6 +217,7 @@ public: map cards; string meta_desc; string meta_name; + bool meta_commander; vector meta_AIHints; vector Sideboard; vector CommandZone; diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index e6e5f61b5..5b9ee2f17 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -172,8 +172,9 @@ MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card) return NULL; if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) return NULL; - if (nameComparisonMode && compareName != card->name) + if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name)) return NULL; + return card; } @@ -219,7 +220,7 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card) match = NULL; if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) match = NULL; - if(nameComparisonMode && compareName != card->name) + if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name)) match = NULL; return match; @@ -233,10 +234,26 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card) { match = match_and(card); } + else if (mode == CD_NAND) + { + match = match_and(card); + if(!match) + match = card; + else + match = NULL; + } else if (mode == CD_OR) { match = match_or(card); } + else if (mode == CD_NOR) + { + match = match_or(card); + if(!match) + match = card; + else + match = NULL; + } //Abilities BasicAbilitiesSet set = basicAbilities & card->basicAbilities; diff --git a/projects/mtg/src/DeckMetaData.cpp b/projects/mtg/src/DeckMetaData.cpp index b53b98008..eccf500c5 100644 --- a/projects/mtg/src/DeckMetaData.cpp +++ b/projects/mtg/src/DeckMetaData.cpp @@ -30,6 +30,7 @@ void DeckMetaData::LoadDeck() mName = trim(deck.meta_name); mDescription = trim(deck.meta_desc); mDeckId = atoi((mFilename.substr(mFilename.find("deck") + 4, mFilename.find(".txt"))).c_str()); + isCommanderDeck = deck.meta_commander; //Added to read the command tag in deck's metafile. vector requirements = split(deck.meta_unlockRequirements, ','); for(size_t i = 0; i < requirements.size(); ++i) @@ -64,6 +65,7 @@ void DeckMetaData::LoadStats() mGamesPlayed = 0; mColorIndex = ""; mDifficulty = 0; + isCommanderDeck = false; stats->load(mPlayerDeck); DeckStat * opponentDeckStats = stats->getDeckStat(mStatsFilename); diff --git a/projects/mtg/src/GameState.cpp b/projects/mtg/src/GameState.cpp index ff26683fc..1a82a18fc 100644 --- a/projects/mtg/src/GameState.cpp +++ b/projects/mtg/src/GameState.cpp @@ -14,27 +14,17 @@ // TODO: revise sorting strategy to allow other types of sorting. Currently, it is hardwired to use // sortByName to do the sorting. This was done since the menu item display is done in insertion order. -vector GameState::fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix, - Player * statsPlayer) -{ - - vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer); - renderDeckMenu(_menu, deckMetaDataVector); - - return deckMetaDataVector; -} - vector GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix, - Player * statsPlayer, int maxDecks) + Player * statsPlayer, int maxDecks, GameType type) { - vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks); + vector deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks, type); renderDeckMenu(_menu, deckMetaDataVector); return deckMetaDataVector; } -vector GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks) +vector GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks, GameType type) { vector retList; @@ -52,6 +42,11 @@ vector GameState::BuildDeckList(const string& path, const string if (meta) { found = 1; + if((meta->isCommanderDeck && type != GAME_TYPE_COMMANDER) || (!meta->isCommanderDeck && type == GAME_TYPE_COMMANDER)){ + meta = NULL; // It will show commander decks only in commander mode and it will hide them in other modes. + nbDecks++; + continue; + } //Check if the deck is unlocked based on sets etc... bool unlocked = true; vector unlockRequirements = meta->getUnlockRequirements(); diff --git a/projects/mtg/src/GameStateDuel.cpp b/projects/mtg/src/GameStateDuel.cpp index 2acb98b5e..04415e9ac 100644 --- a/projects/mtg/src/GameStateDuel.cpp +++ b/projects/mtg/src/GameStateDuel.cpp @@ -240,7 +240,7 @@ void GameStateDuel::Start() GameStateDuel::selectedPlayerDeckId, true); deckmenu->enableDisplayDetailsOverride(); DeckManager *deckManager = DeckManager::GetInstance(); - vector playerDeckList = BuildDeckList(options.profileFile()); + vector playerDeckList = BuildDeckList(options.profileFile(), "", NULL, 0, mParent->gameType); int nbDecks = playerDeckList.size(); if (nbDecks) @@ -425,7 +425,7 @@ void GameStateDuel::ConstructOpponentMenu() DeckManager * deckManager = DeckManager::GetInstance(); vector opponentDeckList; - opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", game->getPlayer(0), nbUnlockedDecks); + opponentDeckList = fillDeckMenu(opponentMenu, "ai/baka", "ai_baka", game->getPlayer(0), nbUnlockedDecks, mParent->gameType); deckManager->updateMetaDataList(&opponentDeckList, true); tournament->setAvailableDecks(opponentDeckList.size()); opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); diff --git a/projects/mtg/src/MTGDeck.cpp b/projects/mtg/src/MTGDeck.cpp index f76abe87d..2c707e3a4 100644 --- a/projects/mtg/src/MTGDeck.cpp +++ b/projects/mtg/src/MTGDeck.cpp @@ -825,6 +825,7 @@ MTGDeck::MTGDeck(MTGAllCards * _allcards) database = _allcards; filename = ""; meta_name = ""; + meta_commander = false; } int MTGDeck::totalPrice() @@ -850,6 +851,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on size_t dot = filename.find("."); meta_name = filename.substr(slash + 1, dot - slash - 1); meta_id = atoi(meta_name.substr(4).c_str()); + meta_commander = false; std::string contents; if (JFileSystem::GetInstance()->readIntoString(config_file, contents)) { @@ -888,7 +890,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on continue; } found = s.find("SB:"); // Now it's possible to add cards to Sideboard even using their Name instead of ID such as normal deck cards. - if (found != string::npos) + if (found != string::npos && database) { s = s.substr(found + 3); s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); @@ -920,6 +922,8 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on found = s.find("CMD:"); // Now it's possible to add a card to Command Zone even using their Name instead of ID such as normal deck cards. if (found != string::npos) { + meta_commander = true; //Added to read the command tag in metafile. + if(!database) continue; s = s.substr(found + 4); s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); s.erase(0, s.find_first_not_of("\t\n\v\f\r ")); @@ -961,7 +965,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on } continue; } - if (meta_only) break; + if (meta_only) continue; //Changed from break in order to read the command tag in metafile. int numberOfCopies = 1; size_t found = s.find(" *"); if (found != string::npos) diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 02bfd61d8..e93f55de1 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -816,7 +816,10 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta else cd->compareName = card->name; - cd->nameComparisonMode = COMPARISON_EQUAL; + if (attribute.find("notshare!") != string::npos) + cd->nameComparisonMode = COMPARISON_UNEQUAL; + else + cd->nameComparisonMode = COMPARISON_EQUAL; } else if( CDtype.find("color") != string::npos ) { @@ -824,8 +827,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta cd->colors = card->target->colors; else cd->colors = card->colors; - - cd->mode = CardDescriptor::CD_OR; + + if (attribute.find("notshare!") != string::npos) + cd->mode = CardDescriptor::CD_NOR; + else + cd->mode = CardDescriptor::CD_OR; } else if( CDtype.find("types") != string::npos ) { @@ -853,7 +859,11 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta subt << card->getName() << "_DummyType_" << i; cd->setSubtype(subt.str()); // Fix to avoid type vector size is 0 causing the always true match issue. } - cd->mode = CardDescriptor::CD_OR; + + if (attribute.find("notshare!") != string::npos) + cd->mode = CardDescriptor::CD_NOR; + else + cd->mode = CardDescriptor::CD_OR; } } else if (attribute.find("counter") != string::npos)