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:
@@ -43015,8 +43015,9 @@ type=Enchantment
|
||||
[/card]
|
||||
[card]
|
||||
name=Shared Summons
|
||||
aicode=activate target(<upto:2>creature[-share!name!]|mylibrary) moveto(myhand)
|
||||
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~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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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<DeckMetaData *> 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<DeckMetaData *> 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<DeckMetaData *> 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<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 *>
|
||||
static void renderDeckMenu(SimpleMenu * _menu, const vector<DeckMetaData *>& deckMetaDataList);
|
||||
|
||||
@@ -217,6 +217,7 @@ public:
|
||||
map<int, int> cards;
|
||||
string meta_desc;
|
||||
string meta_name;
|
||||
bool meta_commander;
|
||||
vector<string> meta_AIHints;
|
||||
vector<string> Sideboard;
|
||||
vector<string> CommandZone;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<string> 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);
|
||||
|
||||
@@ -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<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,
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
@@ -52,6 +42,11 @@ vector<DeckMetaData *> 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<int> unlockRequirements = meta->getUnlockRequirements();
|
||||
|
||||
@@ -240,7 +240,7 @@ void GameStateDuel::Start()
|
||||
GameStateDuel::selectedPlayerDeckId, true);
|
||||
deckmenu->enableDisplayDetailsOverride();
|
||||
DeckManager *deckManager = DeckManager::GetInstance();
|
||||
vector<DeckMetaData *> playerDeckList = BuildDeckList(options.profileFile());
|
||||
vector<DeckMetaData *> 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<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);
|
||||
tournament->setAvailableDecks(opponentDeckList.size());
|
||||
opponentMenu->Add(MENUITEM_CANCEL, "Cancel", _("Choose a different player deck").c_str());
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user