From eaaa4d783b37c91fefdf9fc135058d4c6f72fe93 Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Thu, 7 Jan 2021 18:56:47 +0100 Subject: [PATCH] Fixed/added primitives, added keyword to alter devotion count, added keyword to target cards with flashback cost, added "duplicatecounters(single)" keyword to add a counter of a specific kind already present on a permanent or a player. --- .../bin/Res/sets/primitives/borderline.txt | 136 +++++++++++++++--- .../bin/Res/sets/primitives/planeswalkers.txt | 2 +- .../bin/Res/sets/primitives/unsupported.txt | 81 ----------- projects/mtg/include/AllAbilities.h | 23 ++- projects/mtg/include/CardDescriptor.h | 2 + projects/mtg/include/Player.h | 1 + projects/mtg/src/AllAbilities.cpp | 57 +++++++- projects/mtg/src/CardDescriptor.cpp | 11 ++ projects/mtg/src/CardGui.cpp | 12 ++ projects/mtg/src/MTGAbility.cpp | 15 +- projects/mtg/src/Player.cpp | 1 + projects/mtg/src/Rules.cpp | 1 + projects/mtg/src/TargetChooser.cpp | 12 ++ 13 files changed, 249 insertions(+), 105 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index 23411a7f0..f597a0880 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -19,6 +19,17 @@ mana={X}{U} type=Sorcery [/card] [card] +name=Aetherborn Marauder +abilities=flying,lifelink +auto=all(*[counter{1/1}|mybattlefield) transforms((,newability[thisforeach(counter{1/1.1}) may name(Move 1/1 counter) counter(1/1.-1) all(this) && counter(1/1) target(Aetherborn Marauder[fresh]|mybattlefield)])) oneshot +text=Flying, lifelink -- When Aetherborn Marauder enters the battlefield, move any number of +1/+1 counters from other permanents you control onto Aetherborn Marauder. +mana={3}{B} +type=Creature +subtype=Aetherborn Rogue +power=2 +toughness=2 +[/card] +[card] name=Abandon Hope auto=reject target(*|myhand) auto=reject target(*|opponenthand) @@ -532,6 +543,17 @@ power=2 toughness=3 [/card] [card] +name=Aggression +target=creature[-wall] +auto=first strike +auto=trample +auto=teach(creature) transforms((,newability[@each my endofturn restriction{didntattack}:destroy])) +text=Enchant non-Wall creature -- Enchanted creature has first strike and trample. -- At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn. +mana={2}{R} +type=Enchantment +subtype=Aura +[/card] +[card] name=Aggressive Instinct target=creature|mybattlefield auto=transforms((,newability[target(creature|opponentbattlefield) dynamicability])) forever @@ -636,6 +658,17 @@ mana={2}{G}{W} type=Enchantment [/card] [card] +name=Ajani's Chosen +auto=@movedTo(enchantment[aura]|myBattlefield):all(trigger[to]) transforms((,newability[may name(Attach aura to cat) rehook target(cat[token;fresh]|mybattlefield)])) oneshot +auto=@movedTo(enchantment|myBattlefield):token(Cat,Creature Cat,2/2,white) +text=Whenever an enchantment enters the battlefield under your control, put a 2/2 white Cat creature token onto the battlefield. If that enchantment is an Aura, you may attach it to the token. +mana={2}{W}{W} +type=Creature +subtype=Cat Soldier +power=3 +toughness=3 +[/card] +[card] name=Ajani's Influence target=creature auto=counter(1/1,2) @@ -926,6 +959,15 @@ power=1 toughness=1 [/card] [card] +name=Allure of the Unknown +auto=if type(*[-land;zpos<=6]|mylibrary)~morethan~0 then ability$!name(Reveal the top six cards) name(Reveal the top six cards) target(<6>*[zpos<=6]|opponentlibrary) donothing!$ opponent +auto=if type(*[-land;zpos<=6]|mylibrary)~morethan~0 then ability$!name(Choose one) name(Exile and cast) target(*[-land;zpos<=6]|opponentlibrary) moveto(exile) and!( activate castcard(normal) and!( moveto(opponenthand) all(*[zpos<=6]|opponentlibrary) )! )! _ choice name(Exile and don't cast) target(*[-land;zpos<=6]|opponentlibrary) moveto(exile) and!( moveto(opponenthand) all(*[zpos<=6]|opponentlibrary) )! !$ opponent +auto=if type(*[-land;zpos<=6]|mylibrary)~equalto~0 then ability$!name(Reveal the top six cards) name(Reveal the top six cards) target(<6>*[zpos<=6]|opponentlibrary) moveto(opponenthand)!$ opponent +text=Reveal the top six cards of your library. An opponent exiles a nonland card from among them, then you put the rest into your hand. That opponent may cast the exiled card without paying its mana cost. +mana={3}{B}{R} +type=Sorcery +[/card] +[card] name=Ally Encampment auto={T}:add{C} auto=this(variable{type:ally:myrestrictedcastingzone}>0) {T}:add{B} @@ -1022,21 +1064,31 @@ type=Artifact [card] name=Altar of the Lost auto=tap(noevent) -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{W}{B} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{W}{R} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{W}{G} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{W}{U} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{B}{R} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{B}{G} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{B}{U} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{R}{G} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{R}{U} -auto=this(variable{type:*[flashback]:mygraveyard}>0) {T}:add{U}{G} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{W}{B} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{W}{R} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{W}{G} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{W}{U} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{B}{R} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{B}{G} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{B}{U} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{R}{G} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{R}{U} +auto=this(variable{type:*[hasflashback]:mygraveyard}>0) {T}:add{U}{G} text=Altar of the Lost enters the battlefield tapped. -- {T}: Add two mana in any combination of colors to your mana pool. Spend this mana only to cast spells with flashback from a graveyard. mana={3} type=Artifact [/card] [card] +name=Altar of the Pantheon +auto=alterdevoffset:1 controller +auto=@movedto(this|nonbattlezone) from(battlefield):alterdevoffset:-1 controller +auto=this(variable{type:*[god;demigod]:mybattlefieldplustype:enchantment[legendary]:mybattlefieldplusend}>0) {T}:ability$! name(choose a color) choice name(Add White) add{W} _ choice name(Add Blue) add{U} _ choice name(Add Black) add{B} _ choice name(Add Red) add{R} _ choice name(Add Green) add{G}!$ controller && life:1 controller +auto=this(variable{type:*[god;demigod]:mybattlefieldplustype:enchantment[legendary]:mybattlefieldplusend}=0) {T}:ability$! name(choose a color) choice name(Add White) add{W} _ choice name(Add Blue) add{U} _ choice name(Add Black) add{B} _ choice name(Add Red) add{R} _ choice name(Add Green) add{G}!$ controller +text=Your devotion to each color and each combination of colors is increased by one. -- {T}: Add one mana of any color. If you control a God, a Demigod, or a legendary enchantment, you gain 1 life. +mana={3} +type=Artifact +[/card] +[card] name=Amaranthine Wall abilities=defender auto={2}:indestructible ueot @@ -1048,6 +1100,21 @@ power=0 toughness=6 [/card] [card] +name=Amareth, the Lustrous +abilities=flying +auto=@movedTo(planeswalker|myBattlefield):all(trigger[to]) transforms((,newability[reveal:1 optionone name(May put in hand) target(planeswalker|reveal) moveto(myhand) optiononeend optiontwo name(Put back in library) target(*|reveal) moveto(mylibrary) optiontwoend revealend])) oneshot +auto=@movedTo(creature|myBattlefield):all(trigger[to]) transforms((,newability[reveal:1 optionone name(May put in hand) target(creature|reveal) moveto(myhand) optiononeend optiontwo name(Put back in library) target(*|reveal) moveto(mylibrary) optiontwoend revealend])) oneshot +auto=@movedTo(land[-creature]|myBattlefield):all(trigger[to]) transforms((,newability[reveal:1 optionone name(May put in hand) target(land|reveal) moveto(myhand) optiononeend optiontwo name(Put back in library) target(*|reveal) moveto(mylibrary) optiontwoend revealend])) oneshot +auto=@movedTo(enchantment[-creature]|myBattlefield):all(trigger[to]) transforms((,newability[reveal:1 optionone name(May put in hand) target(enchantment|reveal) moveto(myhand) optiononeend optiontwo name(Put back in library) target(*|reveal) moveto(mylibrary) optiontwoend revealend])) oneshot +auto=@movedTo(artifact[-creature;-land;-enchantment]|myBattlefield):all(trigger[to]) transforms((,newability[reveal:1 optionone name(May put in hand) target(artifact|reveal) moveto(myhand) optiononeend optiontwo name(Put back in library) target(*|reveal) moveto(mylibrary) optiontwoend revealend])) oneshot +text=Flying -- Whenever another permanent enters the battlefield under your control, look at the top card of your library. If it shares a card type with that permanent, you may reveal that card and put it into your hand. +mana={3}{G}{W}{U} +type=Legendary Creature +subtype=Dragon +power=6 +toughness=6 +[/card] +[card] name=Amateur Auteur auto={S}:destroy target(enchantment) text=Sacrifice Amateur Auteur: Destroy target enchantment. @@ -1124,6 +1191,19 @@ power=4 toughness=4 [/card] [card] +name=Anavolver +other={3}{G}{B} name(Kicker {B}) +auto=if paid(alternative) then transforms((,newability[counter(1/1.1)],newability[{L:3}:regenerate])) forever +kicker={1}{U} +auto=kicker ifnot paid(alternative) then transforms((,newability[counter(1/1.2)],newability[flying])) forever +text=Kicker {1}{U} and/or {B} (You may pay an additional {1}{U} and/or {B} as you cast this spell.) -- If Anavolver was kicked with its {1}{U} kicker, it enters the battlefield with two +1/+1 counters on it and with flying. -- If Anavolver was kicked with its {B} kicker, it enters the battlefield with a +1/+1 counter on it and with "Pay 3 life: Regenerate Anavolver." +mana={3}{G} +type=Creature +subtype=Volver +power=3 +toughness=3 +[/card] +[card] name=Anax, Hardened in the Forge anyzone=type:manaR:mybattlefield/3 cdaactive auto=@movedTo(this|mygraveyard) from(battlefield):token(Satyr,Creature Satyr,1/1,red,cantblock) @@ -1219,6 +1299,13 @@ text={T}: Add one mana of any color to your mana pool. Spend this mana only to c type=Land [/card] [card] +name=Angel's Trumpet +auto=lord(creature) transforms((,newability[vigilance],newability[@each my end restriction{didntattack}:tap(noevent) && damage:1 controller])) +text=All creatures have vigilance. -- At the beginning of each player's end step, tap all untapped creatures that player controls that didn't attack this turn. Angel's Trumpet deals damage to the player equal to the number of creatures tapped this way. +mana={3} +type=Artifact +[/card] +[card] name=Angel Ang abilities=flying type=Creature @@ -1487,6 +1574,14 @@ mana={B}{R} type=Sorcery [/card] [card] +name=Animal Magnetism +auto=if type(*[creature;zpos<=5]|mylibrary)~morethan~0 then ability$!name(Choose creature card) name(Choose creature card) target(creature[zpos<=5]|opponentlibrary) moveto(opponentBattlefield) and!( moveto(opponentgraveyard) all(*[zpos<=5]|opponentlibrary) )! !$ opponent +auto=if type(*[creature;zpos<=5]|mylibrary)~equalto~0 then ability$!name(Reveal the top five cards) name(Reveal the top five cards) target(<5>*[zpos<=5]|opponentlibrary) moveto(opponentgraveyard)!$ opponent +text=Reveal the top five cards of your library. An opponent chooses a creature card from among them. Put that card onto the battlefield and the rest into your graveyard. +mana={4}{G} +type=Sorcery +[/card] +[card] name=Animal Sanctuary auto={T}:add{C} auto={2}{T}:counter(1/1,1) target(creature[bird;cat;dog;goat;ox;snake]) @@ -1507,6 +1602,15 @@ power=2 toughness=2 [/card] [card] +name=Animation Module +auto=@counteradded(1/1) from(*|mybattlefield):name(pay 1 for 1/1 Servo) pay[[{1}]] name(pay 1 for 1/1 Servo) token(Servo,Artifact Creature Servo,1/1) +auto={3}{T}:name(Add counter to a permanent) name(Add counter to a permanent) target(*[counter{any}]|battlefield) duplicatecounters(single) +auto={3}{T}:name(Add counter to a player) name(Add counter to a player) target(player) duplicatecounters(single) +text=Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token. -- {3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. +mana={1} +type=Artifact +[/card] +[card] name=Anje Falkenrath abilities=haste auto={T}{D(*|myhand)}:draw:1 controller @@ -5047,7 +5151,7 @@ target=*[instant;sorcery]|stack auto=fizzle auto=activate castcard(copied noevent) other={R} name(Reduced cast) -otherestriction=type(creature[power>=4]|mybattlefield)~morethan~0 +otherrestriction=type(creature[power>=4]|mybattlefield)~morethan~0 text=This spell costs {3} less to cast if you control a creature with power 4 or greater. -- Change the target of target spell or ability with a single target. mana={3}{R} type=Instant @@ -26646,8 +26750,8 @@ auto=@each cleanup restriction{compare(mygreenpoolcount)~morethan~0}:thisforeach auto=@each cleanup restriction{compare(myredpoolcount)~morethan~0}:thisforeach(variable{myredpoolcount})add{C} && removemana({R}) auto=@each cleanup restriction{compare(myblackpoolcount)~morethan~0}:thisforeach(variable{myblackpoolcount}) add{C} && removemana({B}) auto=@each cleanup restriction{compare(mywhitepoolcount)~morethan~0}:thisforeach(variable{mywhitepoolcount}) add{C} && removemana({W}) -auto=this(variable{type:managplustype:manauplusend}<7) transforms((removetypes,newability[becomes(Legendary Enchantment God)])) -auto=this(variable{type:managplustype:manauplusend}>6) transforms((Legendary Enchantment Creature)) +auto=this(variable{simic}<7) transforms((removetypes,newability[becomes(Legendary Enchantment God)])) +auto=this(variable{simic}>6) transforms((Legendary Enchantment Creature)) text=Indestructible -- As long as your devotion to green and blue is less than seven, Kruphix isn't a creature. -- You have no maximum hand size. -- If unused mana would empty from your mana pool, that mana becomes colorless instead. mana={3}{G}{U} type=Legendary Enchantment Creature @@ -36853,7 +36957,7 @@ toughness=6 [card] name=Quiet Speculation target=player -auto=Reveal:type:*:targetedpersonslibrary revealzone(targetedpersonslibrary) optionone name(Choose 3 cards with flashback) target(*[flashback]|reveal) moveto(ownergraveyard) optiononeend optiontwo name(put back) all(*|reveal) moveto(ownerlibrary) optiontwoend revealend +auto=Reveal:type:*:targetedpersonslibrary revealzone(targetedpersonslibrary) optionone name(Choose 3 cards with flashback) target(*[hasflashback]|reveal) moveto(ownergraveyard) optiononeend optiontwo name(put back) all(*|reveal) moveto(ownerlibrary) optiontwoend revealend text=Search target player's library for up to three cards with flashback and put them into that player's graveyard. Then the player shuffles his or her library. mana={1}{U} type=Sorcery @@ -40019,7 +40123,7 @@ type=Instant [/card] [card] name=Runic Repetition -target=*[flashback]|myexile +target=*[hasflashback]|myexile auto=moveto(myhand) text=Return target exiled card with flashback you own to your hand. mana={2}{U} @@ -50673,7 +50777,7 @@ toughness=1 [card] name=Tombfire target=player -auto=ability$!name(Exile flashback cards) all(*[flashback]|mygraveyard) moveto(myexile)!$ targetedplayer +auto=ability$!name(Exile flashback cards) all(*[hasflashback]|mygraveyard) moveto(myexile)!$ targetedplayer text=Target player exiles all cards with flashback from his or her graveyard. mana={B} type=Sorcery diff --git a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt index 95ba483a9..65f7c5e74 100644 --- a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt +++ b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt @@ -1188,7 +1188,7 @@ auto={C(0/0,0,Loyalty)}:name(+0: Draw 1 and remove Loyalty counters) draw:1 && c auto={C(0/0,0,Loyalty)}:name(+0: Draw 1 and remove Loyalty counters) draw:1 && counter(0/0,-20,loyalty) restriction{type(*[manacost=20;zpos=1]|mylibrary)~morethan~0} text=Kicker {2} -- When Jace, Mirror Mage enters the battlefield, if Jace was kicked, create a token that's a copy of Jace, Mirror Mage except it's not legendary and its starting loyalty is 1. -- +1: Scry 2. -- 0: Draw a card and reveal it. Remove a number of loyalty counters equal to that card's converted mana cost from Jace, Mirror Mage. mana={1}{U}{U} -type=Planeswalker +type=Legendary Planeswalker subtype=Jace [/card] [card] diff --git a/projects/mtg/bin/Res/sets/primitives/unsupported.txt b/projects/mtg/bin/Res/sets/primitives/unsupported.txt index 863524473..1a0fb3971 100644 --- a/projects/mtg/bin/Res/sets/primitives/unsupported.txt +++ b/projects/mtg/bin/Res/sets/primitives/unsupported.txt @@ -175,22 +175,6 @@ mana={B} type=Instant [/card] [card] -name=Aetherborn Marauder -abilities=flying,lifelink -text=Flying, lifelink -- When Aetherborn Marauder enters the battlefield, move any number of +1/+1 counters from other permanents you control onto Aetherborn Marauder. -mana={3}{B} -type=Creature -subtype=Aetherborn Rogue -power=2 -toughness=2 -[/card] -[card] -name=Aethermage's Touch -text=Reveal the top four cards of your library. You may put a creature card from among them onto the battlefield. It gains "At the beginning of your end step, return this creature to its owner's hand." Then put the rest of the cards revealed this way on the bottom of your library in any order. -mana={2}{W}{U} -type=Instant -[/card] -[card] name=Agent of Acquisitions text=Draft Agent of Acquisitions face up. -- Instead of drafting a card from a booster pack, you may draft each card in that booster pack, one at a time. If you do, turn Agent of Acquisitions face down and you can't draft cards for the rest of this draft round. (You may look at booster packs passed to you.) mana={2} @@ -200,28 +184,12 @@ power=2 toughness=1 [/card] [card] -name=Aggression -text=Enchant non-Wall creature -- Enchanted creature has first strike and trample. -- At the beginning of the end step of enchanted creature's controller, destroy that creature if it didn't attack this turn. -mana={2}{R} -type=Enchantment -subtype=Aura -[/card] -[card] name=Agyrem text=Whenever a white creature dies, return it to the battlefield under its owner's control at the beginning of the next end step. -- Whenever a nonwhite creature dies, return it to its owner's hand at the beginning of the next end step. -- Whenever you roll {C}, creatures can't attack you until a player planeswalks. type=Plane subtype=Ravnica [/card] [card] -name=Ajani's Chosen -text=Whenever an enchantment enters the battlefield under your control, put a 2/2 white Cat creature token onto the battlefield. If that enchantment is an Aura, you may attach it to the token. -mana={2}{W}{W} -type=Creature -subtype=Cat Soldier -power=3 -toughness=3 -[/card] -[card] name=Akki Lavarunner text=Haste -- Whenever Akki Lavarunner deals damage to an opponent, flip it. -- -- ——— -- -- Tok-Tok, Volcano Born -- Legendary Creature — Goblin Shaman -- -- Protection from red -- If a red source would deal damage to a player, it deals that much damage plus 1 to that player instead. -- 2/2 mana={3}{R} @@ -266,12 +234,6 @@ mana={W} type=Sorcery [/card] [card] -name=Allure of the Unknown -text=Reveal the top six cards of your library. An opponent exiles a nonland card from among them, then you put the rest into your hand. That opponent may cast the exiled card without paying its mana cost. -mana={3}{B}{R} -type=Sorcery -[/card] -[card] name=Alms Collector text=Flash -- If an opponent would draw two or more cards, instead you and that player each draw a card. mana={3}{W} @@ -295,27 +257,12 @@ mana={R} type=Enchantment [/card] [card] -name=Altar of the Pantheon -text=Your devotion to each color and each combination of colors is increased by one. -- {T}: Add one mana of any color. If you control a God, a Demigod, or a legendary enchantment, you gain 1 life. -mana={3} -type=Artifact -[/card] -[card] name=Alter Reality text=Change the text of target spell or permanent by replacing all instances of one color word with another. (This effect lasts indefinitely.) -- Flashback {1}{U} (You may cast this card from your graveyard for its flashback cost. Then exile it.) mana={1}{U} type=Instant [/card] [card] -name=Amareth, the Lustrous -text=Flying -- Whenever another permanent enters the battlefield under your control, look at the top card of your library. If it shares a card type with that permanent, you may reveal that card and put it into your hand. -mana={3}{G}{W}{U} -type=Legendary Creature -subtype=Dragon -power=6 -toughness=6 -[/card] -[card] name=Ambiguity text=Whenever a player plays a spell that counters a spell that has been played or a player plays a spell that comes into play with counters, that player may counter the next spell played or put an additional counter on a permanent that has already been played, but not countered. mana={2}{U}{U} @@ -349,33 +296,12 @@ power=2 toughness=2 [/card] [card] -name=Anavolver -text=Kicker {1}{U} and/or {B} (You may pay an additional {1}{U} and/or {B} as you cast this spell.) -- If Anavolver was kicked with its {1}{U} kicker, it enters the battlefield with two +1/+1 counters on it and with flying. -- If Anavolver was kicked with its {B} kicker, it enters the battlefield with a +1/+1 counter on it and with "Pay 3 life: Regenerate Anavolver." -mana={3}{G} -type=Creature -subtype=Volver -power=3 -toughness=3 -[/card] -[card] name=Angel's Grace text=Split second (As long as this spell is on the stack, players can't cast spells or activate abilities that aren't mana abilities.) -- You can't lose the game this turn and your opponents can't win the game this turn. Until end of turn, damage that would reduce your life total to less than 1 reduces it to 1 instead. mana={W} type=Instant [/card] [card] -name=Angel's Trumpet -text=All creatures have vigilance. -- At the beginning of each player's end step, tap all untapped creatures that player controls that didn't attack this turn. Angel's Trumpet deals damage to the player equal to the number of creatures tapped this way. -mana={3} -type=Artifact -[/card] -[card] -name=Animal Magnetism -text=Reveal the top five cards of your library. An opponent chooses a creature card from among them. Put that card onto the battlefield and the rest into your graveyard. -mana={4}{G} -type=Sorcery -[/card] -[card] name=Animate Library text=Enchant your library -- Enchanted library is an artifact creature on the battlefield with power and toughness each equal to the number of cards in it. It's still a library. -- If enchanted library would leave the battlefield, exile Animate Library instead. mana={4}{U}{U} @@ -383,13 +309,6 @@ type=Enchantment subtype=Aura [/card] [card] -name=Animation Module -auto=@counter(1/1,1) target(*|myBattlefield):pay({1}) create(Servo:Artifact Creature Servo:1/1) -text=Whenever one or more +1/+1 counters are placed on a permanent you control, you may pay {1}. If you do, create a 1/1 colorless Servo artifact creature token. -- {3}, {T}: Choose a counter on target permanent or player. Give that permanent or player another counter of that kind. -mana={1} -type=Artifact -[/card] -[card] name=Animus of Predation text=Draft Animus of Predation face up. -- As you draft a card, you may remove it from the draft face up. (It isn't in your card pool.) -- If you removed a creature card with flying from the draft with cards named Animus of Predation, Animus of Predation has flying. The same is true for first strike, double strike, deathtouch, haste, hexproof, indestructible, lifelink, menace, reach, and vigilance. mana={4}{G} diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 2fda5a071..f40a85ff5 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -427,7 +427,7 @@ private: { if (color) { - intValue += zone->countTotalManaSymbols(tc, color); + intValue += card->controller()->devotionOffset + zone->countTotalManaSymbols(tc, color); // Increase total devotion with an offset (e.g. Altar of the Pantheon) } else { @@ -576,6 +576,10 @@ private: { intValue = (s == "psurveiloffset")?card->controller()->surveilOffset:card->controller()->opponent()->surveilOffset; } + else if (s == "pdevotionoffset" || s == "odevotionoffset") + { + intValue = (s == "pdevotionoffset")?card->controller()->devotionOffset:card->controller()->opponent()->devotionOffset; + } else if (s == "praidcount" || s == "oraidcount") { intValue = (s == "praidcount")?card->controller()->raidcount:card->controller()->opponent()->raidcount; @@ -1115,7 +1119,7 @@ public: counthybrid += zone->countDevotion(dtc, color1, color2); } SAFE_DELETE(dtc); - return counthybrid; + return card->controller()->devotionOffset + counthybrid; // Increase total devotion with an offset (e.g. Altar of the Pantheon) } int countCardNameinZone(string name, MTGGameZone * zone) @@ -2356,7 +2360,7 @@ public: class AADuplicateCounters: public ActivatedAbility { public: - bool allcounters; + bool allcounters, single; AADuplicateCounters(GameObserver* observer, int id, MTGCardInstance * source, Targetable * target, ManaCost * cost = NULL); int resolve(); const string getMenuText(); @@ -5046,6 +5050,19 @@ public: AAAlterSurveilOffset * clone() const; ~AAAlterSurveilOffset(); }; +//Devotion Offset +class AAAlterDevotionOffset: public ActivatedAbilityTP +{ +public: + int devotionOffset; + + AAAlterDevotionOffset(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int devotionOffset, ManaCost * _cost = NULL, + int who = TargetChooser::UNSET); + int resolve(); + const string getMenuText(); + AAAlterDevotionOffset * clone() const; + ~AAAlterDevotionOffset(); +}; /* Standard Damager, can choose a NEW target each time the price is paid */ class TADamager: public TargetAbility { diff --git a/projects/mtg/include/CardDescriptor.h b/projects/mtg/include/CardDescriptor.h index 8c1f50329..ac5f1c6cd 100644 --- a/projects/mtg/include/CardDescriptor.h +++ b/projects/mtg/include/CardDescriptor.h @@ -43,11 +43,13 @@ class CardDescriptor: public MTGCardInstance int zposComparisonMode; int zposition; int hasKickerCost; + int hasFlashbackCost; int anyCounter; int init(); CardDescriptor(); void unsecureSetKicked(int i); void unsecureSetHasKickerCost(int i); + void unsecureSetHasFlashbackCost(int i); void unsecureSetTapped(int i); void unsecuresetfresh(int k); void unsecuresetrecent(int j); diff --git a/projects/mtg/include/Player.h b/projects/mtg/include/Player.h index b32d6d5ca..ab0e3dac9 100644 --- a/projects/mtg/include/Player.h +++ b/projects/mtg/include/Player.h @@ -47,6 +47,7 @@ public: int numOfCommandCast; int monarch; int surveilOffset; + int devotionOffset; int epic; int forcefield; int dealsdamagebycombat; diff --git a/projects/mtg/src/AllAbilities.cpp b/projects/mtg/src/AllAbilities.cpp index 5b38ff65e..af531d6e0 100644 --- a/projects/mtg/src/AllAbilities.cpp +++ b/projects/mtg/src/AllAbilities.cpp @@ -1133,6 +1133,44 @@ AAAlterSurveilOffset::~AAAlterSurveilOffset() { } +//AA Devotion Offset +AAAlterDevotionOffset::AAAlterDevotionOffset(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int devotionOffset, ManaCost * _cost, + int who) : + ActivatedAbilityTP(observer, _id, _source, _target, _cost, who), devotionOffset(devotionOffset) +{ +} + +int AAAlterDevotionOffset::resolve() +{ + Damageable * _target = (Damageable *) getTarget(); + if (_target) + { + Player * pTarget = (Player*)_target; + if(pTarget) + { + pTarget->devotionOffset += devotionOffset; + if(pTarget->devotionOffset < 0) + pTarget->devotionOffset = 0; + } + } + return 0; +} + +const string AAAlterDevotionOffset::getMenuText() +{ + WParsedInt parsedNum(devotionOffset); + return _(parsedNum.getStringValue() + " Devotion Offset ").c_str(); +} + +AAAlterDevotionOffset * AAAlterDevotionOffset::clone() const +{ + return NEW AAAlterDevotionOffset(*this); +} + +AAAlterDevotionOffset::~AAAlterDevotionOffset() +{ +} + //AA Yidaro Count AAAlterYidaroCount::AAAlterYidaroCount(GameObserver* observer, int _id, MTGCardInstance * _source, Targetable * _target, int yidarocount, ManaCost * _cost, int who) : @@ -2376,6 +2414,7 @@ ActivatedAbility(observer, id, source, cost, 0) { this->GetId(); allcounters = false; + single = false; } int AADuplicateCounters::resolve() @@ -2390,13 +2429,21 @@ int AADuplicateCounters::resolve() if(pTarget && pTarget->poisonCount) { - MTGAbility * a = NEW AAAlterPoison(game, game->mLayers->actionLayer()->getMaxId(), source, target, pTarget->poisonCount, NULL); + MTGAbility * a = NULL; + if(single) + a = NEW AAAlterPoison(game, game->mLayers->actionLayer()->getMaxId(), source, target, pTarget->poisonCount, NULL); + else + a = NEW AAAlterPoison(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL); a->oneShot = true; pcounters.push_back(a); } else if(pTarget && pTarget->energyCount) { - MTGAbility * a = NEW AAAlterEnergy(game, game->mLayers->actionLayer()->getMaxId(), source, target, pTarget->energyCount, NULL); + MTGAbility * a = NULL; + if(single) + a = NEW AAAlterEnergy(game, game->mLayers->actionLayer()->getMaxId(), source, target, 1, NULL); + else + a = NEW AAAlterEnergy(game, game->mLayers->actionLayer()->getMaxId(), source, target, pTarget->energyCount, NULL); a->oneShot = true; pcounters.push_back(a); } @@ -2406,7 +2453,11 @@ int AADuplicateCounters::resolve() for(size_t i = 0; i < counters->counters.size(); ++i) { Counter * counter = counters->counters[i]; - MTGAbility * a = NEW AACounter(game, game->mLayers->actionLayer()->getMaxId(), source, cTarget,"", counter->name.c_str(), counter->power, counter->toughness, counter->nb, 0); + MTGAbility * a = NULL; + if(single) + a = NEW AACounter(game, game->mLayers->actionLayer()->getMaxId(), source, cTarget,"", counter->name.c_str(), counter->power, counter->toughness, 1, 0); + else + a = NEW AACounter(game, game->mLayers->actionLayer()->getMaxId(), source, cTarget,"", counter->name.c_str(), counter->power, counter->toughness, counter->nb, 0); a->oneShot = true; pcounters.push_back(a); } diff --git a/projects/mtg/src/CardDescriptor.cpp b/projects/mtg/src/CardDescriptor.cpp index 441d7747e..9be168a06 100644 --- a/projects/mtg/src/CardDescriptor.cpp +++ b/projects/mtg/src/CardDescriptor.cpp @@ -22,6 +22,7 @@ CardDescriptor::CardDescriptor() zposComparisonMode = COMPARISON_NONE; zposition = -1; hasKickerCost = 0; + hasFlashbackCost = 0; compareName =""; nameComparisonMode = COMPARISON_NONE; colorComparisonMode = COMPARISON_NONE; @@ -62,6 +63,11 @@ void CardDescriptor::unsecureSetHasKickerCost(int k) hasKickerCost = k; } +void CardDescriptor::unsecureSetHasFlashbackCost(int k) +{ + hasFlashbackCost = k; +} + void CardDescriptor::unsecureSetTapped(int i) { tapped = i; @@ -241,6 +247,11 @@ MTGCardInstance * CardDescriptor::match(MTGCardInstance * card) match = NULL; } + if ((hasFlashbackCost == -1 && card->getManaCost()->getFlashback()) || (hasFlashbackCost == 1 && !card->getManaCost()->getFlashback())) + { + match = NULL; + } + if ((tapped == -1 && card->isTapped()) || (tapped == 1 && !card->isTapped())) { match = NULL; diff --git a/projects/mtg/src/CardGui.cpp b/projects/mtg/src/CardGui.cpp index 495d6613d..f950bcbd4 100644 --- a/projects/mtg/src/CardGui.cpp +++ b/projects/mtg/src/CardGui.cpp @@ -1503,6 +1503,18 @@ bool CardGui::FilterCard(MTGCard * _card,string filter) cd.unsecureSetHasKickerCost(1); } } + //Has kicker cost + else if (attribute.find("hasflashback") != string::npos) + { + if (minus) + { + cd.unsecureSetHasFlashbackCost(-1); + } + else + { + cd.unsecureSetHasFlashbackCost(1); + } + } //Token else if (attribute.find("token") != string::npos) { diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 2213d9597..6233b4abf 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -3488,7 +3488,7 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } - //set surveil offset controller (eg. Enhanced Surveillance) + //set surveil offset of a player (eg. Enhanced Surveillance) vector splitSurveilOffset = parseBetween(s, "altersurvoffset:", " ", false); if (splitSurveilOffset.size()) { @@ -3499,6 +3499,17 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG return a; } + //set devotion offset of a player (eg. Altar of the Pantheon) + vector splitDevotionOffset = parseBetween(s, "alterdevoffset:", " ", false); + if (splitDevotionOffset.size()) + { + int devotionOffset = atoi(splitDevotionOffset[1].c_str()); + Targetable * t = spell ? spell->getNextTarget() : NULL; + MTGAbility * a = NEW AAAlterDevotionOffset(observer, id, card, t, devotionOffset, NULL, who); + a->oneShot = 1; + return a; + } + //prevent next damage vector splitPrevent = parseBetween(s, "prevent:", " ", false); if (splitPrevent.size()) @@ -3916,6 +3927,8 @@ MTGAbility * AbilityFactory::parseMagicLine(string s, int id, Spell * spell, MTG string counterString = splitDuplicateCounters[1]; if(counterString.find("all") != string::npos) ((AADuplicateCounters*)a)->allcounters = true; + else if(counterString.find("single") != string::npos) + ((AADuplicateCounters*)a)->single = true; return a; } //remove single counter of any type diff --git a/projects/mtg/src/Player.cpp b/projects/mtg/src/Player.cpp index ca23ec6d3..f0d1d70da 100644 --- a/projects/mtg/src/Player.cpp +++ b/projects/mtg/src/Player.cpp @@ -39,6 +39,7 @@ Player::Player(GameObserver *observer, string file, string fileSmall, MTGDeck * numOfCommandCast = 0; monarch = 0; surveilOffset = 0; + devotionOffset = 0; epic = 0; forcefield = 0; dealsdamagebycombat = 0; diff --git a/projects/mtg/src/Rules.cpp b/projects/mtg/src/Rules.cpp index e1681c80e..66c68a2f4 100644 --- a/projects/mtg/src/Rules.cpp +++ b/projects/mtg/src/Rules.cpp @@ -606,6 +606,7 @@ void Rules::initGame(GameObserver *g, bool currentPlayerSet) p->numOfCommandCast = initState.playerData[i].player->numOfCommandCast; p->monarch = initState.playerData[i].player->monarch; p->surveilOffset = initState.playerData[i].player->surveilOffset; + p->devotionOffset = initState.playerData[i].player->devotionOffset; if (initState.playerData[i].player->mAvatarName.size()) { p->mAvatarName = initState.playerData[i].player->mAvatarName; diff --git a/projects/mtg/src/TargetChooser.cpp b/projects/mtg/src/TargetChooser.cpp index 020584ef6..dfd3b9961 100644 --- a/projects/mtg/src/TargetChooser.cpp +++ b/projects/mtg/src/TargetChooser.cpp @@ -542,6 +542,18 @@ TargetChooser * TargetChooserFactory::createTargetChooser(string s, MTGCardInsta cd->unsecureSetHasKickerCost(1); } } + //Has flashback cost + else if (attribute.find("hasflashback") != string::npos) + { + if (minus) + { + cd->unsecureSetHasFlashbackCost(-1); + } + else + { + cd->unsecureSetHasFlashbackCost(1); + } + } //Token else if (attribute.find("token") != string::npos) {