From eb35e3589bae52d9fa35f1bcefbede9763f13289 Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Thu, 14 Oct 2021 15:39:58 +0200 Subject: [PATCH] Fixed primitives, improved Aftermath casting rule: now the casted card becomes instant or sorcery in the stack according to the casted half, fixed a bug with the previous zone of cards casted using the "putinplay" option of "castcard" keyword. --- CHANGELOG.md | 5 +++- .../bin/Res/sets/primitives/borderline.txt | 23 ++++++++++--------- projects/mtg/src/AllAbilities.cpp | 6 ++--- projects/mtg/src/MTGGameZones.cpp | 13 +++++++++-- 4 files changed, 30 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8fef18a01..4ffd918c9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,11 @@ ## [master] (https://github.com/WagicProject/wagic/tree/master) +### 14/10/21 +- *Committed:* Fixed primitives, improved Aftermath casting rule: now the casted card becomes instant or sorcery in the stack according to the casted half, fixed a bug with the previous zone of cards casted using the "putinplay" option of "castcard" keyword. ([Vitty85](https://github.com/Vitty85)) + ### 13/10/21 -- *Committed:* Fixed primitives, added new ability "hasaftermath" to implement Aftermath cost with Flashback and refactored all cards with Aftermath cost (now they use a special version of Flashback but they don't count as flashback spell), added a new ability "spellmover" to implement all cards that have to target a spell on stack to move to some other zone (they are not real counters so they don't care about "nofizzle" or "nofizzlealternative" abilites of their target), fixed all primitives with "spellmover" ability, added a new keyword "storedname" to target card with a specifc previously stored name, improved "fizzleto" ability in order to allow to move the fizzled card on second place from the top or to exile and imprint the target name. ([Vitty85](https://github.com/Vitty85)) +- *Committed:* Fixed primitives, added new ability "hasaftermath" to implement Aftermath cost with Flashback and refactored all cards with Aftermath cost (now they use a special version of Flashback but they don't count as flashback spell), added a new ability "spellmover" to implement all cards that have to target a spell on stack to move to some other zone (they are not real counters so they don't care about "nofizzle" or "nofizzlealternative" abilites of their target), fixed all primitives with "spellmover" ability, added a new keyword "storedname" to target card with a specifc previously stored name, improved "fizzleto" ability in order to allow to move the fizzled card on second place from the top or to exile and imprint the target name. https://github.com/WagicProject/wagic/commit/9c2eee7d7e74f0f494339b10f4f1c3279076bd50 ([Vitty85](https://github.com/Vitty85)) - *Committed:* Fixed primitives, fixed "proliferate" target chooser, improved "cycled" and "discarded" triggers, added new keywords "pcycledcount" and "ocycledcount" to calculate how may cards have been cycled this turn from a specific player, added new menu choices to instantly select/deselect and confirm all the possible targets (in any zone) during the target selection of an ability (e.g. Proliferation ability can target a lot of permanents and players so using that menu choice all the targets will be instantly chosen and then the current player will be able to remove any of them or confirm the entire selection). https://github.com/WagicProject/wagic/commit/fbcb1feb88072988dfe81b33d4e88e1e0f54563c ([Vitty85](https://github.com/Vitty85)) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index a492bc4c5..b72f91bf4 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -12728,6 +12728,7 @@ type=Instant name=Commit // Memory abilities=hasaftermath restriction=compare(type:*[-land]:battlefieldplustype:*:stackplusend)~morethan~0 +otherrestriction=can play sorcery flashback={4}{U}{U} name(Memory) auto=ifnot paid(flashback) then if type(*[-land]|battlefield)~morethan~0 then choice name(Target non-land permanent) name(Target non-land permanent) name(Target non-land permanent) target(*[-land]|battlefield) placefromthetop(2) auto=ifnot paid(flashback) then if type(*|opponentstack)~morethan~0 then choice name(Target opponent spell) name(Target opponent spell) name(Target opponent spell) target(*|opponentstack) spellmover(librarysecond) @@ -29746,7 +29747,6 @@ toughness=8 name=Grind // Dust abilities=hasaftermath flashback={3}{W} name(Dust) -otherrestriction=can play sorcery auto=ifnot paid(flashback) then name(Put -1/-1 counter) target(creature) counter(-1/-1) auto=if paid(flashback) then target(creature[counter{-1/-1}]) moveto(exile) text=Put a -1/-1 counter on each of up to two target creatures. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Exile any number of target creatures that have -1/-1 counters on them. @@ -54205,7 +54205,7 @@ flashback={2}{R} name(Rubble) restriction=type(*|stack)~morethan~0 otherrestriction=can play sorcery auto=ifnot paid(flashback) then target(*|stack) transforms((,newability[pay[[{3}]] name(pay 3 mana) donothing?fizzle])) forever -auto=if paid(flashback) then target(land) freeze +auto=if paid(flashback) then target(land|battlefield) freeze text=Counter target spell unless its controller pays {3}. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Up to three target lands don't untap during their controller's next untap step. mana={2}{U} type=Instant @@ -54248,11 +54248,11 @@ toughness=3 [/card] [card] name=Refuse // Cooperate -abilities=hasaftermath +abilities=hasaftermath,asflash flashback={2}{U} name(Cooperate) restriction=type(*|stack)~morethan~0 otherrestriction=type(*[instant;sorcery]|stack)~morethan~0 -auto=ifnot paid(flashback) then target(*|stack) transforms((.newability[damage:manacost])) oneshot +auto=ifnot paid(flashback) then target(*|stack) transforms((,newability[damage:manacost controller])) oneshot auto=if paid(flashback) then target(*[instant;sorcery]|stack) castcard(copied noevent) text=Refuse deals damage to target spell's controller equal to that spell's converted mana cost. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Copy target instant or sorcery spell. You may choose new targets for the copy. mana={3}{R} @@ -56119,7 +56119,7 @@ abilities=hasaftermath flashback={1}{R}{R} name(Ruin) otherrestriction=can play sorcery,type(creature|battlefield)~morethan~0 auto=ifnot paid(flashback) then name(Search basic land) target(land[basic]|myLibrary) moveTo(myBattlefield) and!( transforms((,newability[tap(noevent)],newability[shuffle])) oneshot )! -auto=if paid(flashback) then target(creature|battlefield) damage:type:land:mybattlefield +auto=if paid(flashback) then name(Damage creature) target(creature|battlefield) damage:type:land:mybattlefield text=Search your library for a basic land card, put it onto the battlefield tapped, then shuffle. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Ruin deals damage to target creature equal to the number of lands you control. mana={2}{G} type=Instant @@ -65294,9 +65294,10 @@ type=Sorcery [/card] [card] name=Spring // Mind -abilities=hasaftermath +abilities=hasaftermath,asflash flashback={4}{U}{U} name(Mind) -auto=ifnot paid(flashback) then target(land[basic]|myLibrary) moveTo(myBattlefield) and!( transforms((,newability[tap(noevent)],newability[shuffle])) oneshot )! +restriction=can play sorcery +auto=ifnot paid(flashback) then name(Search basic land) target(land[basic]|myLibrary) moveTo(myBattlefield) and!( transforms((,newability[tap(noevent)],newability[shuffle])) oneshot )! auto=if paid(flashback) then draw:2 controller text=Search your library for a basic land card, put it onto the battlefield tapped, then shuffle your library. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Draw two cards. mana={2}{G} @@ -65812,9 +65813,9 @@ type=Sorcery name=Start // Finish abilities=hasaftermath flashback={2}{B}{S(creature|mybattlefield)} name(Finish) -otherrestriction=can play sorcery,type(creature|myBattlefield)~morethan~0 -auto=ifnot paid(flashback) then token(Warrior,creature Warrior,1/1,white,vigilance)*2 -auto=if paid(flashback) then destroy target(creature) +otherrestriction=can play sorcery,type(creature|myBattlefield)~morethan~0,type(creature|battlefield)~morethan~1 +auto=ifnot paid(flashback) then token(Warrior,Creature Warrior,1/1,white,vigilance)*2 +auto=if paid(flashback) then destroy target(creature|battlefield) text=Create two 1/1 white Warrior creature tokens with vigilance. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) As an additional cost to cast Finish, sacrifice a creature. -- Destroy target creature. mana={2}{W} type=Instant @@ -66877,7 +66878,7 @@ abilities=hasaftermath flashback={1}{G} name(Survive) restriction=type(creature|battlefield)~morethan~0 otherrestriction=can play sorcery -auto=ifnot paid(flashback) then target(creature|battlefield) damage:type:land:myBattlefield +auto=ifnot paid(flashback) then target(creature|battlefield) damage:type:land:mybattlefield auto=if paid(flashback) then all(*|mygraveyard) moveto(mylibrary) && shuffle auto=if paid(flashback) then all(*|opponentgraveyard) moveto(opponentlibrary) && shuffle opponent text=Struggle deals damage to target creature equal to the number of lands you control. -- Aftermath (Cast this spell only from your graveyard. Then exile it.) Each player shuffles his or her graveyard into his or her library. diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index ab7a5a88d..69d93acf3 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -9872,9 +9872,9 @@ int AACastCard::resolveSpell() if ((normal || asNormalMadness)||(!_target->hasType(Subtypes::TYPE_INSTANT) && !_target->hasType(Subtypes::TYPE_SORCERY))) { if (putinplay && (_target->hasType(Subtypes::TYPE_ARTIFACT)||_target->hasType(Subtypes::TYPE_CREATURE)||_target->hasType(Subtypes::TYPE_ENCHANTMENT)||_target->hasType(Subtypes::TYPE_PLANESWALKER))) - copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->battlefield, noEvent); + copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->reveal, noEvent); // Fixed a problem with previous zone of card, it cannot be directly battlefield. else - copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->stack, noEvent); + copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->stack, noEvent); copy->changeController(source->controller(),true); if(asNormalMadness) copy->MadnessPlay = true; @@ -9882,7 +9882,7 @@ int AACastCard::resolveSpell() else { if (putinplay && (_target->hasType(Subtypes::TYPE_ARTIFACT)||_target->hasType(Subtypes::TYPE_CREATURE)||_target->hasType(Subtypes::TYPE_ENCHANTMENT)||_target->hasType(Subtypes::TYPE_PLANESWALKER))) - copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->battlefield, noEvent); + copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->reveal, noEvent); // Fixed a problem with previous zone of card, it cannot be directly battlefield. else copy = _target->controller()->game->putInZone(_target, _target->currentZone, source->controller()->game->stack, noEvent); copy->changeController(source->controller(),true); diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 1fdc478ce..e002c52ea 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -730,8 +730,17 @@ MTGCardInstance * MTGPlayerCards::putInZone(MTGCardInstance * card, MTGGameZone if(shufflelibrary) copy->owner->game->library->shuffle();//shouldnt we only ever do this if you clicked close on your library gui?????? - if(copy->has(Constants::ADVENTURE) && copy->alternateCostPaid[ManaCost::MANA_PAID_WITH_ALTERNATIVE] == 1 && //Added to correctly set the adventure cards type. - (to == g->players[0]->game->stack || to == g->players[1]->game->stack || to == g->players[0]->game->battlefield || to == g->players[1]->game->battlefield)){ + if(copy->has(Constants::ADVENTURE) && copy->alternateCostPaid[ManaCost::MANA_PAID_WITH_ALTERNATIVE] == 1 && //Added to correctly set the adventure cards type on stack. + (to == g->players[0]->game->stack || to == g->players[1]->game->stack)){ + copy->types.clear(); + if(copy->has(Constants::ASFLASH)) + copy->types.push_back(Subtypes::TYPE_INSTANT); + else + copy->types.push_back(Subtypes::TYPE_SORCERY); + } + + if(copy->has(Constants::HASAFTERMATH) && copy->alternateCostPaid[ManaCost::MANA_PAID_WITH_FLASHBACK] == 1 && //Added to correctly set the aftermath cards type on stack. + (to == g->players[0]->game->stack || to == g->players[1]->game->stack)){ copy->types.clear(); if(copy->has(Constants::ASFLASH)) copy->types.push_back(Subtypes::TYPE_INSTANT);