fixed a reported bug with @vampired, it was tricky, but ultimately i had to move the building of vampevent outside of TRVampired...the reason being that all instances of TRVamp were able to send and react to other instances of it sending out "vampevents", so move it into rules so only one object handles that, also changed the method it was handled, it now maps the cards with a 2nd vector of the vampires...basically "this card was dealt damage by X, Y, Z this turn"...

let me know if i missed some strange edge case somewhere. as far as i tested, it seems to work just fine.
This commit is contained in:
omegablast2002@yahoo.com
2011-04-29 13:24:02 +00:00
parent 95987c6d87
commit 0fba6994a6
6 changed files with 103 additions and 63 deletions
+1
View File
@@ -38,6 +38,7 @@ void DuelLayers::init()
action->Add(NEW MTGPlaneWalkerRule(-1));
action->Add(NEW MTGTokensCleanup(-1)); // needs to be before persist
action->Add(NEW MTGPersistRule(-1));
action->Add(NEW MTGVampireRule(-1));
action->Add(NEW MTGUnearthRule(-1));
action->Add(NEW MTGLifelinkRule(-1));
action->Add(NEW MTGDeathtouchRule(-1));
+1 -1
View File
@@ -713,7 +713,7 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string magicText, int
fromTc = tcf.createTargetChooser(starget, card);
fromTc->targetter = NULL;
}
return NEW TrVampired(id, card, tc, fromTc, 0);
return NEW TrVampired(id, card, tc, fromTc);
}
//when card becomes the target of a spell or ability
+77
View File
@@ -1819,6 +1819,83 @@ MTGPersistRule * MTGPersistRule::clone() const
return a;
}
//vampires rule
//handled seperately as a rule since we only want one object to send out events that a card was "vampired".
//otherwise vampire event is sent per instance of @vampired on the battlefield, multipling the results.
MTGVampireRule::MTGVampireRule(int _id) :
MTGAbility(_id, NULL)
{
}
;
int MTGVampireRule::receiveEvent(WEvent * event)
{
WEventDamage * e = dynamic_cast<WEventDamage *> (event);
WEventZoneChange * z = dynamic_cast<WEventZoneChange *> (event);
WEventPhaseChange * pe = dynamic_cast<WEventPhaseChange*>(event);
if (e)
{
if(!e->damage->damage)
return 0;
if (!e->damage->target)
return 0;
MTGCardInstance * newVictem = (MTGCardInstance*)(e->damage->target);
MTGCardInstance * vampire = (MTGCardInstance*)(e->damage->source);
victems[newVictem].push_back(vampire);
}
else if (z)
{
MTGCardInstance * card = z->card->previous;
if(card && victems[card].empty())
return 0;
std::sort(victems[card].begin(), victems[card].end());
victems[card].erase(std::unique(victems[card].begin(), victems[card].end()), victems[card].end());
//sort and remove duplicates, we only want one event of a vampire damaging a card stored per victem.
for(unsigned int w = 0;w < victems[card].size();w++)
{
if(victems[card].at(w) == NULL)
continue;
Player * p = card->controller();
if (z->from == p->game->inPlay && z->to == p->game->graveyard)
{
if(card == z->card->previous)
{
WEvent * e = NEW WEventVampire(card,victems[card].at(w),card);
game->receiveEvent(e);
}
}
}
return 0;
}
else if (pe)
{
if( pe->from->id == Constants::MTG_PHASE_ENDOFTURN)
{
victems.clear();
}
}
return 0;
}
ostream& MTGVampireRule::toString(ostream& out) const
{
out << "MTGVampireRule ::: (";
return MTGAbility::toString(out) << ")";
}
int MTGVampireRule::testDestroy()
{
return 0;
}
MTGVampireRule * MTGVampireRule::clone() const
{
MTGVampireRule * a = NEW MTGVampireRule(*this);
a->isClone = 1;
return a;
}
/////////////////////////////////////////////////
//unearth rule----------------------------------
//if the card leaves play, exile it instead.
MTGUnearthRule::MTGUnearthRule(int _id) :
+2 -2
View File
@@ -173,9 +173,9 @@ Targetable * WEventVampire::getTarget(int target)
switch (target)
{
case TARGET_TO:
return source->next;
return victem->next;
case TARGET_FROM:
return victem;
return source;
}
return NULL;
}