- Removed "isClone" flag. This flag was error prone. The "core" classes now have decent copy constructors, and ideally long term we should create copy constructors for the abilities that have additional pointers in them.

-- The test suite passes but this is a big change. I might have introduced some memory leaks or bugs. I might have fixed some bugs, too
This commit is contained in:
wagic.the.homebrew
2011-07-27 14:31:27 +00:00
parent a26125ee4c
commit ef5e011e23
14 changed files with 520 additions and 610 deletions

View File

@@ -858,7 +858,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
AManaProducer * amp = dynamic_cast<AManaProducer*> (a);
if (amp)
{
amp->cost = cost;
amp->setCost(cost);
if (cost && card->typeAsTarget() == TARGET_CARD)
cost->setExtraCostsAction(a, card);
amp->oneShot = 0;
@@ -873,7 +873,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG
AEquip *ae = dynamic_cast<AEquip*> (a);
if (ae)
{
ae->cost = cost;
ae->setCost(cost);
if (!tc)
{
TargetChooserFactory tcf;
@@ -3302,6 +3302,42 @@ MTGAbility * AbilityFactory::getManaReduxAbility(string s, int id, Spell *spell,
return NEW AAlterCost(id, card, target, amount, color);
}
MTGAbility::MTGAbility(const MTGAbility& a): ActionElement(a)
{
//Todo get rid of menuText, it is only used as a placeholder in getMenuText, for something that could be a string
for (int i = 0; i < 50; ++i)
{
menuText[i] = a.menuText[i];
}
game = a.game;
oneShot = a.oneShot;
forceDestroy = a.forceDestroy;
forcedAlive = a.forcedAlive;
canBeInterrupted = a.canBeInterrupted;
//costs get copied, and will be deleted in the destructor
mCost = a.mCost ? NEW ManaCost(a.mCost) : NULL;
//alternative costs are not deleted in the destructor...who deletes them???
alternative = a.alternative; // ? NEW ManaCost(a.alternative) : NULL;
BuyBack = a.BuyBack; //? NEW ManaCost(a.BuyBack) : NULL;
FlashBack = a.FlashBack; // ? NEW ManaCost(a.FlashBack) : NULL;
Retrace = a.Retrace;// ? NEW ManaCost(a.Retrace) : NULL;
morph = a.morph; //? NEW ManaCost(a.morph) : NULL;
suspend = a.suspend;// ? NEW ManaCost(a.suspend) : NULL;
//Those two are pointers, but we don't delete them in the destructor, no need to copy them
target = a.target;
source = a.source;
aType = a.aType;
naType = a.naType;
abilitygranted = a.abilitygranted;
};
MTGAbility::MTGAbility(int id, MTGCardInstance * card) :
ActionElement(id)
{
@@ -3309,7 +3345,7 @@ MTGAbility::MTGAbility(int id, MTGCardInstance * card) :
source = card;
target = card;
aType = MTGAbility::UNKNOWN;
cost = NULL;
mCost = NULL;
forceDestroy = 0;
oneShot = 0;
canBeInterrupted = true;
@@ -3322,12 +3358,22 @@ MTGAbility::MTGAbility(int id, MTGCardInstance * _source, Targetable * _target)
source = _source;
target = _target;
aType = MTGAbility::UNKNOWN;
cost = NULL;
mCost = NULL;
forceDestroy = 0;
oneShot = 0;
canBeInterrupted = true;
}
void MTGAbility::setCost(ManaCost * cost, bool forceDelete)
{
if (mCost) {
DebugTrace("WARNING: Mtgability.cpp, attempt to set cost when previous cost is not null");
if (forceDelete)
delete(mCost);
}
mCost = cost;
}
int MTGAbility::stillInUse(MTGCardInstance * card)
{
if (card == source || card == target)
@@ -3337,10 +3383,7 @@ int MTGAbility::stillInUse(MTGCardInstance * card)
MTGAbility::~MTGAbility()
{
if (!isClone)
{
SAFE_DELETE(cost);
}
SAFE_DELETE(mCost);
}
int MTGAbility::addToGame()
@@ -3392,7 +3435,7 @@ int MTGAbility::fireAbility()
ostream& MTGAbility::toString(ostream& out) const
{
return out << "MTGAbility ::: menuText : " << menuText << " ; game : " << game << " ; forceDestroy : " << forceDestroy
<< " ; cost : " << cost << " ; target : " << target << " ; aType : " << aType << " ; source : " << source;
<< " ; mCost : " << mCost << " ; target : " << target << " ; aType : " << aType << " ; source : " << source;
}
NestedAbility::NestedAbility(MTGAbility * _ability)
@@ -3406,7 +3449,7 @@ ActivatedAbility::ActivatedAbility(int id, MTGCardInstance * card, ManaCost * _c
MTGAbility(id, card), restrictions(restrictions), needsTapping(0),limit(limit),sideEffect(sideEffect),usesBeforeSideEffects(usesBeforeSideEffects)
{
counters = 0;
cost = _cost;
setCost(_cost);
abilityCost = 0;
sa = NULL;
}
@@ -3473,6 +3516,7 @@ int ActivatedAbility::isReactingToClick(MTGCardInstance * card, ManaCost * mana)
if (card == source && source->controller() == player && (!needsTapping || (!source->isTapped()
&& !source->hasSummoningSickness())))
{
ManaCost * cost = getCost();
if (!cost)
return 1;
cost->setExtraCostsAction(this, card);
@@ -3492,6 +3536,7 @@ int ActivatedAbility::reactToClick(MTGCardInstance * card)
if (!isReactingToClick(card))
return 0;
Player * player = game->currentlyActing();
ManaCost * cost = getCost();
if (cost)
{
if (!cost->isExtraPaymentSet())
@@ -3514,6 +3559,7 @@ int ActivatedAbility::reactToTargetClick(Targetable * object)
if (!isReactingToTargetClick(object))
return 0;
Player * player = game->currentlyActing();
ManaCost * cost = getCost();
if (cost)
{
if (object->typeAsTarget() == TARGET_CARD)
@@ -3542,6 +3588,7 @@ int ActivatedAbility::activateAbility()
fmp = af.getCoreAbility(this);
AManaProducer * amp = dynamic_cast<AManaProducer *> (this);
AManaProducer * femp = dynamic_cast<AManaProducer *> (fmp);
ManaCost * cost = getCost();
if((amp||femp) && cost && cost->extraCosts)
{
for(unsigned int i = 0; i < cost->extraCosts->costs.size();i++)
@@ -3612,14 +3659,9 @@ void ActivatedAbility::activateSideEffect()
ActivatedAbility::~ActivatedAbility()
{
//Ok, this will probably lead to crashes, maybe with lord abilities involving "X" costs.
// If that's the case, we need to improve the clone() method of GenericActivatedAbility and GenericTargetAbility, I think
// Erwan 2004/04/25
//if (!isClone){
SAFE_DELETE(abilityCost);
SAFE_DELETE(sideEffect);
SAFE_DELETE(sa);
//}
}
ostream& ActivatedAbility::toString(ostream& out) const
@@ -3663,6 +3705,7 @@ int TargetAbility::reactToClick(MTGCardInstance * card)
{
if (isReactingToClick(card))
{
ManaCost * cost = getCost();
if (cost && !cost->isExtraPaymentSet())
{
game->mExtraPayment = cost->extraCosts;
@@ -3716,9 +3759,14 @@ int TargetAbility::resolve()
Targetable * t = tc->getNextTarget();
if (t && ability)
{
ManaCost * diff = abilityCost->Diff(cost);
source->X = diff->hasX();
delete (diff);
source->X = 0;
if (abilityCost)
{
ManaCost * diff = abilityCost->Diff(getCost());
source->X = diff->hasX();
delete (diff);
}
ability->target = t;
//do nothing if the target controller responded by phasing out the target.
if (t->typeAsTarget() == TARGET_CARD && ((MTGCardInstance*)t)->isPhased)
@@ -3740,8 +3788,7 @@ const char * TargetAbility::getMenuText()
TargetAbility::~TargetAbility()
{
if (!isClone)
SAFE_DELETE(ability);
SAFE_DELETE(ability);
}
ostream& TargetAbility::toString(ostream& out) const
@@ -4009,9 +4056,7 @@ TriggerAtPhase::TriggerAtPhase(int id, MTGCardInstance * source, Targetable * ta
TriggerAtPhase* TriggerAtPhase::clone() const
{
TriggerAtPhase * a = NEW TriggerAtPhase(*this);
a->isClone = 1;
return a;
return NEW TriggerAtPhase(*this);
}
TriggerNextPhase::TriggerNextPhase(int id, MTGCardInstance * source, Targetable * target, int _phaseId, int who,bool sourceUntapped, bool sourceTap,bool once) :
@@ -4036,9 +4081,7 @@ int TriggerNextPhase::testDestroy()
TriggerNextPhase* TriggerNextPhase::clone() const
{
TriggerNextPhase * a = NEW TriggerNextPhase(*this);
a->isClone = 1;
return a;
return NEW TriggerNextPhase(*this);
}
GenericTriggeredAbility::GenericTriggeredAbility(int id, MTGCardInstance * _source, TriggeredAbility * _t, MTGAbility * a,
@@ -4156,12 +4199,9 @@ int GenericTriggeredAbility::testDestroy()
GenericTriggeredAbility::~GenericTriggeredAbility()
{
if (!isClone)
{
delete t;
delete ability;
SAFE_DELETE(destroyCondition);
}
delete t;
delete ability;
SAFE_DELETE(destroyCondition);
}
const char * GenericTriggeredAbility::getMenuText()
@@ -4171,8 +4211,10 @@ const char * GenericTriggeredAbility::getMenuText()
GenericTriggeredAbility* GenericTriggeredAbility::clone() const
{
GenericTriggeredAbility * a = NEW GenericTriggeredAbility(*this);
a->isClone = 1;
GenericTriggeredAbility * a = NEW GenericTriggeredAbility(*this);
a->t = t->clone();
a->ability = ability->clone();
a->destroyCondition = destroyCondition->clone();
return a;
}
@@ -4188,7 +4230,7 @@ AManaProducer::AManaProducer(int id, MTGCardInstance * card, Targetable * t, Man
{
aType = MTGAbility::MANA_PRODUCER;
cost = _cost;
setCost(_cost);
output = _output;
menutext = "";
@@ -4202,6 +4244,7 @@ int AManaProducer::isReactingToClick(MTGCardInstance * _card, ManaCost * mana)
if (_card == source && (!tap || !source->isTapped()) && game->currentlyActing()->game->inPlay->hasCard(source)
&& (source->hasType(Subtypes::TYPE_LAND) || !tap || !source->hasSummoningSickness()) && !source->isPhased)
{
ManaCost * cost = getCost();
if (!cost || mana->canAfford(cost))
{
result = 1;
@@ -4236,6 +4279,8 @@ int AManaProducer::reactToClick(MTGCardInstance * _card)
return 0;
if(!ActivatedAbility::isReactingToClick(_card))
return 0;
ManaCost * cost = getCost();
if (cost)
{
cost->setExtraCostsAction(this, _card);
@@ -4302,18 +4347,14 @@ const char * AManaProducer::getMenuText()
AManaProducer::~AManaProducer()
{
SAFE_DELETE(cost);
SAFE_DELETE(output);
}
AManaProducer * AManaProducer::clone() const
{
AManaProducer * a = NEW AManaProducer(*this);
a->cost = NEW ManaCost();
a->output = NEW ManaCost();
a->cost->copy(cost);
a->output->copy(output);
a->isClone = 1;
return a;
}