Fixed primitives, added "notshare!" keyword (e.g. to search cards with different names), improved decks selection according to chosen game mode (e.g. Game will show commander decks only in commander mode and it will hide them in other modes).

This commit is contained in:
Vittorio Alfieri
2021-01-22 14:15:43 +01:00
parent 3a38e7f4ab
commit 5184132e8b
11 changed files with 63 additions and 34 deletions
@@ -43015,8 +43015,9 @@ type=Enchantment
[/card] [/card]
[card] [card]
name=Shared Summons name=Shared Summons
aicode=activate target(<upto:2>creature[-share!name!]|mylibrary) moveto(myhand) 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=name(search card) Reveal:type:*:mylibrary revealzone(mylibrary) optionone name(choose card) target(<upto:2>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~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. 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} mana={3}{G}{G}
type=Instant type=Instant
+3 -1
View File
@@ -30,7 +30,9 @@ class CardDescriptor: public MTGCardInstance
public: public:
enum Operator{ enum Operator{
CD_OR = 1, CD_OR = 1,
CD_AND = 2 CD_AND = 2,
CD_NOR = 3,
CD_NAND = 4
}; };
Operator mode; Operator mode;
+1 -1
View File
@@ -33,7 +33,7 @@ private:
public: public:
bool isCommanderDeck; //Added to read the command tag in deck's metafile.
DeckMetaData(const string& filename, bool isAI = false); DeckMetaData(const string& filename, bool isAI = false);
void LoadDeck(); void LoadDeck();
void LoadStats(); void LoadStats();
+3 -6
View File
@@ -73,14 +73,11 @@ public:
// it makes it easier to manipulate the deck information menus. // it makes it easier to manipulate the deck information menus.
// generate the Deck Meta Data and build the menu items of the menu given // generate the Deck Meta Data and build the menu items of the menu given
static vector<DeckMetaData *> fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL); // 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<DeckMetaData *> fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0, GameType type = GAME_TYPE_CLASSIC);
// 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<DeckMetaData *> fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0);
// build a vector of decks with the information passsed in. // build a vector of decks with the information passsed in.
static vector<DeckMetaData *> BuildDeckList(const string& path, const string& smallDeckPrefix = "", Player * statsPlayer = NULL, int maxDecks = 0); static vector<DeckMetaData *> 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<DeckMetaData *> // build menu items based on the vector<DeckMetaData *>
static void renderDeckMenu(SimpleMenu * _menu, const vector<DeckMetaData *>& deckMetaDataList); static void renderDeckMenu(SimpleMenu * _menu, const vector<DeckMetaData *>& deckMetaDataList);
+1
View File
@@ -217,6 +217,7 @@ public:
map<int, int> cards; map<int, int> cards;
string meta_desc; string meta_desc;
string meta_name; string meta_name;
bool meta_commander;
vector<string> meta_AIHints; vector<string> meta_AIHints;
vector<string> Sideboard; vector<string> Sideboard;
vector<string> CommandZone; vector<string> CommandZone;
+19 -2
View File
@@ -172,8 +172,9 @@ MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card)
return NULL; return NULL;
if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition))
return NULL; return NULL;
if (nameComparisonMode && compareName != card->name) if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name))
return NULL; return NULL;
return card; return card;
} }
@@ -219,7 +220,7 @@ MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card)
match = NULL; match = NULL;
if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition)) if (zposComparisonMode && !valueInRange(zposComparisonMode, card->zpos, zposition))
match = NULL; match = NULL;
if(nameComparisonMode && compareName != card->name) if ((nameComparisonMode == COMPARISON_UNEQUAL && compareName == card->name) || (nameComparisonMode && nameComparisonMode != COMPARISON_UNEQUAL && compareName != card->name))
match = NULL; match = NULL;
return match; return match;
@@ -233,10 +234,26 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
{ {
match = match_and(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) else if (mode == CD_OR)
{ {
match = match_or(card); match = match_or(card);
} }
else if (mode == CD_NOR)
{
match = match_or(card);
if(!match)
match = card;
else
match = NULL;
}
//Abilities //Abilities
BasicAbilitiesSet set = basicAbilities & card->basicAbilities; BasicAbilitiesSet set = basicAbilities & card->basicAbilities;
+2
View File
@@ -30,6 +30,7 @@ void DeckMetaData::LoadDeck()
mName = trim(deck.meta_name); mName = trim(deck.meta_name);
mDescription = trim(deck.meta_desc); mDescription = trim(deck.meta_desc);
mDeckId = atoi((mFilename.substr(mFilename.find("deck") + 4, mFilename.find(".txt"))).c_str()); 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<string> requirements = split(deck.meta_unlockRequirements, ','); vector<string> requirements = split(deck.meta_unlockRequirements, ',');
for(size_t i = 0; i < requirements.size(); ++i) for(size_t i = 0; i < requirements.size(); ++i)
@@ -64,6 +65,7 @@ void DeckMetaData::LoadStats()
mGamesPlayed = 0; mGamesPlayed = 0;
mColorIndex = ""; mColorIndex = "";
mDifficulty = 0; mDifficulty = 0;
isCommanderDeck = false;
stats->load(mPlayerDeck); stats->load(mPlayerDeck);
DeckStat * opponentDeckStats = stats->getDeckStat(mStatsFilename); DeckStat * opponentDeckStats = stats->getDeckStat(mStatsFilename);
+8 -13
View File
@@ -14,27 +14,17 @@
// TODO: revise sorting strategy to allow other types of sorting. Currently, it is hardwired to use // 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. // sortByName to do the sorting. This was done since the menu item display is done in insertion order.
vector<DeckMetaData *> GameState::fillDeckMenu(SimpleMenu * _menu, const string& path, const string& smallDeckPrefix,
Player * statsPlayer)
{
vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer);
renderDeckMenu(_menu, deckMetaDataVector);
return deckMetaDataVector;
}
vector<DeckMetaData *> GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix, vector<DeckMetaData *> GameState::fillDeckMenu(DeckMenu * _menu, const string& path, const string& smallDeckPrefix,
Player * statsPlayer, int maxDecks) Player * statsPlayer, int maxDecks, GameType type)
{ {
vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks); vector<DeckMetaData *> deckMetaDataVector = BuildDeckList(path, smallDeckPrefix, statsPlayer, maxDecks, type);
renderDeckMenu(_menu, deckMetaDataVector); renderDeckMenu(_menu, deckMetaDataVector);
return deckMetaDataVector; return deckMetaDataVector;
} }
vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks) vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string& smallDeckPrefix, Player * statsPlayer, int maxDecks, GameType type)
{ {
vector<DeckMetaData*> retList; vector<DeckMetaData*> retList;
@@ -52,6 +42,11 @@ vector<DeckMetaData *> GameState::BuildDeckList(const string& path, const string
if (meta) if (meta)
{ {
found = 1; 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... //Check if the deck is unlocked based on sets etc...
bool unlocked = true; bool unlocked = true;
vector<int> unlockRequirements = meta->getUnlockRequirements(); vector<int> unlockRequirements = meta->getUnlockRequirements();
+2 -2
View File
@@ -240,7 +240,7 @@ void GameStateDuel::Start()
GameStateDuel::selectedPlayerDeckId, true); GameStateDuel::selectedPlayerDeckId, true);
deckmenu->enableDisplayDetailsOverride(); deckmenu->enableDisplayDetailsOverride();
DeckManager *deckManager = DeckManager::GetInstance(); DeckManager *deckManager = DeckManager::GetInstance();
vector<DeckMetaData *> playerDeckList = BuildDeckList(options.profileFile()); vector<DeckMetaData *> playerDeckList = BuildDeckList(options.profileFile(), "", NULL, 0, mParent->gameType);
int nbDecks = playerDeckList.size(); int nbDecks = playerDeckList.size();
if (nbDecks) if (nbDecks)
@@ -425,7 +425,7 @@ void GameStateDuel::ConstructOpponentMenu()
DeckManager * deckManager = DeckManager::GetInstance(); DeckManager * deckManager = DeckManager::GetInstance();
vector<DeckMetaData*> opponentDeckList; vector<DeckMetaData*> 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); deckManager->updateMetaDataList(&opponentDeckList, true);
tournament->setAvailableDecks(opponentDeckList.size()); tournament->setAvailableDecks(opponentDeckList.size());
opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str()); opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str());
+6 -2
View File
@@ -825,6 +825,7 @@ MTGDeck::MTGDeck(MTGAllCards * _allcards)
database = _allcards; database = _allcards;
filename = ""; filename = "";
meta_name = ""; meta_name = "";
meta_commander = false;
} }
int MTGDeck::totalPrice() int MTGDeck::totalPrice()
@@ -850,6 +851,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
size_t dot = filename.find("."); size_t dot = filename.find(".");
meta_name = filename.substr(slash + 1, dot - slash - 1); meta_name = filename.substr(slash + 1, dot - slash - 1);
meta_id = atoi(meta_name.substr(4).c_str()); meta_id = atoi(meta_name.substr(4).c_str());
meta_commander = false;
std::string contents; std::string contents;
if (JFileSystem::GetInstance()->readIntoString(config_file, contents)) if (JFileSystem::GetInstance()->readIntoString(config_file, contents))
{ {
@@ -888,7 +890,7 @@ MTGDeck::MTGDeck(const string& config_file, MTGAllCards * _allcards, int meta_on
continue; 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. 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 = s.substr(found + 3);
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); 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. 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) if (found != string::npos)
{ {
meta_commander = true; //Added to read the command tag in metafile.
if(!database) continue;
s = s.substr(found + 4); s = s.substr(found + 4);
s.erase(s.find_last_not_of("\t\n\v\f\r ") + 1); 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 ")); 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; continue;
} }
if (meta_only) break; if (meta_only) continue; //Changed from break in order to read the command tag in metafile.
int numberOfCopies = 1; int numberOfCopies = 1;
size_t found = s.find(" *"); size_t found = s.find(" *");
if (found != string::npos) if (found != string::npos)
+10
View File
@@ -816,6 +816,9 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
else else
cd->compareName = card->name; cd->compareName = card->name;
if (attribute.find("notshare!") != string::npos)
cd->nameComparisonMode = COMPARISON_UNEQUAL;
else
cd->nameComparisonMode = COMPARISON_EQUAL; cd->nameComparisonMode = COMPARISON_EQUAL;
} }
else if( CDtype.find("color") != string::npos ) else if( CDtype.find("color") != string::npos )
@@ -825,6 +828,9 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
else else
cd->colors = card->colors; cd->colors = card->colors;
if (attribute.find("notshare!") != string::npos)
cd->mode = CardDescriptor::CD_NOR;
else
cd->mode = CardDescriptor::CD_OR; cd->mode = CardDescriptor::CD_OR;
} }
else if( CDtype.find("types") != string::npos ) else if( CDtype.find("types") != string::npos )
@@ -853,6 +859,10 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
subt << card->getName() << "_DummyType_" << i; subt << card->getName() << "_DummyType_" << i;
cd->setSubtype(subt.str()); // Fix to avoid type vector size is 0 causing the always true match issue. cd->setSubtype(subt.str()); // Fix to avoid type vector size is 0 causing the always true match issue.
} }
if (attribute.find("notshare!") != string::npos)
cd->mode = CardDescriptor::CD_NOR;
else
cd->mode = CardDescriptor::CD_OR; cd->mode = CardDescriptor::CD_OR;
} }
} }