fix for crash from not having a playerTarget when ability$! is used on targetedPlayer by an instant.

This commit is contained in:
omegablast2002@yahoo.com
2013-01-30 03:51:16 +00:00
parent d07951fbdf
commit c078af5f24
5 changed files with 128 additions and 0 deletions

View File

@@ -1077,6 +1077,33 @@ public:
~IfThenAbility();
};
//MayPayAbility: May do ...
class MayPayAbility: public MTGAbility, public NestedAbility
{
public:
int triggered;
bool must;
string Cond;
Player * previousInterrupter;
MTGAbility * mClone;
ManaCost * optionalCost;
MayPayAbility(GameObserver* observer, int _id, MTGAbility * _ability, MTGCardInstance * _source, bool must = false, string restriction = "");
void Update(float dt);
const char * getMenuText();
int testDestroy();
int isReactingToTargetClick(Targetable * card);
int reactToTargetClick(Targetable * object);
MayPayAbility * clone() const;
~MayPayAbility();
};
//MayAbility: May do ...
class MayAbility: public MTGAbility, public NestedAbility
{

View File

@@ -302,10 +302,12 @@ Spell::~Spell()
int Spell::resolve()
{
MTGCardInstance * oldStored = source->storedCard;
Player * playerT = source->playerTarget;
if (!source->hasType(Subtypes::TYPE_INSTANT) && !source->hasType(Subtypes::TYPE_SORCERY) && source->name.size())
{
Player * p = source->controller();
int castMethod = source->castMethod;
Player * playerT = source->playerTarget;
vector<Targetable*>backupTgt = source->backupTargets;
source = p->game->putInZone(source, from, p->game->battlefield);
@@ -315,6 +317,7 @@ int Spell::resolve()
source->backupTargets = backupTgt;
from = p->game->battlefield;
}
source->playerTarget = playerT;
source->storedCard = oldStored;
//Play SFX
if (options[Options::SFXVOLUME].number > 0)

View File

@@ -3095,6 +3095,100 @@ IfThenAbility::~IfThenAbility()
SAFE_DELETE(delayedElseAbility);
}
//
//May Abilities
MayPayAbility::MayPayAbility(GameObserver* observer, int _id, MTGAbility * _ability, MTGCardInstance * _source, bool must,string _cond) :
MTGAbility(observer, _id, _source), NestedAbility(_ability), must(must), Cond(_cond)
{
triggered = 0;
mClone = NULL;
optionalCost = NULL;
}
void MayPayAbility::Update(float dt)
{
MTGAbility::Update(dt);
if (!triggered && !game->getCurrentTargetChooser() && (!game->mLayers->actionLayer()->menuObject||game->mLayers->actionLayer()->menuObject == source))
{
triggered = 1;
if(optionalCost && !source->controller()->getManaPool()->canAfford(optionalCost))
return;
if(Cond.size())
{
AbilityFactory af(game);
int checkCond = af.parseCastRestrictions(source,source->controller(),Cond);
if(!checkCond)
{
return;
}
}
if (TargetAbility * ta = dynamic_cast<TargetAbility *>(ability))
{
if (!ta->getActionTc()->validTargetsExist())
return;
}
game->mLayers->actionLayer()->setMenuObject(source, must);
previousInterrupter = game->isInterrupting;
game->mLayers->stackLayer()->setIsInterrupting(source->controller(), false);
}
}
const char * MayPayAbility::getMenuText()
{
return ability->getMenuText();
}
int MayPayAbility::testDestroy()
{
if (!triggered)
return 0;
if (game->mLayers->actionLayer()->menuObject)
return 0;
if (game->mLayers->actionLayer()->getIndexOf(mClone) != -1)
return 0;
if(game->currentPlayer == source->controller() && game->isInterrupting == source->controller() && dynamic_cast<AManaProducer*>(AbilityFactory::getCoreAbility(ability)))
//if its my turn, and im interrupting myself(why?) then set interrupting to previous interrupter if the ability was a manaability
//special case since they don't use the stack.
game->mLayers->stackLayer()->setIsInterrupting(previousInterrupter, false);
return 1;
}
int MayPayAbility::isReactingToTargetClick(Targetable * card)
{
if (card == source)
{
if(!optionalCost || source->controller()->getManaPool()->canAfford(optionalCost))
return 1;
}
return 0;
}
int MayPayAbility::reactToTargetClick(Targetable * object)
{
mClone = ability->clone();
if(optionalCost)
{
source->controller()->getManaPool()->pay(optionalCost);
optionalCost->setExtraCostsAction(this, source);
optionalCost->doPayExtra();
}
mClone->addToGame();
mClone->forceDestroy = 1;
return mClone->reactToTargetClick(object);
}
MayPayAbility * MayPayAbility::clone() const
{
MayPayAbility * a = NEW MayPayAbility(*this);
a->ability = ability->clone();
a->optionalCost = this->optionalCost;
return a;
}
MayPayAbility::~MayPayAbility()
{
SAFE_DELETE(ability);
SAFE_DELETE(optionalCost);
}
//May Abilities
MayAbility::MayAbility(GameObserver* observer, int _id, MTGAbility * _ability, MTGCardInstance * _source, bool must,string _cond) :

View File

@@ -1256,6 +1256,8 @@ int GameObserver::cardClick(MTGCardInstance * card, Targetable * object, bool lo
result = targetChooser->toggleTarget(clickedPlayer);
if(card)
card->playerTarget = clickedPlayer;
else
targetChooser->source->playerTarget = clickedPlayer;
}
if (result == TARGET_OK_FULL)
card = cardWaitingForTargets;

View File

@@ -3534,6 +3534,8 @@ void AbilityFactory::addAbilities(int _id, Spell * spell)
}
card->playerTarget = spell->getNextPlayerTarget();
}
if(!card->playerTarget && card->previous && card->previous->playerTarget)
card->playerTarget = card->previous->playerTarget;//instants seem to forget as they travel from zone to zone.
_id = magicText(_id, spell);
MTGPlayerCards * zones = card->controller()->game;