Performance improvements/cleanup: card->hasType("foo") performs a string lookup for an integer id. Now that our primitives have over 1000 types (1018, I believe is the number I saw while debugging), this is not the cheapest lookup. Over the course of time, a lot of new rules have crept in the code - support for 'aura', 'equipment', and recently 'planeswalker'. While profiling, I saw an inordinate amount of time being used doing map lookups for these strings. Since they're used so frequently, I've added them to the SubTypes enumeration, and swapped out doing the string lookup in favour of using the int ID directly. I also found a few places where we were using hasType("Creature") or hasType("land") when we already had helper functions to do the int lookup, so I swapped these in as appropriate, as well as a couple of places where we had hasType("instant") instead of hasType(Subtypes::TYPE_INSTANT), etc.

This commit is contained in:
wrenczes@gmail.com
2011-04-10 00:07:34 +00:00
parent 62da8e7ad8
commit 99ed83c5e8
12 changed files with 67 additions and 61 deletions
+4 -3
View File
@@ -15,6 +15,7 @@
#include "WEvent.h"
#include "GuiStatic.h"
#include "GameObserver.h"
#include "Subtypes.h"
#include "ThisDescriptor.h"
#include <JGui.h>
#include <hge/hgeparticle.h>
@@ -130,7 +131,7 @@ public:
intValue = 0;
intValue = target->thatmuch;
int checkagain = 0;
if(target->hasSubtype("aura") || target->hasSubtype("equipment"))
if(target->hasSubtype(Subtypes::TYPE_AURA) || target->hasSubtype(Subtypes::TYPE_EQUIPMENT))
{
if(target->target)
{
@@ -2727,7 +2728,7 @@ public:
{
if(card->isPhased || source->isPhased)
return 0;
if ((tc->source->hasSubtype("aura") || tc->source->hasSubtype("equipment") || tc->source->hasSubtype("instant")
if ((tc->source->hasSubtype(Subtypes::TYPE_AURA) || tc->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || tc->source->hasSubtype("instant")
|| tc->source->hasSubtype("sorcery")) && tc->canTarget(card) && card == tc->source->target && card != tc->source) return 1;
return 0;
}
@@ -2759,7 +2760,7 @@ public:
{
MTGAbility * a = ability->clone();
if (a->source->hasSubtype("aura") || a->source->hasSubtype("equipment") || a->source->hasSubtype("instant")
if (a->source->hasSubtype(Subtypes::TYPE_AURA) || a->source->hasSubtype(Subtypes::TYPE_EQUIPMENT) || a->source->hasSubtype("instant")
|| a->source->hasSubtype("sorcery"))
{
a->target = a->source->target;
+4 -2
View File
@@ -19,7 +19,10 @@ public:
TYPE_LAND = 5,
TYPE_ARTIFACT = 6,
TYPE_LEGENDARY = 7,
LAST_TYPE = TYPE_LEGENDARY,
TYPE_EQUIPMENT = 8,
TYPE_AURA = 9,
TYPE_PLANESWALKER = 10,
LAST_TYPE = TYPE_PLANESWALKER,
};
protected:
@@ -28,7 +31,6 @@ protected:
public:
static Subtypes * subtypesList;
Subtypes();
int find(const char * subtype, bool forceAdd = true);
int find(string subtype, bool forceAdd = true);
string find(unsigned int id);
};
+1 -1
View File
@@ -427,7 +427,7 @@ int AIAction::getEfficiency()
{
MTGCardInstance * _target = (MTGCardInstance *) (a->target);
//nothing huge here, just ensuring that Ai makes his noncreature becomers into creatures during first main, so it can actually use them in combat.
if (_target && !_target->hasType("Creature") && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN)
if (_target && !_target->isCreature() && g->getCurrentGamePhase() == Constants::MTG_PHASE_FIRSTMAIN)
{
efficiency = 100;
}
+2 -1
View File
@@ -11,6 +11,7 @@ The Action Stack contains all information for Game Events that can be interrupte
#include "GameOptions.h"
#include "ManaCost.h"
#include "MTGAbility.h"
#include "Subtypes.h"
#include "TargetChooser.h"
#include "Translate.h"
#include "WResourceManager.h"
@@ -289,7 +290,7 @@ Spell::~Spell()
int Spell::resolve()
{
GameObserver * game = GameObserver::GetInstance();
if (!source->hasType("instant") && !source->hasType("sorcery"))
if (!source->hasType(Subtypes::TYPE_INSTANT) && !source->hasType(Subtypes::TYPE_SORCERY))
{
Player * p = source->controller();
int castMethod = source->castMethod;
+5 -5
View File
@@ -767,12 +767,12 @@ int AANewTarget::resolve()
MTGCardInstance * refreshed = source->controller()->game->putInZone(_target,_target->currentZone,source->controller()->game->battlefield);
Spell * reUp = NEW Spell(refreshed);
if(reUp->source->hasSubtype("aura"))
if(reUp->source->hasSubtype(Subtypes::TYPE_AURA))
{
reUp->source->target = source;
reUp->resolve();
}
if(_target->hasSubtype("equipment"))
if(_target->hasSubtype(Subtypes::TYPE_EQUIPMENT))
{
reUp->resolve();
GameObserver * g = g->GetInstance();
@@ -3189,7 +3189,7 @@ void ABlink::Update(float dt)
}
Spell * spell = NEW Spell(Blinker);
spell->source->counters->init();
if(spell->source->hasSubtype("aura") && !blinkhand)
if(spell->source->hasSubtype(Subtypes::TYPE_AURA) && !blinkhand)
{
TargetChooserFactory tcf;
TargetChooser * tc = tcf.createTargetChooser(spell->source->spellTargetType,spell->source);
@@ -3223,7 +3223,7 @@ void ABlink::Update(float dt)
}
spell->source->power = spell->source->origpower;
spell->source->toughness = spell->source->origtoughness;
if(!spell->source->hasSubtype("aura"))
if(!spell->source->hasSubtype(Subtypes::TYPE_AURA))
{
spell->resolve();
if(stored)
@@ -3288,7 +3288,7 @@ void ABlink::resolveBlink()
}
Spell * spell = NEW Spell(Blinker);
spell->source->counters->init();
if(spell->source->hasSubtype("aura") && !blinkhand)
if(spell->source->hasSubtype(Subtypes::TYPE_AURA) && !blinkhand)
{
TargetChooserFactory tcf;
TargetChooser * tc = tcf.createTargetChooser(spell->source->spellTargetType,spell->source);
+7 -7
View File
@@ -6,6 +6,7 @@
#include "Damage.h"
#include "Rules.h"
#include "ExtraCost.h"
#include "Subtypes.h"
#include <JLogger.h>
#include <JRenderer.h>
@@ -13,7 +14,6 @@ GameObserver * GameObserver::mInstance = NULL;
GameObserver* GameObserver::GetInstance()
{
return mInstance;
}
@@ -296,7 +296,7 @@ void GameObserver::startGame(Rules * rules)
for (int j = 0; j < z->nb_cards; j++)
{
MTGCardInstance * _card = z->cards[j];
if (_card->hasType("land"))
if (_card->isLand())
{
card = _card;
j = z->nb_cards;
@@ -403,12 +403,12 @@ void GameObserver::gameStateBasedEffects()
///////////////////////////////////////////////////////
//Remove auras that don't have a valid target anymore//
///////////////////////////////////////////////////////
if (card->target && !isInPlay(card->target) && !card->hasType("equipment"))
if (card->target && !isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT))
{
players[i]->game->putInGraveyard(card);
}
card->enchanted = false;
if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura"))
if (card->target && isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT) && card->hasSubtype(Subtypes::TYPE_AURA))
{
card->target->enchanted = true;
}
@@ -455,7 +455,7 @@ void GameObserver::gameStateBasedEffects()
if(card->view)
card->view->alpha = 255;
}
if (card->target && isInPlay(card->target) && (card->hasSubtype("equipment") || card->hasSubtype("aura")))
if (card->target && isInPlay(card->target) && (card->hasSubtype(Subtypes::TYPE_EQUIPMENT) || card->hasSubtype(Subtypes::TYPE_AURA)))
{
card->isPhased = card->target->isPhased;
card->phasedTurn = card->target->phasedTurn;
@@ -681,7 +681,7 @@ void GameObserver::enchantmentStatus()
for (int k = zone->nb_cards - 1; k >= 0; k--)
{
MTGCardInstance * card = zone->cards[k];
if (card && !card->hasType("equipment") && !card->hasSubtype("aura"))
if (card && !card->hasType(Subtypes::TYPE_EQUIPMENT) && !card->hasSubtype(Subtypes::TYPE_AURA))
{
card->enchanted = false;
card->auras = 0;
@@ -690,7 +690,7 @@ void GameObserver::enchantmentStatus()
for (int j = zone->nb_cards - 1; j >= 0; j--)
{
MTGCardInstance * card = zone->cards[j];
if (card->target && isInPlay(card->target) && !card->hasType("equipment") && card->hasSubtype("aura"))
if (card->target && isInPlay(card->target) && !card->hasType(Subtypes::TYPE_EQUIPMENT) && card->hasSubtype(Subtypes::TYPE_AURA))
{
card->target->enchanted = true;
card->target->auras += 1;
+8 -6
View File
@@ -3,6 +3,7 @@
#include "CardSelectorSingleton.h"
#include "GameApp.h"
#include "GuiPlay.h"
#include "Subtypes.h"
#include "Trash.h"
#define CARD_WIDTH (31)
@@ -10,6 +11,7 @@
const float GuiPlay::HORZWIDTH = 300.0f;
const float GuiPlay::VERTHEIGHT = 80.0f;
void GuiPlay::CardStack::reset(unsigned total, float x, float y)
{
this->total = total;
@@ -177,7 +179,7 @@ GuiPlay::~GuiPlay()
bool isSpell(CardView* c)
{
return c->card->isSpell() && !c->card->isCreature() && !c->card->hasType("Planeswalker");
return c->card->isSpell() && !c->card->isCreature() && !c->card->hasType(Subtypes::TYPE_PLANESWALKER);
}
void GuiPlay::Replace()
{
@@ -189,7 +191,7 @@ void GuiPlay::Replace()
for (iterator it = cards.begin(); it != end_spells; ++it)
if (!(*it)->card->target)
{
if(!(*it)->card->hasSubtype("aura") && !(*it)->card->hasType("Planeswalker"))
if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
{
if (game->players[0] == (*it)->card->controller())
++selfSpellsN;
@@ -210,7 +212,7 @@ void GuiPlay::Replace()
else
++opponentCreaturesN;
}
else if ((*it)->card->isLand() || (*it)->card->hasType("Planeswalker"))
else if ((*it)->card->isLand() || (*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
{
if (game->players[0] == (*it)->card->controller())
++selfLandsN;
@@ -225,7 +227,7 @@ void GuiPlay::Replace()
for (iterator it = cards.begin(); it != end_spells; ++it)
if (!(*it)->card->target)
{
if(!(*it)->card->hasSubtype("aura") && !(*it)->card->hasType("Planeswalker"))
if(!(*it)->card->hasSubtype(Subtypes::TYPE_AURA) && !(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
{
if (game->players[0] == (*it)->card->controller())
selfSpells.Enstack(*it);
@@ -268,7 +270,7 @@ void GuiPlay::Replace()
//rerun the iter reattaching planes walkers to the back of the lands.
for (iterator it = end_spells; it != cards.end(); ++it)
{
if ((*it)->card->hasType("Planeswalker"))
if ((*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
{
if (game->players[0] == (*it)->card->controller())
selfLands.Enstack(*it);
@@ -297,7 +299,7 @@ void GuiPlay::Render()
else
opponentCreatures.Render(*it, cards.begin(), end_spells);
}
else if(!(*it)->card->hasType("Planeswalker"))
else if(!(*it)->card->hasType(Subtypes::TYPE_PLANESWALKER))
{
if (!(*it)->card->target)
{
+12 -12
View File
@@ -1214,7 +1214,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
oneShot = 1;
if (activated)
oneShot = 1;
if (card->hasType("sorcery") || card->hasType("instant"))
if (card->hasType(Subtypes::TYPE_SORCERY) || card->hasType(Subtypes::TYPE_INSTANT))
oneShot = 1;
if (a->oneShot)
oneShot = 1;
@@ -1304,7 +1304,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
oneShot = 1;
if (a->oneShot)
oneShot = 1;
if (card->hasType("sorcery") || card->hasType("instant"))
if (card->hasType(Subtypes::TYPE_SORCERY) || card->hasType(Subtypes::TYPE_INSTANT))
oneShot = 1;
found = s.find("while ");
if (found != string::npos)
@@ -1868,7 +1868,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
//hack for http://code.google.com/p/wagic/issues/detail?id=120
//We assume that auras don't move their own target...
if (card->hasType("aura"))
if (card->hasType(Subtypes::TYPE_AURA))
target = card;
MTGAbility * a = NEW AAMover(id, card, target, szone);
@@ -2300,7 +2300,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
t = spell->getNextTarget();
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NEW AInstantCastRestrictionUEOT(id, card, t, castTargets, value, modifyExisting, kMaxCastZones[i], who);
}
@@ -2608,7 +2608,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
{
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NEW AInstantPowerToughnessModifierUntilEOT(id, card, target, wppt);
}
@@ -2647,7 +2647,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
fromTc->setAllZones();
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NULL; //TODO
}
@@ -2668,7 +2668,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
fromTc->setAllZones();
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NULL; //TODO
}
@@ -2690,7 +2690,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
//default target zone to opponentbattlefield here?
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NULL; //TODO
}
@@ -2797,7 +2797,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
}
if (!activated)
{
if (card->hasType("instant") || card->hasType("sorcery") || forceUEOT)
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY) || forceUEOT)
{
return NEW AInstantBasicAbilityModifierUntilEOT(id, card, target, j, modifier);
}
@@ -3073,7 +3073,7 @@ int AbilityFactory::getAbilities(vector<MTGAbility *> * v, Spell * spell, MTGCar
magicText.append(faceupC);
}
else if(card && card->hasType("equipment") && card->target)
else if(card && card->hasType(Subtypes::TYPE_EQUIPMENT) && card->target)
{
magicText = card->model->data->magicText;
string equipText = card->magicTexts["skill"];
@@ -3451,7 +3451,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
for (int j = inplay->nb_cards - 1; j >= 0; j--)
{
MTGCardInstance * card = inplay->cards[j];
if (card->owner == player && card->hasType("artifact"))
if (card->owner == player && card->hasType(Subtypes::TYPE_ARTIFACT))
{
player->game->putInZone(card, inplay, player->game->hand);
}
@@ -3780,7 +3780,7 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
if(card->previous && card->previous->previous && card->previous->previous->suspended)
card->basicAbilities[Constants::HASTE] = 1;
if (card->hasType("instant") || card->hasType("sorcery"))
if (card->hasType(Subtypes::TYPE_INSTANT) || card->hasType(Subtypes::TYPE_SORCERY))
{
MTGPlayerCards * zones = card->controller()->game;
if (card->alternateCostPaid[ManaCost::MANA_PAID_WITH_BUYBACK] > 0)
+12 -9
View File
@@ -5,6 +5,7 @@
#include "GameOptions.h"
#include "WEvent.h"
#include "MTGDeck.h"
#include "Subtypes.h"
#if defined (WIN32) || defined (LINUX)
#include <time.h>
@@ -133,7 +134,7 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat
{
MTGCardInstance * _card = z->cards[j];
//-------------
if (_card->hasType("Land") && optimizedland < lands)
if (_card->isLand() && optimizedland < lands)
{
card = _card;
if (card)
@@ -143,8 +144,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat
}
}
//----------------first try to optimize a few cards that cost 2 or less.
if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->hasType("Land")
&& !_card->hasType("Creature"))
if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedothercards < othercards && !_card->isLand()
&& !_card->isCreature())
{
card = _card;
if (card)
@@ -153,7 +154,7 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat
optimizedothercards += 1;
}
}
if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->hasType("Creature"))
if (_card->getManaCost()->getConvertedCost() <= 2 && optimizedcreatures < creatures && _card->isCreature())
{
card = _card;
if (card)
@@ -168,8 +169,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat
{
MTGCardInstance * _card = z->cards[k];
if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->hasType("Land")
|| _card->hasType("Creature")))
if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedothercards < othercards && (!_card->isLand()
|| _card->isCreature()))
{
card = _card;
if (card)
@@ -178,8 +179,8 @@ void MTGPlayerCards::OptimizedHand(Player * who,int amount, int lands, int creat
optimizedothercards += 1;
}
}
if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->hasType("Creature")
|| !_card->hasType("Land")))
if (_card->getManaCost()->getConvertedCost() <= 3 && optimizedcreatures < creatures && (_card->isCreature()
|| !_card->isLand()))
{
card = _card;
if (card)
@@ -478,15 +479,17 @@ MTGCardInstance * MTGGameZone::hasCard(MTGCardInstance * card)
int MTGGameZone::countByType(const char * value)
{
int result = 0;
int subTypeId = Subtypes::subtypesList->find(value);
for (int i = 0; i < (nb_cards); i++)
{
if (cards[i]->hasType(value))
if (cards[i]->hasType(subTypeId))
{
result++;
}
}
return result;
}
int MTGGameZone::countByCanTarget(TargetChooser * tc)
{
if(!tc)
+8 -8
View File
@@ -38,7 +38,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
if(!allowedToCast(card,player))
return 0;
if (card->hasType("land"))
if (card->isLand())
{
if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->inPlay) == PlayRestriction::CANT_PLAY)
return 0;
@@ -49,7 +49,7 @@ int MTGPutInPlayRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
return 1;
}
}
else if ((card->hasType("instant")) || card->has(Constants::FLASH)
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH)
|| (player == currentPlayer && !game->isInterrupting
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
@@ -127,7 +127,7 @@ int MTGPutInPlayRule::reactToClick(MTGCardInstance * card)
ManaCost * spellCost = previousManaPool->Diff(player->getManaPool());
delete previousManaPool;
if (card->hasType("land"))
if (card->isLand())
{
MTGCardInstance * copy = player->game->putInZone(card, player->game->hand, player->game->temp);
Spell * spell = NEW Spell(0,copy,NULL,NULL, payResult);
@@ -224,7 +224,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
if(!allowedToAltCast(card,player))
return 0;
if (card->hasType("land"))
if (card->isLand())
{
if (currentPlayer->game->playRestrictions->canPutIntoZone(card, currentPlayer->game->inPlay) == PlayRestriction::CANT_PLAY)
return 0;
@@ -234,7 +234,7 @@ int MTGAlternativeCostRule::isReactingToClick(MTGCardInstance * card, ManaCost *
)
return 1;
}
else if ((card->hasType("instant")) || card->has(Constants::FLASH)
else if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH)
|| (player == currentPlayer && !game->isInterrupting
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
@@ -295,7 +295,7 @@ int MTGAlternativeCostRule::reactToClick(MTGCardInstance * card, ManaCost *alter
card->alternateCostPaid[alternateCostType] = 1;
if (card->hasType("land"))
if (card->isLand())
{
MTGCardInstance * copy = player->game->putInZone(card, card->currentZone, player->game->temp);
Spell * spell = NEW Spell(0,copy,NULL,NULL, alternateCostType);
@@ -642,7 +642,7 @@ int MTGMorphCostRule::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
if(!allowedToAltCast(card,player))
return 0;
//note lands can morph too, this is different from other cost types.
if ((card->hasType("instant")) || card->has(Constants::FLASH) || (player == currentPlayer
if ((card->hasType(Subtypes::TYPE_INSTANT)) || card->has(Constants::FLASH) || (player == currentPlayer
&& !game->isInterrupting
&& (game->currentGamePhase == Constants::MTG_PHASE_FIRSTMAIN
|| game->currentGamePhase == Constants::MTG_PHASE_SECONDMAIN))
@@ -1571,7 +1571,7 @@ int MTGPlaneWalkerRule::canBeInList(MTGCardInstance * card)
{
if(card->isPhased)
return 0;
if (card->hasType("Planeswalker") && game->isInPlay(card))
if (card->hasType(Subtypes::TYPE_PLANESWALKER) && game->isInPlay(card))
{
return 1;
}
+3 -6
View File
@@ -15,6 +15,9 @@ Subtypes::Subtypes()
find("Land");
find("Artifact");
find("Legendary");
find("Equipment");
find("Aura");
find("Planeswalker");
}
int Subtypes::find(string value, bool forceAdd)
@@ -29,12 +32,6 @@ int Subtypes::find(string value, bool forceAdd)
return id;
}
int Subtypes::find(const char * subtype, bool forceAdd)
{
string value = subtype;
return find(value, forceAdd);
}
string Subtypes::find(unsigned int id)
{
if (valuesById.size() < id || !id) return "";
+1 -1
View File
@@ -754,7 +754,7 @@ bool TargetChooser::canTarget(Targetable * target,bool withoutProtections)
tempcard = tempcard->previous;
}
}
if(source && ((source->hasSubtype("aura") || source->hasSubtype("equipment")) && source->target && source->target == card && source->target->isPhased && targetter->target == card))
if(source && ((source->hasSubtype(Subtypes::TYPE_AURA) || source->hasSubtype(Subtypes::TYPE_EQUIPMENT)) && source->target && source->target == card && source->target->isPhased && targetter->target == card))
return true;
//this is kinda cheating but by default we let auras and equipments always continue to target a phased creature.
else if(card->isPhased)