diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 7b382d58c..032e8f1b5 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -30441,7 +30441,7 @@ toughness=1 card] name=Remand target=*|stack -auto=fizhand +auto=fizzleto(hand) auto=draw:1 controller text=Counter target spell. If that spell is countered this way, put it into its owner's hand instead of into that player's graveyard. -- Draw a card. mana={1}{U} @@ -30450,7 +30450,7 @@ type=Instant [card] name=Memory Lapse target=*|stack -auto=fizlibrary +auto=fizzleto(librarytop) text=Counter target spell. If that spell is countered this way, put it on top of its owner's library instead of into that player's graveyard. mana={1}{U} type=Instant @@ -30458,7 +30458,7 @@ type=Instant [card] name=Dissipate target=*|stack -auto=fizexile +auto=fizzleto(exile) text=Counter target spell. If that spell is countered this way, exile it instead of putting it into its owner's graveyard. mana={1}{U}{U} type=Instant diff --git a/projects/mtg/include/ActionStack.h b/projects/mtg/include/ActionStack.h index a57f991e4..2f831245e 100644 --- a/projects/mtg/include/ActionStack.h +++ b/projects/mtg/include/ActionStack.h @@ -194,6 +194,14 @@ public: DONT_INTERRUPT_ALL = 2 } InterruptDecision; + typedef enum + { + PUT_IN_GRAVEARD, + PUT_IN_HAND, + PUT_IN_LIBRARY_TOP, + PUT_IN_EXILE + } FizzleMode; + protected: JQuadPtr pspIcons[8]; InterruptDecision interruptDecision[2]; @@ -216,8 +224,7 @@ public: int getPreviousIndex(Interruptible * next, int type = 0, int state = 0 , int display = -1); Interruptible * getNext(Interruptible * previous, int type = 0, int state = 0 , int display = -1); int getNextIndex(Interruptible * previous, int type = 0, int state = 0 , int display = -1); - void Fizzle(Interruptible * action); - void Fizzle(Interruptible * action, int targetZone); //Overloaded fizzle (0 - 3: graveyard, hand, exile, librarytop) + void Fizzle(Interruptible * action, FizzleMode fizzleMode = PUT_IN_GRAVEARD); Interruptible * getAt(int id); void cancelInterruptOffer(InterruptDecision cancelMode = DONT_INTERRUPT, bool log = true); void endOfInterruption(bool log = true); diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 0fba6cde7..4475ed7a0 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1112,23 +1112,15 @@ public: class AAFizzler: public ActivatedAbility { - public: + ActionStack::FizzleMode fizzleMode; // action to do after fizzling + AAFizzler(GameObserver* observer, int _id, MTGCardInstance * card, Spell * _target, ManaCost * _cost = NULL); int resolve(); const char * getMenuText(); AAFizzler* clone() const; }; -class AAOFizzler: public AAFizzler -{ -public: - AAOFizzler( GameObserver* observer, int _id, MTGCardInstance * card, Spell * _target, int tgtZone, ManaCost * _cost ); - int targetZone; - int resolve(); - AAOFizzler* clone() const; -}; - /* Generic classes */ diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index a40a4f00f..2b4fef865 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -1150,7 +1150,8 @@ int ActionStack::garbageCollect() return 1; } -void ActionStack::Fizzle(Interruptible * action) +// Fizzle action and put it in targetZone +void ActionStack::Fizzle(Interruptible * action, FizzleMode fizzleMode) { if (!action) { @@ -1160,32 +1161,17 @@ void ActionStack::Fizzle(Interruptible * action) if (action->type == ACTION_SPELL) { Spell * spell = (Spell *) action; - spell->source->controller()->game->putInGraveyard(spell->source); - } - action->state = RESOLVED_NOK; -} - -void ActionStack::Fizzle(Interruptible * action,int targetZone) -{ - if (!action) - { - DebugTrace("ACTIONSTACK ==ERROR==: action is NULL in ActionStack::Fizzle"); - return; - } - if (action->type == ACTION_SPELL) - { - Spell * spell = (Spell *) action; - switch ( targetZone ) { - case 0: + switch (fizzleMode) { + case PUT_IN_GRAVEARD: spell->source->controller()->game->putInGraveyard(spell->source); break; - case 1: + case PUT_IN_HAND: spell->source->controller()->game->putInHand(spell->source); break; - case 2: + case PUT_IN_EXILE: spell->source->controller()->game->putInExile(spell->source); break; - case 3: + case PUT_IN_LIBRARY_TOP: spell->source->controller()->game->putInLibrary(spell->source); break; } diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 296326ced..0de702c24 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1314,52 +1314,16 @@ ActivatedAbility(observer, _id, card, _cost, 0) { aType = MTGAbility::STANDARD_FIZZLER; target = _target; + + // by default we put the spell to graveyard after fizzling + fizzleMode = ActionStack::PUT_IN_GRAVEARD; } int AAFizzler::resolve() -{ - ActionStack * stack = game->mLayers->stackLayer(); - //the next section helps Ai correctly recieve its targets for this effect - if(!target && source->target) - { - //ai is casting a spell from its hand to fizzle. - target = stack->getActionElementFromCard(source->target); - } - else if(MTGCardInstance * cTarget = dynamic_cast(target)) - { - //ai targeted using an ability on a card to fizzle. - target = stack->getActionElementFromCard(cTarget); - } - Spell * sTarget = (Spell *) target; - MTGCardInstance* sCard = NULL; - if(sTarget) - sCard = sTarget->source; - if(!sCard || !sTarget || sCard->has(Constants::NOFIZZLE)) - return 0; - stack->Fizzle(sTarget); - return 1; -} - -const char * AAFizzler::getMenuText() -{ - return "Fizzle"; -} - -AAFizzler* AAFizzler::clone() const -{ - return NEW AAFizzler(*this); -} - -AAOFizzler::AAOFizzler( GameObserver* observer, int _id, MTGCardInstance * card, Spell * _target, int tgtZone, ManaCost * _cost ) : -AAFizzler( observer, _id, card, _target, _cost ) -{ - targetZone = tgtZone; -} -int AAOFizzler::resolve() { ActionStack * stack = game->mLayers->stackLayer(); //the next section helps Ai correctly recieve its targets for this effect - if(!target && source->target) + if (!target && source->target) { //ai is casting a spell from its hand to fizzle. target = stack->getActionElementFromCard(source->target); @@ -1371,19 +1335,23 @@ int AAOFizzler::resolve() } Spell * sTarget = (Spell *) target; MTGCardInstance* sCard = NULL; - if(sTarget) - sCard = sTarget->source; - if(!sCard || !sTarget || sCard->has(Constants::NOFIZZLE)) + if (sTarget) + sCard = sTarget->source; + if (!sCard || !sTarget || sCard->has(Constants::NOFIZZLE)) return 0; - stack->Fizzle(sTarget, targetZone); + stack->Fizzle(sTarget, fizzleMode); return 1; } -AAOFizzler* AAOFizzler::clone() const + +const char * AAFizzler::getMenuText() { - return NEW AAOFizzler(*this); + return "Fizzle"; } - +AAFizzler* AAFizzler::clone() const +{ + return NEW AAFizzler(*this); +} // BanishCard implementations // Bury diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 210681dfa..f4db55208 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -2015,6 +2015,33 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } + // Fizzle (counterspell...) and put to zone + // This should always be above "fizzle" section + vector splitFizzle = parseBetween(s, "fizzleto(", ")"); + if (splitFizzle.size()) + { + // currently only hand, exile and library are supported + string zone = splitFizzle[1]; + ActionStack::FizzleMode fizzleMode = ActionStack::PUT_IN_GRAVEARD; + if (zone == "hand") + { + fizzleMode = ActionStack::PUT_IN_HAND; + } else if (zone == "exile") + { + fizzleMode = ActionStack::PUT_IN_EXILE; + } else if (zone == "librarytop") + { + fizzleMode = ActionStack::PUT_IN_LIBRARY_TOP; + } + Spell * starget = NULL; + if (spell) + starget = spell->getNextSpellTarget(); + AAFizzler * a = NEW AAFizzler(observer, id, card, starget); + a->fizzleMode = fizzleMode; + a->oneShot = 1; + return a; + } + //Fizzle (counterspell...) found = s.find("fizzle"); if (found != string::npos) @@ -2026,38 +2053,6 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG a->oneShot = 1; return a; } - found = s.find("fizhand"); - if (found != string::npos) - { - Spell * starget = NULL; - if (spell) - starget = spell->getNextSpellTarget(); - MTGAbility * a = NEW AAOFizzler( observer, id, card, starget, 1, NULL ); - a->oneShot = 1; - return a; - } - //Fizzle to exile - found = s.find("fizexile"); - if (found != string::npos) - { - Spell * starget = NULL; - if (spell) - starget = spell->getNextSpellTarget(); - MTGAbility * a = NEW AAOFizzler( observer, id, card, starget, 2, NULL ); - a->oneShot = 1; - return a; - } - //Fizzle to top of library - found = s.find("fizlibrary"); - if (found != string::npos) - { - Spell * starget = NULL; - if (spell) - starget = spell->getNextSpellTarget(); - MTGAbility * a = NEW AAOFizzler( observer, id, card, starget, 3, NULL ); - a->oneShot = 1; - return a; - } //Describes a player target in many abilities int who = TargetChooser::UNSET;