From 3e7ef8c77c04eec3e950a6c0c1ca7ed8960f620d Mon Sep 17 00:00:00 2001 From: valfieri Date: Wed, 16 Dec 2020 12:21:57 +0100 Subject: [PATCH] Added abilities for cards which have to return battlefield or hand instead of graveyard (e.g. just like exiledeath ability), improved fresh attribute management also for card moved in hand, library, commandzone and for instants and sorcery spells, added/fixed primitives. --- .../bin/Res/sets/primitives/borderline.txt | 130 +++++++++++++++++- .../bin/Res/sets/primitives/unsupported.txt | 72 ---------- projects/mtg/include/MTGDefinitions.h | 5 +- projects/mtg/src/ActionStack.cpp | 12 ++ projects/mtg/src/MTGAbility.cpp | 8 +- projects/mtg/src/MTGCardInstance.cpp | 12 ++ projects/mtg/src/MTGDefinitions.cpp | 5 +- projects/mtg/src/MTGGameZones.cpp | 16 ++- 8 files changed, 178 insertions(+), 82 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index 061be4aab..6bee6b3e4 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -29,7 +29,7 @@ type=Sorcery [card] name=Abnormal Endurance target=creature -auto=transforms((,newability[2/0],newability[@movedTo(this|graveyard) from(battlefield):all(trigger[to]) moveTo(ownerBattlefield) and!(tap(noevent))!])) ueot +auto=transforms((,newability[2/0],newability[inplaytapdeath])) ueot text=Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control." mana={1}{B} type=Instant @@ -1605,6 +1605,24 @@ power=10 toughness=10 [/card] [card] +name=Apex of Power +autohand={7}{R}{R}{R}:name(Cast from hand and add 10 white mana) name(Cast from hand and add 10 white mana) add{W}{W}{W}{W}{W}{W}{W}{W}{W}{W} controller && target(Apex of Power|myhand) activate castcard(restricted) +autohand={7}{R}{R}{R}:name(Cast from hand and add 10 black mana) name(Cast from hand and add 10 black mana) add{B}{B}{B}{B}{B}{B}{B}{B}{B}{B} controller && target(Apex of Power|myhand) activate castcard(restricted) +autohand={7}{R}{R}{R}:name(Cast from hand and add 10 blue mana) name(Cast from hand and add 10 blue mana) add{U}{U}{U}{U}{U}{U}{U}{U}{U}{U} controller && target(Apex of Power|myhand) activate castcard(restricted) +autohand={7}{R}{R}{R}:name(Cast from hand and add 10 green mana) name(Cast from hand and add 10 green mana) add{G}{G}{G}{G}{G}{G}{G}{G}{G}{G} controller && target(Apex of Power|myhand) activate castcard(restricted) +autohand={7}{R}{R}{R}:name(Cast from hand and add 10 red mana) name(Cast from hand and add 10 red mana) add{R}{R}{R}{R}{R}{R}{R}{R}{R}{R} controller && target(Apex of Power|myhand) activate castcard(restricted) +auto=if type(land[zpos=1]|mylibrary)~equalto~1 then all(*[zpos=1|mylibrary) moveto(exile) else all(*[zpos=1|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=2]|mylibrary)~equalto~1 then all(*[zpos=2|mylibrary) moveto(exile) else all(*[zpos=2|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=3]|mylibrary)~equalto~1 then all(*[zpos=3|mylibrary) moveto(exile) else all(*[zpos=3|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=4]|mylibrary)~equalto~1 then all(*[zpos=4|mylibrary) moveto(exile) else all(*[zpos=4|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=5]|mylibrary)~equalto~1 then all(*[zpos=5|mylibrary) moveto(exile) else all(*[zpos=5|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=6]|mylibrary)~equalto~1 then all(*[zpos=6|mylibrary) moveto(exile) else all(*[zpos=6|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +auto=if type(land[zpos=7]|mylibrary)~equalto~1 then all(*[zpos=7|mylibrary) moveto(exile) else all(*[zpos=7|mylibrary) moveto(exile) and!( transforms((,canplayfromexile)) ueot )! +text=Exile the top seven cards of your library. Until end of turn, you may cast spells from among them. -- If this spell was cast from your hand, add ten mana of any one color. +mana={7}{R}{R}{R} +type=Sorcery +[/card] +[card] name=Aphemia, the Cacophony abilities=flying auto=@each my endofturn:may moveto(exile) target(enchantment|myGraveyard) && token(Zombie,Creature Zombie,2/2,black) @@ -5290,6 +5308,19 @@ mana={4}{G}{G} type=Instant [/card] [card] +name=Bounty of the Hunt +target=creature +restriction=type(creature|battlefield)~morethan~0 +otherrestriction=type(creature|battlefield)~morethan~0 +other={E(other *[green]|myhand)} name(Exile green card) +auto=transforms((,newability[counter(1/1) all(this)],newability[phaseaction[cleanup once] counter(1/1.-1) all(this)])) oneshot +auto=choice name(Give other 2 counters to 1 creature) name(Give other 2 counters to 1 creature) target(other creature) transforms((,newability[counter(1/1.2) all(this)],newability[phaseaction[cleanup once] counter(1/1.-2) all(this)])) oneshot +auto=if type(creature|battlefield)~morethan~2 then choice name(Give 1 counter to other 2 creatures) name(Give 1 counter to other 2 creatures) target(<2>other creature) transforms((,newability[counter(1/1) all(this)],newability[phaseaction[cleanup once] counter(1/1.-1) all(this)])) oneshot +text=You may exile a green card from your hand rather than pay Bounty of the Hunt's mana cost. -- Distribute three +1/+1 counters among one, two, or three target creatures. For each +1/+1 counter you put on a creature this way, remove a +1/+1 counter from that creature at the beginning of the next cleanup step. +mana={3}{G}{G} +type=Instant +[/card] +[card] name=Bounty of the Luxa auto=@each my firstmain:if type(this[counter(flood)])~morethan~0 ability$!thisforeach(counter{0/0,1,flood}) counter(0/0,-1,flood) && add{1}{G}{U}!$ controller else ability$!counter(0/0,1,flood) && draw:1 controller!$ controller text=At the beginning of your precombat main phase, remove all flood counters from Bounty of the Luxa. If no counters were removed this way, put a flood counter on Bounty of the Luxa and draw a card. Otherwise, add {1}{G}{U} to your mana pool. @@ -11345,6 +11376,13 @@ mana={2}{R} type=Sorcery [/card] [card] +name=Detection Tower +auto={T}:add{C} +auto={1}{T}:lord(*[opponentshroud;controllershroud]|opponentbattlefield) transforms((,newability[-opponentshroud]),newability[-controllershroud])) ueot +text={T}: Add {C}. -- {1}, {T}: Until end of turn, your opponents and creatures your opponents control with hexproof can be the targets of spells and abilities you control as though they didn't have hexproof. +type=Land +[/card] +[card] name=Devastating Dreams auto=if type(*|myHand)~morethan~0 then choice name(Discard 1 card) discard:1 controller && damage:1 all(creature) && ability$!sacrifice notatarget(land|mybattlefield)!$ controller && ability$!sacrifice notatarget(land|mybattlefield)!$ opponent auto=if type(*|myHand)~morethan~1 then choice name(Discard 2 cards) discard:2 controller && damage:2 all(creature) && ability$!sacrifice notatarget(<2>land|mybattlefield)!$ controller && ability$!sacrifice notatarget(<2>land|mybattlefield)!$ opponent @@ -16367,6 +16405,18 @@ mana={2}{R} type=Instant [/card] [card] +name=Flame-Wreathed Phoenix +abilities=flying +auto=all(this) flipacoin winability counter(0/0,1,TributeUnpaid) winabilityend loseability counter(1/1,2) loseabilityend flipend +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:all(this) transforms((,newability[counter(0/0.-1.TributeUnpaid)],newability[haste],newability[handdeath])) forever +text=Flying -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Flame-Wreathed Phoenix enters the battlefield, if tribute wasn't paid, it gains haste and "When this creature dies, return it to its owner's hand." +mana={2}{R}{R} +type=Creature +subtype=Phoenix +power=3 +toughness=3 +[/card] +[card] name=Flameblade Adept abilities=menace auto=@movedto(*|mygraveyard) from(myhand):1/0 ueot @@ -28156,7 +28206,7 @@ type=Land name=Malakir Rebirth autohand={0}:restriction{can play land} name(Malakir Mire) name(Malakir Mire) flip(Malakir Mire) forcetype(land) auto=life:-2 controller -auto=name(Choose a creature) name(Choose a creature) target(creature) transforms((,newability[@movedTo(this|graveyard) from(battlefield):all(trigger[to]) moveTo(ownerBattlefield) and!(tap(noevent))!])) ueot +auto=name(Choose a creature) name(Choose a creature) target(creature) transforms((,newability[inplaytapdeath])) ueot text=Choose target creature. You lose 2 life. Until end of turn, that creature gains "When this creature dies, return it to the battlefield tapped under its owner's control." mana={B} type=Instant @@ -30959,6 +31009,18 @@ power=10 toughness=6 [/card] [card] +name=Nessian Demolok +auto=all(this) flipacoin winability counter(0/0,1,TributeUnpaid) winabilityend loseability counter(1/1,3) loseabilityend flipend +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:all(this) counter(0/0,-1,TributeUnpaid) +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:target(*[-creature]|battlefield) destroy +text=Tribute 3 (As this creature enters the battlefield, an opponent of your choice may place three +1/+1 counters on it.) -- When Nessian Demolok enters the battlefield, if tribute wasn't paid, destroy target noncreature permanent. +mana={3}{G}{G} +type=Creature +subtype=Beast +power=3 +toughness=3 +[/card] +[card] name=Nessian Hornbeetle auto=@each my combatbegins restriction{type(creature[power>=4]|mybattlefield)~morethan~0}:counter(1/1,1) text=At the beginning of combat on your turn, if you control another creature with power 4 or greater, put a +1/+1 counter on Nessian Hornbeetle. @@ -32705,6 +32767,18 @@ mana={2}{U} type=Instant [/card] [card] +name=Oracle of Bones +auto=if type(*[instant;sorcery]|mygraveyard)~morethan~0 then all(this) flipacoin winability counter(0/0,1,TributeUnpaid) winabilityend loseability counter(1/1,2) loseabilityend flipend +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:counter(0/0,-1,TributeUnpaid) all(this) +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:may name(Cast instant or sorcery) name(Cast instant or sorcery) activate castcard(normal) target(*[sorcery;instant]|mygraveyard) +text=Haste -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Oracle of Bones enters the battlefield, if tribute wasn't paid, you may cast an instant or sorcery card from your hand without paying its mana cost. +mana={2}{R}{R} +type=Creature +subtype=Minotaur Shaman +power=3 +toughness=1 +[/card] +[card] name=Oracle's Vault auto={2}{T}{counter(0/0,1,brick)}:deplete:1 controller auto={T}{restriction type(this[counter(brick)>=3])~morethan~0}:deplete:1 controller @@ -33985,6 +34059,16 @@ power=2 toughness=2 [/card] [card] +name=Pharagax Giant +auto=all(this) flipacoin winability damage:5 opponent winabilityend loseability counter(1/1,2) loseabilityend flipend +text=Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Pharagax Giant enters the battlefield, if tribute wasn't paid, Pharagax Giant deals 5 damage to each opponent. +mana={4}{R} +type=Creature +subtype=Giant +power=3 +toughness=3 +[/card] +[card] name=Pharika's Libation target=player auto=choice ability$!name(sacrifice an enchantment) notatarget(enchantment|myBattlefield) sacrifice!$ targetedplayer @@ -41131,6 +41215,18 @@ power=* toughness=3 [/card] [card] +name=Shambling Swarm +auto=@movedTo(this|graveyard) from(battlefield):choice name(Assign -1/-1 counter) name(Assign -1/-1 counter) target(creature) transforms((,newability[counter(-1/-1) all(this)],newability[phaseaction[endofturn once] counter(-1/-1.-1) all(this)])) oneshot +auto=@movedTo(this|graveyard) from(battlefield):choice name(Assign -1/-1 counter) name(Assign -1/-1 counter) target(creature) transforms((,newability[counter(-1/-1) all(this)],newability[phaseaction[endofturn once] counter(-1/-1.-1) all(this)])) oneshot +auto=@movedTo(this|graveyard) from(battlefield):choice name(Assign -1/-1 counter) name(Assign -1/-1 counter) target(creature) transforms((,newability[counter(-1/-1) all(this)],newability[phaseaction[endofturn once] counter(-1/-1.-1) all(this)])) oneshot +text=When Shambling Swarm dies, distribute three -1/-1 counters among one, two, or three target creatures. For each -1/-1 counter you put on a creature this way, remove a -1/-1 counter from that creature at the beginning of the next end step. +mana={1}{B}{B}{B} +type=Creature +subtype=Horror +power=3 +toughness=3 +[/card] +[card] name=Shanna, Sisay's Legacy auto=cantbetargetof(artifact,creatures,enchantment[-auras],land,planeswalker|opponentbattlefield,opponentgraveyard) auto=foreach(creature|myBattlefield) 1/1 @@ -41711,6 +41807,19 @@ power=2 toughness=1 [/card] [card] +name=Shrike Harpy +abilities=flying +auto=all(this) flipacoin winability counter(0/0,1,TributeUnpaid) winabilityend loseability counter(1/1,2) loseabilityend flipend +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:all(this) counter(0/0,-1,TributeUnpaid) +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:ability$!name(Sacrifice a creature) notatarget(creature|mybattlefield) sacrifice!$ opponent +text=Flying -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Shrike Harpy enters the battlefield, if tribute wasn't paid, target opponent sacrifices a creature. +mana={3}{B}{B} +type=Creature +subtype=Harpy +power=2 +toughness=2 +[/card] +[card] name=Shrine Keeper mana={1}{W} type=Creature @@ -42328,6 +42437,19 @@ power=1 toughness=2 [/card] [card] +name=Siren of the Fanged Coast +abilities=flying +auto=if type(creature|opponentBattlefield)~morethan~0 then all(this) flipacoin winability counter(0/0,1,TributeUnpaid) winabilityend loseability counter(1/1,3) loseabilityend flipend +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:all(this) counter(0/0,-1,TributeUnpaid) +auto=@counteradded(0/0,1,TributeUnpaid) from(this) once:target(creature) moveto(mybattlefield) +text=Flying -- Tribute 3 (As this creature enters the battlefield, an opponent of your choice may place three +1/+1 counters on it.) -- When Siren of the Fanged Coast enters the battlefield, if tribute wasn't paid, gain control of target creature. +mana={3}{U}{U} +type=Creature +subtype=Siren +power=1 +toughness=1 +[/card] +[card] name=Siren Reaver abilities=flying text=Raid — This spell costs {1} less to cast if you attacked with a creature this turn. -- Flying @@ -46250,7 +46372,7 @@ type=Sorcery [card] name=Supernatural Stamina target=creature -auto=transforms((,newability[2/0],newability[@movedTo(this|graveyard) from(battlefield):all(trigger[to]) moveTo(ownerBattlefield) and!(tap(noevent))!])) ueot +auto=transforms((,newability[2/0],newability[inplaytapdeath])) ueot text=Until end of turn, target creature gets +2/+0 and gains "When this creature dies, return it to the battlefield tapped under its owner's control." mana={B} type=Instant @@ -51841,7 +51963,7 @@ type=Sorcery [card] name=Verdant Rebirth target=creature -auto=transforms((,newability[@movedTo(this|graveyard) from(battlefield):all(trigger[to]) moveTo(ownerHand)])) ueot +auto=transforms((,newability[handdeath])) ueot auto=draw:1 controller text=Until end of turn, target creature gains "When this creature dies, return it to its owner's hand." -- Draw a card. mana={1}{G} diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index db32c342f..8e69ba8f1 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -1412,12 +1412,6 @@ mana={3}{B}{G} // {G}{U} type=Instant // Instant [/card] [card] -name=Bounty of the Hunt -text=You may exile a green card from your hand rather than pay Bounty of the Hunt's mana cost. -- Distribute three +1/+1 counters among one, two, or three target creatures. For each +1/+1 counter you put on a creature this way, remove a +1/+1 counter from that creature at the beginning of the next cleanup step. -mana={3}{G}{G} -type=Instant -[/card] -[card] name=Brago's Favor text=Hidden agenda (Start the game with this conspiracy face down in the command zone and secretly name a card. You may turn this conspiracy face up any time and reveal the chosen name.) -- Spells with the chosen name you cast cost {1} less to cast. type=Conspiracy @@ -4299,16 +4293,6 @@ mana={4}{U}{U} type=Sorcery [/card] [card] -name=Flame-Wreathed Phoenix -abilities=flying -text=Flying -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Flame-Wreathed Phoenix enters the battlefield, if tribute wasn't paid, it gains haste and "When this creature dies, return it to its owner's hand." -mana={2}{R}{R} -type=Creature -subtype=Phoenix -power=3 -toughness=3 -[/card] -[card] name=Flames of the Blood Hand text=Flames of the Blood Hand deals 4 damage to target player. The damage can't be prevented. If that player would gain life this turn, that player gains no life instead. mana={2}{R} @@ -8878,15 +8862,6 @@ type=Artifact subtype=Equipment [/card] [card] -name=Nessian Demolok -text=Tribute 3 (As this creature enters the battlefield, an opponent of your choice may place three +1/+1 counters on it.) -- When Nessian Demolok enters the battlefield, if tribute wasn't paid, destroy target noncreature permanent. -mana={3}{G}{G} -type=Creature -subtype=Beast -power=3 -toughness=3 -[/card] -[card] name=Nesting Grounds auto={T}:add{1} text={T}: Add {1}. -- {1}, {T}: Move a counter from target permanent you control onto another target permanent. Activate this ability only any time you could cast a sorcery. @@ -9305,15 +9280,6 @@ power=1 toughness=1 [/card] [card] -name=Oracle of Bones -text=Haste -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Oracle of Bones enters the battlefield, if tribute wasn't paid, you may cast an instant or sorcery card from your hand without paying its mana cost. -mana={2}{R}{R} -type=Creature -subtype=Minotaur Shaman -power=3 -toughness=1 -[/card] -[card] name=Oracle's Attendants text={T}: All damage that would be dealt to target creature this turn by a source of your choice is dealt to Oracle's Attendants instead. mana={3}{W} @@ -9647,15 +9613,6 @@ power=1 toughness=1 [/card] [card] -name=Pharagax Giant -text=Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Pharagax Giant enters the battlefield, if tribute wasn't paid, Pharagax Giant deals 5 damage to each opponent. -mana={4}{R} -type=Creature -subtype=Giant -power=3 -toughness=3 -[/card] -[card] name=Phoebe, Head of S.N.E.A.K. text=Phoebe, Head of S.N.E.A.K. can't be blocked by creatures with flavor text. -- {2}{U}{B}: Phoebe permanently steals target creature's text box. (That creature loses all rules text, flavor text, and watermarks. This creature gains them.) mana={1}{U}{B} @@ -11443,15 +11400,6 @@ mana={2}{R} type=Instant [/card] [card] -name=Shambling Swarm -text=When Shambling Swarm dies, distribute three -1/-1 counters among one, two, or three target creatures. For each -1/-1 counter you put on a creature this way, remove a -1/-1 counter from that creature at the beginning of the next end step. -mana={1}{B}{B}{B} -type=Creature -subtype=Horror -power=3 -toughness=3 -[/card] -[card] name=Shape Stealer text=Whenever Shape Stealer blocks or becomes blocked by a creature, change Shape Stealer's power and toughness to that creature's power and toughness until end of turn. mana={U}{U} @@ -11636,16 +11584,6 @@ power=3 toughness=3 [/card] [card] -name=Shrike Harpy -abilities=flying -text=Flying -- Tribute 2 (As this creature enters the battlefield, an opponent of your choice may place two +1/+1 counters on it.) -- When Shrike Harpy enters the battlefield, if tribute wasn't paid, target opponent sacrifices a creature. -mana={3}{B}{B} -type=Creature -subtype=Harpy -power=2 -toughness=2 -[/card] -[card] name=Shrouded Lore text=Target opponent chooses a card in your graveyard. You may pay {B}. If you do, repeat this process except that opponent can't choose a card already chosen for Shrouded Lore. Then put the last chosen card into your hand. mana={B} @@ -11743,16 +11681,6 @@ power=3 toughness=2 [/card] [card] -name=Siren of the Fanged Coast -abilities=flying -text=Flying -- Tribute 3 (As this creature enters the battlefield, an opponent of your choice may place three +1/+1 counters on it.) -- When Siren of the Fanged Coast enters the battlefield, if tribute wasn't paid, gain control of target creature. -mana={3}{U}{U} -type=Creature -subtype=Siren -power=1 -toughness=1 -[/card] -[card] name=Siren's Call text=Cast Siren's Call only during an opponent's turn, before attackers are declared. -- Creatures the active player controls attack this turn if able. -- At the beginning of the next end step, destroy all non-Wall creatures that player controls that didn't attack this turn. Ignore this effect for each creature the player didn't control continuously since the beginning of the turn. mana={U} diff --git a/projects/mtg/include/MTGDefinitions.h b/projects/mtg/include/MTGDefinitions.h index 42ea77d02..7ab278cdf 100644 --- a/projects/mtg/include/MTGDefinitions.h +++ b/projects/mtg/include/MTGDefinitions.h @@ -292,7 +292,10 @@ class Constants CANBECOMMANDER = 165, ISCOMMANDER = 166, THREEBLOCKERS = 167, - NB_BASIC_ABILITIES = 168, + HANDDEATH = 168, + INPLAYDEATH = 169, + INPLAYTAPDEATH = 170, + NB_BASIC_ABILITIES = 171, RARITY_S = 'S', //Special Rarity RARITY_M = 'M', //Mythics diff --git a/projects/mtg/src/ActionStack.cpp b/projects/mtg/src/ActionStack.cpp index e98e1f5de..f04873cb5 100644 --- a/projects/mtg/src/ActionStack.cpp +++ b/projects/mtg/src/ActionStack.cpp @@ -589,6 +589,18 @@ int PutInGraveyard::resolve() card->controller()->game->putInZone(card, zone, card->owner->game->exile); return 1; } + if (card->basicAbilities[(int)Constants::HANDDEATH]) + { + card->controller()->game->putInZone(card, zone, card->owner->game->hand); + return 1; + } + if (card->basicAbilities[(int)Constants::INPLAYDEATH] || card->basicAbilities[(int)Constants::INPLAYTAPDEATH]) + { + card->controller()->game->putInZone(card, zone, card->owner->game->battlefield); + if(card->basicAbilities[(int)Constants::INPLAYTAPDEATH]) + card->tap(true); + return 1; + } if (zone == observer->players[0]->game->inPlay || zone == observer->players[1]->game->inPlay) { card->controller()->game->putInZone(card, zone, card->owner->game->graveyard); diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index a571378f6..6a14d479a 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -4925,6 +4925,9 @@ int AbilityFactory::abilityEfficiency(MTGAbility * a, Player * p, int mode, Targ badAbilities[(int)Constants::NOMANA] = true; badAbilities[(int)Constants::ONLYMANA] = true; badAbilities[(int)Constants::EXILEDEATH] = true; + badAbilities[(int)Constants::HANDDEATH] = true; + badAbilities[(int)Constants::INPLAYDEATH] = true; + badAbilities[(int)Constants::INPLAYTAPDEATH] = true; badAbilities[(int)Constants::WEAK] = true; badAbilities[(int)Constants::NOLIFEGAIN] = true; badAbilities[(int)Constants::NOLIFEGAINOPPONENT] = true; @@ -5741,7 +5744,10 @@ void AbilityFactory::addAbilities(int _id, Spell * spell) if (card->basicAbilities[(int)Constants::EXILEDEATH]) { card->controller()->game->putInZone(card, card->getCurrentZone(), card->owner->game->exile); - + } + else if (card->basicAbilities[(int)Constants::HANDDEATH]) + { + card->controller()->game->putInZone(card, card->getCurrentZone(), card->owner->game->hand); } else if (card->alternateCostPaid[ManaCost::MANA_PAID_WITH_BUYBACK] > 0) { diff --git a/projects/mtg/src/MTGCardInstance.cpp b/projects/mtg/src/MTGCardInstance.cpp index b1d582616..1d9b8df20 100644 --- a/projects/mtg/src/MTGCardInstance.cpp +++ b/projects/mtg/src/MTGCardInstance.cpp @@ -510,6 +510,18 @@ int MTGCardInstance::toGrave( bool forced ) p->game->putInZone(this, p->game->inPlay, owner->game->exile); return 1; } + if (basicAbilities[(int)Constants::HANDDEATH]) + { + p->game->putInZone(this, p->game->inPlay, owner->game->hand); + return 1; + } + if (basicAbilities[(int)Constants::INPLAYDEATH] || basicAbilities[(int)Constants::INPLAYTAPDEATH]) + { + p->game->putInZone(this, p->game->inPlay, owner->game->battlefield); + if(basicAbilities[(int)Constants::INPLAYTAPDEATH]) + tap(true); + return 1; + } if (!basicAbilities[(int)Constants::INDESTRUCTIBLE]) { p->game->putInZone(this, p->game->inPlay, owner->game->graveyard); diff --git a/projects/mtg/src/MTGDefinitions.cpp b/projects/mtg/src/MTGDefinitions.cpp index 0670e2762..5c6e020a5 100644 --- a/projects/mtg/src/MTGDefinitions.cpp +++ b/projects/mtg/src/MTGDefinitions.cpp @@ -198,7 +198,10 @@ const char* Constants::MTGBasicAbilities[] = { "partner", //Has partner ability "canbecommander", //Can be a commander (eg. some planeswalkers can) "iscommander", //It's the current commander - "threeblockers" //It can be blocked just by 3 creatures or more. + "threeblockers", //It can be blocked just by 3 creatures or more. + "handdeath", //It goes in hand after death. + "inplaydeath", //It goes back in play untapped after death. + "inplaytapdeath" //It goes back in play tapped after death. }; map Constants::MTGBasicAbilitiesMap; diff --git a/projects/mtg/src/MTGGameZones.cpp b/projects/mtg/src/MTGGameZones.cpp index 4f1a5f5a5..b231b6c04 100644 --- a/projects/mtg/src/MTGGameZones.cpp +++ b/projects/mtg/src/MTGGameZones.cpp @@ -385,10 +385,20 @@ void MTGPlayerCards::showHand() // Moves a card to its owner's graveyard MTGCardInstance * MTGPlayerCards::putInGraveyard(MTGCardInstance * card) { - if (card->basicAbilities[(int)Constants::EXILEDEATH]) + if (card->getCurrentZone() != card->controller()->game->hand && card->basicAbilities[(int)Constants::EXILEDEATH]) { - putInZone(card, card->getCurrentZone(), card->owner->game->exile); - + return putInZone(card, card->getCurrentZone(), card->owner->game->exile); + } + else if (card->getCurrentZone() != card->controller()->game->hand && card->basicAbilities[(int)Constants::HANDDEATH]) + { + return putInZone(card, card->getCurrentZone(), card->owner->game->hand); + } + else if (card->getCurrentZone() != card->controller()->game->hand && (card->basicAbilities[(int)Constants::INPLAYDEATH] || card->basicAbilities[(int)Constants::INPLAYTAPDEATH])) + { + MTGCardInstance* ret = putInZone(card, card->getCurrentZone(), card->owner->game->battlefield); + if(card->basicAbilities[(int)Constants::INPLAYTAPDEATH]) + ret->tap(true); + return ret; } return putInZone(card, card->currentZone, card->owner->game->graveyard); }