Added C21, STA and STX (still in progress) sets, improved Android downloader, added/fixed primitives, added a keyword to get if a card has "X" in its cost, fixed a crash while targeting a spell on stack, added a new option "nolegend" to clone keyword in order to create a token without legendary type and rule, improved "hascnt" keyword with "anycnt" option to count all counters on a card, added a new keyword "hasstorecard" to get if a card has a stored card or not(e.g. fizzlers), added a new keyword "pgmanainstantsorcery" to count the mana value of all instants and sorceries in player graveyard, added a new keyword "currentphase" to get the current game phase.

This commit is contained in:
Vittorio Alfieri
2021-04-20 23:34:30 +02:00
parent d7838829ad
commit 9da159a607
19 changed files with 5338 additions and 314 deletions
+11 -10
View File
@@ -262,20 +262,21 @@ void StackAbility::Render()
Targetable * tt = ability->getActionTc()->getTargetsFrom()[i];
if(tt)
{
if( ((Damageable *)(tt))->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE )
MTGCardInstance* card = dynamic_cast<MTGCardInstance *>(tt);
if(!card && dynamic_cast<Spell *>(tt)) card = dynamic_cast<Spell *>(tt)->source; //Fixed crash on targeting a spell on stack by correctly casting variable tt.
if(((Damageable *)(tt))->type_as_damageable == Damageable::DAMAGEABLE_MTGCARDINSTANCE)
{
//fill vector
myClones.push_back(((MTGCardInstance*)(tt)));
if( source->has(Constants::HIDDENFACE) && !observer->isInLibrary(((MTGCardInstance *)(tt))) )
mytargetQuads.push_back( ((Damageable *)(tt))->getIcon() );
else if ( !source->has(Constants::HIDDENFACE) )
mytargetQuads.push_back( ((Damageable *)(tt))->getIcon() );
if(card)
myClones.push_back(card); //fill vector
if(source->has(Constants::HIDDENFACE) && card && !observer->isInLibrary(card))
mytargetQuads.push_back(card->getIcon()); //Fixed crash on targeting a spell on stack by correctly casting variable tt.
else if (!source->has(Constants::HIDDENFACE) && card)
mytargetQuads.push_back(card->getIcon()); //Fixed crash on targeting a spell on stack by correctly casting variable tt.
else
fmLibrary++;
}
//else // This was crashing the game when a permanent targeted a spell in the stack
//mytargetQuads.push_back( ((Damageable *)(tt))->getIcon() );
else if(card)
mytargetQuads.push_back(card->getIcon()); //Fixed crash on targeting a spell on stack by correctly casting variable tt.
}
}
}
+5
View File
@@ -3655,6 +3655,8 @@ int AAFizzler::resolve()
}
}
stack->Fizzle(sTarget, fizzleMode);
if(!source->storedCard)
source->storedCard = sCard; // Store the fizzled card to retrive target information later (e.g. manacost for Reinterpret)
return 1;
}
@@ -5243,6 +5245,9 @@ int AACloner::resolve()
Spell * spell = NEW Spell(game, myClone);
spell->source->isToken = 1;
if(spell->source->hasType(Subtypes::TYPE_LEGENDARY) && options.find("nolegend") != string::npos){ // check if the token has to be legendary or not. (e.g. Double Major)
spell->source->removeType(Subtypes::TYPE_LEGENDARY);
}
spell->resolve();
spell->source->owner = targetPlayer;
spell->source->lastController = targetPlayer;
+6
View File
@@ -24,6 +24,7 @@ CardDescriptor::CardDescriptor()
zposition = -1;
hasKickerCost = 0;
hasFlashbackCost = 0;
hasXCost = 0;
compareName ="";
nameComparisonMode = COMPARISON_NONE;
colorComparisonMode = COMPARISON_NONE;
@@ -275,6 +276,11 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
match = NULL;
}
if ((hasXCost == -1 && card->getManaCost()->hasX()) || (hasXCost == 1 && !card->getManaCost()->hasX()))
{
match = NULL;
}
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped()))
{
match = NULL;
+12
View File
@@ -1544,6 +1544,18 @@ bool CardGui::FilterCard(MTGCard * _card,string filter)
cd.isToken = 1;
}
}
//Has x in cost
else if (attribute.find("hasx") != string::npos)
{
if (minus)
{
cd.hasXCost = -1;
}
else
{
cd.hasXCost = 1;
}
}
//put in its zone this turn
else if (attribute.find("fresh") != string::npos)
{
+10 -5
View File
@@ -1684,7 +1684,6 @@ int GameObserver::isInPlay(MTGCardInstance * card)
}
int GameObserver::isInGrave(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * graveyard = players[i]->game->graveyard;
@@ -1695,7 +1694,6 @@ int GameObserver::isInGrave(MTGCardInstance * card)
}
int GameObserver::isInExile(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * exile = players[i]->game->exile;
@@ -1706,7 +1704,6 @@ int GameObserver::isInExile(MTGCardInstance * card)
}
int GameObserver::isInCommandZone(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * commandzone = players[i]->game->commandzone;
@@ -1717,7 +1714,6 @@ int GameObserver::isInCommandZone(MTGCardInstance * card)
}
int GameObserver::isInHand(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * hand = players[i]->game->hand;
@@ -1728,7 +1724,6 @@ int GameObserver::isInHand(MTGCardInstance * card)
}
int GameObserver::isInLibrary(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * library = players[i]->game->library;
@@ -1737,6 +1732,16 @@ int GameObserver::isInLibrary(MTGCardInstance * card)
}
return 0;
}
int GameObserver::isInStack(MTGCardInstance * card)
{
for (int i = 0; i < 2; i++)
{
MTGGameZone * stack = players[i]->game->stack;
if (players[i]->game->isInZone(card, stack))
return 1;
}
return 0;
}
void GameObserver::cleanupPhase()
{
currentPlayer->cleanupPhase();
+1
View File
@@ -3267,6 +3267,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
string with = "";
string types = "";
string options = "";
replace(s.begin(), s.end(), '^', ','); // To allow the usage of ^ instead of , char (e.g. using clone keyword inside transforms)
vector<string> splitWith = parseBetween(s, "with(", ")");
if (splitWith.size())
{
+2 -1
View File
@@ -957,7 +957,8 @@ int MTGCardInstance::countDuplicateCardNames()
for(int x = 0; x < nb_cards; x++)
{
if(controller()->game->battlefield->cards[x]->name == this->name && !(controller()->game->battlefield->cards[x]->mutation && controller()->game->battlefield->cards[x]->parentCards.size() > 0)) // Don't count Mutated down card
count+=1;
if(!(this->hasType(Subtypes::TYPE_LEGENDARY) && !(controller()->game->battlefield->cards[x]->hasType(Subtypes::TYPE_LEGENDARY)))) // This fix issue when cloning a card with nolegend option (e.g. Double Major)
count+=1;
}
}
return count;
+3
View File
@@ -519,6 +519,9 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone
if (!(copy = from->removeCard(card, doCopy)))
return NULL; //ERROR
if(!card->hasType(Subtypes::TYPE_LEGENDARY) && copy->hasType(Subtypes::TYPE_LEGENDARY)) // This fix issue when cloning a card with nolegend option (e.g. Double Major)
copy->removeType(Subtypes::TYPE_LEGENDARY);
// Copy all the counters of the original card... (solving the bug on comparison cards with counter before zone changing events)
if(card->counters && doCopy && !asCopy && !inplaytoinplay){
for (unsigned int i = 0; i < card->counters->counters.size(); i++){
+2 -2
View File
@@ -3601,7 +3601,7 @@ void MTGNewLegend::MoveLegend(MTGCardInstance * card)
vector<MTGAbility*>selection;
MTGCardInstance * myClone = NEW MTGCardInstance(card, card->controller()->game);
TargetChooserFactory tfL(game);
tcL = tfL.createTargetChooser("*[-Mutated;share!name!]|mybattlefield",myClone); // The Mutated down cards cannot be considered as Legendary card anymore
tcL = tfL.createTargetChooser("*[-mutated;legendary;share!name!]|mybattlefield",myClone); // The Mutated down cards cannot be considered as Legendary card anymore
tcL->targetter = NULL;
tcL->maxtargets = 1;
Legendrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), myClone, NULL,"ownergraveyard","Put in Graveyard");
@@ -3718,7 +3718,7 @@ void MTGNewPlaneswalker::MovePW(MTGCardInstance * card)
vector<MTGAbility*>selection;
MTGCardInstance * myClone = NEW MTGCardInstance(card, card->controller()->game);
TargetChooserFactory tfL(game);
tcP = tfL.createTargetChooser("*[share!name!]|mybattlefield",myClone);
tcP = tfL.createTargetChooser("*[-mutated;legendary;share!name!]|mybattlefield",myClone); // The Mutated down cards cannot be considered as Legendary card anymore
tcP->targetter = NULL;
tcP->maxtargets = 1;
PWrule = NEW AAMover(game, game->mLayers->actionLayer()->getMaxId(), myClone, NULL,"ownergraveyard","Put in Graveyard");
+12
View File
@@ -589,6 +589,18 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta
cd->isToken = 1;
}
}
//Has x in cost
else if (attribute.find("hasx") != string::npos)
{
if (minus)
{
cd->hasXCost = -1;
}
else
{
cd->hasXCost = 1;
}
}
//put in its zone this turn
else if (attribute.find("fresh") != string::npos)
{
+20 -4
View File
@@ -588,9 +588,13 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card)
{
intValue = (s == "pdrewcount")?target->controller()->drawCounter:target->controller()->opponent()->drawCounter;
}
else if (s == "epicactivated" || s == "currentturn")
else if (s == "epicactivated" || s == "hasstorecard")
{
intValue = (s == "epicactivated")?target->controller()->epic:target->getObserver()->turn;
intValue = (s == "epicactivated")?target->controller()->epic:(target->storedCard != 0);
}
else if (s == "currentphase" || s == "currentturn" )
{
intValue = (s == "currentphase")?target->getObserver()->getCurrentGamePhase():target->getObserver()->turn;
}
else if (s == "canforetellcast")
{
@@ -603,14 +607,16 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card)
if(Constants::MTGBasicAbilities[i] == s.substr(10))
intValue = card->basicAbilities[i];
}
else if (s.find("hascnt") != string::npos) //Return the amount of specific counters on card
else if (s.find("hascnt") != string::npos) //Return the amount of specific counters on card (use "anycnt" to count all of them e.g. Nils, Discipline Enforcer)
{
intValue = 0;
if (card->counters){
Counters * counters = card->counters;
for(size_t i = 0; i < counters->counters.size(); ++i){
Counter * counter = counters->counters[i];
if(counter->name == "" && (s.substr(6) == "11" || s.substr(6) == "-1-1")){
if(s.substr(6) == "anycnt"){
intValue += counter->nb;
} else if(counter->name == "" && (s.substr(6) == "11" || s.substr(6) == "-1-1")){
if((counter->power == 1 && counter->toughness == 1 && s.substr(6) == "11") || (counter->power == -1 && counter->toughness == -1 && s.substr(6) == "-1-1")){
intValue = counter->nb;
break;
@@ -843,6 +849,16 @@ void WParsedInt::init(string s, Spell * spell, MTGCardInstance * card)
intValue += 1;
}
}
else if (s == "pgmanainstantsorcery")//Inferno Project
{
intValue = 0;
for (int j = card->controller()->game->graveyard->nb_cards - 1; j >= 0; --j)
{
if (card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_INSTANT)
||card->controller()->game->graveyard->cards[j]->hasType(Subtypes::TYPE_SORCERY))
intValue += card->controller()->game->graveyard->cards[j]->myconvertedcost;
}
}
else if (s == "gravecardtypes")//Tarmogoyf
{
intValue = 0;