946df16af5
added new card discriptor [share!variable!]
the variables for this so far are
name <---eradicate effect targetting
color <--radiance effect targetting
types <--the plague cycles
it is important to note that a target IS REQUIRED before this, meaning it has to be used below a target= or after the targetting of an && ability...otherwise it will simply default to the source cards variables.
this solution provides a much more generic version without sacrificing the effectiveness of the eradicate set which was limited only to eradicate style cards(which ALSO required a target)
coding exsample
[card]
name=Eradicate
target=creature[-black]
auto=all(*[share!name!]|targetcontrollerhand) moveto(exile)
auto=all(*[share!name!]|targetcontrollerlibrary) moveto(exile)
auto=all(*[share!name!]|targetcontrollergraveyard)moveto(exile)
auto=all(*[share!name!]|targetcontrollerbattlefield) moveto(exile)
mana={2}{b}{b}
type=sorcery
[/card]
you will notice something strange above, for this change to work i had to fix the bug with "targetcontrollerBLAH" zone targetting...tho my fix was a patchwork fix, it does indeed provide the targets controller...we need to find the root cause of why initToZone is not returning the correct "target" variable to this function.
if the source does not have a target it defaults to source.
before it there was no target, which there never is a correct target returned as noted by the fact that 0 cards exist with targetcontroller zone targetting in WAGIC however theres a considerably large card pool for this.
enjoy :)
docs going to kill me for this lol.
395 lines
9.8 KiB
C++
395 lines
9.8 KiB
C++
#include "PrecompiledHeader.h"
|
|
|
|
#include "CardDescriptor.h"
|
|
#include "Subtypes.h"
|
|
#include "Counters.h"
|
|
|
|
CardDescriptor::CardDescriptor() : MTGCardInstance()
|
|
{
|
|
init();
|
|
counterName = "";
|
|
counterPower = 0;
|
|
counterToughness = 0;
|
|
counterNB = 0;
|
|
mode = CD_AND;
|
|
powerComparisonMode = COMPARISON_NONE;
|
|
toughnessComparisonMode = COMPARISON_NONE;
|
|
manacostComparisonMode = COMPARISON_NONE;
|
|
counterComparisonMode = COMPARISON_NONE;
|
|
convertedManacost = -1;
|
|
compareName ="";
|
|
nameComparisonMode = COMPARISON_NONE;
|
|
colorComparisonMode = COMPARISON_NONE;
|
|
}
|
|
|
|
int CardDescriptor::init()
|
|
{
|
|
int result = MTGCardInstance::init();
|
|
attacker = 0;
|
|
defenser = NULL;
|
|
banding = NULL;
|
|
anyCounter = 0;
|
|
//Remove unnecessary pointers
|
|
SAFE_DELETE(counters);
|
|
SAFE_DELETE(previous);
|
|
return result;
|
|
}
|
|
|
|
void CardDescriptor::unsecureSetTapped(int i)
|
|
{
|
|
tapped = i;
|
|
}
|
|
|
|
void CardDescriptor::unsecuresetfresh(int k)
|
|
{
|
|
fresh = k;
|
|
}
|
|
|
|
void CardDescriptor::setisMultiColored(int w)
|
|
{
|
|
isMultiColored = w;
|
|
}
|
|
|
|
void CardDescriptor::setisBlackAndWhite(int w)
|
|
{
|
|
isBlackAndWhite = w;
|
|
}
|
|
void CardDescriptor::setisRedAndBlue(int w)
|
|
{
|
|
isRedAndBlue = w;
|
|
}
|
|
void CardDescriptor::setisBlackAndGreen(int w)
|
|
{
|
|
isBlackAndGreen = w;
|
|
}
|
|
void CardDescriptor::setisBlueAndGreen(int w)
|
|
{
|
|
isBlueAndGreen = w;
|
|
}
|
|
void CardDescriptor::setisRedAndWhite(int w)
|
|
{
|
|
isRedAndWhite = w;
|
|
}
|
|
|
|
void CardDescriptor::setNegativeSubtype(string value)
|
|
{
|
|
int id = Subtypes::subtypesList->find(value);
|
|
addType(-id);
|
|
}
|
|
|
|
// Very generic function to compare a value to a criterion.
|
|
// Should be easily transferable to a more generic class if desired.
|
|
bool CardDescriptor::valueInRange(int comparisonMode, int value, int criterion)
|
|
{
|
|
switch (comparisonMode)
|
|
{
|
|
case COMPARISON_AT_MOST:
|
|
return (value <= criterion);
|
|
case COMPARISON_AT_LEAST:
|
|
return (value >= criterion);
|
|
case COMPARISON_EQUAL:
|
|
return (value == criterion);
|
|
case COMPARISON_GREATER:
|
|
return (value > criterion);
|
|
case COMPARISON_LESS:
|
|
return (value < criterion);
|
|
case COMPARISON_UNEQUAL:
|
|
return (value != criterion);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match_or(MTGCardInstance * card)
|
|
{
|
|
int found = 1;
|
|
for (size_t i = 0; i < types.size(); i++)
|
|
{
|
|
found = 0;
|
|
if (types[i] >= 0)
|
|
{
|
|
|
|
if (card->hasSubtype(types[i]) || (Subtypes::subtypesList->find(card->getLCName(), false) == types[i]))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!card->hasSubtype(-types[i]) && (Subtypes::subtypesList->find(card->getLCName(), false) != -types[i]))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
return NULL;
|
|
|
|
for (int i = 0; i < Constants::MTG_NB_COLORS; i++)
|
|
{
|
|
if (colors[i] == 1)
|
|
{
|
|
found = 0;
|
|
if (card->hasColor(i))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
else if (colors[i] == -1)
|
|
{
|
|
found = 0;
|
|
if (!card->hasColor(i))
|
|
{
|
|
found = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!found)
|
|
return NULL;
|
|
|
|
// Quantified restrictions are always AND-ed:
|
|
if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power))
|
|
return NULL;
|
|
if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness))
|
|
return NULL;
|
|
if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost))
|
|
return NULL;
|
|
if (nameComparisonMode && compareName != card->name)
|
|
return NULL;
|
|
return card;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match_and(MTGCardInstance * card)
|
|
{
|
|
MTGCardInstance * match = card;
|
|
for (size_t i = 0; i < types.size(); i++)
|
|
{
|
|
if (types[i] >= 0)
|
|
{
|
|
if (!card->hasSubtype(types[i]) && !(Subtypes::subtypesList->find(card->getLCName(), false) == types[i]))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (card->hasSubtype(-types[i]) || (Subtypes::subtypesList->find(card->getLCName(), false) == -types[i]))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
}
|
|
for (int i = 0; i < Constants::MTG_NB_COLORS; i++)
|
|
{
|
|
if ((colors[i] == 1 && !card->hasColor(i)) || (colors[i] == -1 && card->hasColor(i)))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
|
|
if (powerComparisonMode && !valueInRange(powerComparisonMode, card->getPower(), power))
|
|
match = NULL;
|
|
if (toughnessComparisonMode && !valueInRange(toughnessComparisonMode, card->getToughness(), toughness))
|
|
match = NULL;
|
|
if (manacostComparisonMode && !valueInRange(manacostComparisonMode, card->getManaCost()->getConvertedCost(), convertedManacost))
|
|
match = NULL;
|
|
if(nameComparisonMode && compareName != card->name)
|
|
match = NULL;
|
|
if(colorComparisonMode)
|
|
{
|
|
bool hasMatch = false;
|
|
for (int i=0;i< Constants::MTG_NB_COLORS;i++)
|
|
{
|
|
if (card->hasColor(i) && colors[i] > 0)
|
|
{
|
|
hasMatch = true;
|
|
}
|
|
}
|
|
if( !hasMatch )
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
return match;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match(MTGCardInstance * card)
|
|
{
|
|
|
|
MTGCardInstance * match = card;
|
|
if (mode == CD_AND)
|
|
{
|
|
match = match_and(card);
|
|
}
|
|
else
|
|
{
|
|
match = match_or(card);
|
|
}
|
|
|
|
//Abilities
|
|
for (map<int, int>::const_iterator it = basicAbilities.begin(); it != basicAbilities.end(); ++it)
|
|
{
|
|
int j = it->first;
|
|
if ((basicAbilities[j] == 1 && !card->basicAbilities[j]) || (basicAbilities[j] == -1 && card->basicAbilities[j]))
|
|
{
|
|
match = NULL;
|
|
}
|
|
}
|
|
|
|
if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped()))
|
|
{
|
|
match = NULL;
|
|
}
|
|
|
|
if ((fresh == -1 && card->fresh) || (fresh == 1 && !card->fresh))
|
|
{
|
|
match = NULL;
|
|
}
|
|
|
|
if ((isMultiColored == -1 && card->isMultiColored) || (isMultiColored == 1 && !card->isMultiColored))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isBlackAndWhite == -1 && card->isBlackAndWhite) || (isBlackAndWhite == 1 && !card->isBlackAndWhite))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isRedAndBlue == -1 && card->isRedAndBlue) || (isRedAndBlue == 1 && !card->isRedAndBlue))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isBlackAndGreen == -1 && card->isBlackAndGreen) || (isBlackAndGreen == 1 && !card->isBlackAndGreen))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isBlueAndGreen == -1 && card->isBlueAndGreen) || (isBlueAndGreen == 1 && !card->isBlueAndGreen))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isRedAndWhite == -1 && card->isRedAndWhite) || (isRedAndWhite == 1 && !card->isRedAndWhite))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isLeveler == -1 && card->isLeveler) || (isLeveler == 1 && !card->isLeveler))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((CDenchanted == -1 && card->enchanted) || (CDenchanted == 1 && !card->enchanted))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if ((isToken == -1 && card->isToken) || (isToken == 1 && !card->isToken))
|
|
{
|
|
match = NULL;
|
|
}
|
|
if (attacker == 1)
|
|
{
|
|
if (defenser == &AnyCard)
|
|
{
|
|
if (!card->attacker && !card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (!card->attacker)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else if (attacker == -1)
|
|
{
|
|
if (defenser == &NoCard)
|
|
{
|
|
if (card->attacker || card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (card->attacker)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (defenser == &NoCard)
|
|
{
|
|
if (card->defenser)
|
|
match = NULL;
|
|
}
|
|
else if (defenser == &AnyCard)
|
|
{
|
|
if (!card->defenser)
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
// we don't care about the attack/blocker state
|
|
}
|
|
}
|
|
|
|
//Counters
|
|
if (anyCounter)
|
|
{
|
|
if (!(card->counters->mCount))
|
|
{
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
int hasCounter = 0;
|
|
for (int i = 0; i < card->counters->mCount; i++)
|
|
{
|
|
if (card->counters->counters[i]->nb > 0)
|
|
hasCounter = 1;
|
|
}
|
|
if (!hasCounter)
|
|
match = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (counterComparisonMode)
|
|
{
|
|
Counter * targetCounter = card->counters->hasCounter(counterName.c_str(), counterPower, counterToughness);
|
|
if (targetCounter)
|
|
{
|
|
if (!valueInRange(counterComparisonMode, targetCounter->nb, counterNB))
|
|
match = NULL;
|
|
}
|
|
else
|
|
{
|
|
if (counterComparisonMode != COMPARISON_LESS && counterComparisonMode != COMPARISON_AT_MOST)
|
|
match = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
return match;
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::match(MTGGameZone * zone)
|
|
{
|
|
return (nextmatch(zone, NULL));
|
|
}
|
|
|
|
MTGCardInstance * CardDescriptor::nextmatch(MTGGameZone * zone, MTGCardInstance * previous)
|
|
{
|
|
int found = 0;
|
|
if (NULL == previous)
|
|
found = 1;
|
|
for (int i = 0; i < zone->nb_cards; i++)
|
|
{
|
|
if (found && match(zone->cards[i]))
|
|
{
|
|
return zone->cards[i];
|
|
}
|
|
if (zone->cards[i] == previous)
|
|
{
|
|
found = 1;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|