From 0fba6994a6904b31a0d796a17ac7262e594b28f2 Mon Sep 17 00:00:00 2001 From: "omegablast2002@yahoo.com" Date: Fri, 29 Apr 2011 13:24:02 +0000 Subject: [PATCH] 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. --- projects/mtg/include/AllAbilities.h | 71 +++++--------------------- projects/mtg/include/MTGRules.h | 11 +++++ projects/mtg/src/DuelLayers.cpp | 1 + projects/mtg/src/MTGAbility.cpp | 2 +- projects/mtg/src/MTGRules.cpp | 77 +++++++++++++++++++++++++++++ projects/mtg/src/WEvent.cpp | 4 +- 6 files changed, 103 insertions(+), 63 deletions(-) diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 89426fbb4..4ae33fe36 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -749,10 +749,8 @@ class TrVampired: public TriggeredAbility public: TargetChooser * tc; TargetChooser * fromTc; - vector victems; - int type; - TrVampired(int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0) : - TriggeredAbility(id, source), tc(tc), fromTc(fromTc), type(type) + TrVampired(int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL) : + TriggeredAbility(id, source), tc(tc), fromTc(fromTc) { } @@ -764,64 +762,17 @@ public: int triggerOnEvent(WEvent * event) { if(source->isPhased) return 0; - WEventDamage * e = dynamic_cast (event); - WEventZoneChange * z = dynamic_cast (event); - WEventPhaseChange * pe = dynamic_cast(event); WEventVampire * vamp = dynamic_cast(event); - if (e == event) + if (vamp) { - if (!tc->canTarget(e->damage->target)) return 0; - if (fromTc && !fromTc->canTarget(e->damage->source)) return 0; - - MTGCardInstance * newVictem = (MTGCardInstance*)(e->damage->target); - - victems.push_back(newVictem); - std::sort(victems.begin(), victems.end()); - victems.erase(std::unique(victems.begin(), victems.end()), victems.end()); - } - else if (z == event && !victems.empty()) - { - MTGCardInstance * card = z->card; - - - for(unsigned int k = 0;k < victems.size();k--) - { - if(victems[k] == NULL) - continue; - if(victems[k] != z->card->previous) - { - return 0; - } - } - for(unsigned int w = 0;w < victems.size();w++) - { - if(victems[w] == NULL) - continue; - Player * p = victems[w]->controller(); - if (z->from == p->game->inPlay && z->to == p->game->graveyard) - { - if(victems[w] == z->card->previous) - { - if(!source->isInPlay()) - return 0; - WEvent * e = NEW WEventVampire(victems[w],victems[w],source); - game->receiveEvent(e); - victems[w] = NULL; - return 0; - } - } - } - } - else if (vamp == event) - { - return 1; - } - else if (pe == event) - { - if( pe->from->id == Constants::MTG_PHASE_ENDOFTURN) - { - victems.clear(); - } + if(fromTc && !fromTc->canTarget(vamp->source)) + return 0; + tc->setAllZones(); + //creature that were "vampired" only happens in battlefield, and event sent when they hit a grave. + //setting allzones, as we don't care since we know the preexisting condiations cover the zones. + if(!tc->canTarget(vamp->victem)) + return 0; + return 1; } return 0; } diff --git a/projects/mtg/include/MTGRules.h b/projects/mtg/include/MTGRules.h index 7447a7a70..22059d5d7 100644 --- a/projects/mtg/include/MTGRules.h +++ b/projects/mtg/include/MTGRules.h @@ -253,6 +253,17 @@ public: int testDestroy(); virtual MTGPersistRule * clone() const; }; +/* vampire Rule */ +class MTGVampireRule: public MTGAbility +{ +public: + MTGVampireRule(int _id); + map > victems; + int receiveEvent(WEvent * event); + virtual ostream& toString(ostream& out) const; + int testDestroy(); + virtual MTGVampireRule * clone() const; +}; //unearths destruction if leaves play effect class MTGUnearthRule: public MTGAbility { diff --git a/projects/mtg/src/DuelLayers.cpp b/projects/mtg/src/DuelLayers.cpp index a1a844245..72bd97e18 100644 --- a/projects/mtg/src/DuelLayers.cpp +++ b/projects/mtg/src/DuelLayers.cpp @@ -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)); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index d1f004397..20ea13bd7 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -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 diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index a70a79fad..0dee78942 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -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 (event); + WEventZoneChange * z = dynamic_cast (event); + WEventPhaseChange * pe = dynamic_cast(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) : diff --git a/projects/mtg/src/WEvent.cpp b/projects/mtg/src/WEvent.cpp index b0702a1c6..8a4e74451 100644 --- a/projects/mtg/src/WEvent.cpp +++ b/projects/mtg/src/WEvent.cpp @@ -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; }