From e1df4e5072a341af32db9b3bbc64770a86cbcefb Mon Sep 17 00:00:00 2001 From: valfieri Date: Tue, 13 Oct 2020 18:32:51 +0200 Subject: [PATCH] Improved Life gain trigger (now it's possible to specify a "from" clause and it's possible to add the "limitOnceATurn" restriction) and fixed all the primitives with gives life on life gain event without producing any loop and reviewed all the primitives with the "@lifeof" trigger. --- .../bin/Res/sets/primitives/borderline.txt | 47 ++++++++++--------- projects/mtg/bin/Res/sets/primitives/mtg.txt | 28 +++++------ projects/mtg/include/AllAbilities.h | 16 +++++-- projects/mtg/src/MTGAbility.cpp | 24 +++++----- projects/mtg/src/MTGRules.cpp | 2 +- 5 files changed, 64 insertions(+), 53 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index 238b65c57..d6472f301 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -723,7 +723,7 @@ toughness=4 [/card] [card] name=Alhammarret's Archive -auto=@lifeof(player) except(Alhammarret's Archive): life:thatmuch +auto=@lifeof(player) from(*[-Alhammarret's Archive]):life:thatmuch auto=replacedraw draw:2 noreplace text=If you would gain life, you gain twice that much life instead. -- If you would draw a card except the first one you draw in each of your draw steps, draw two cards instead. mana={5} @@ -1138,7 +1138,7 @@ toughness=4 name=Angel of Vitality abilities=flying auto=this(controllerlife > 24) 2/2 -auto=@lifeof(player) except(Angel of Vitality): life:1 +auto=@lifeof(player) from(*[-Angel of Vitality]):life:1 controller text=Flying -- If you would gain life, you gain that much life plus 1 instead. -- Angel of Vitality gets +2/+2 as long as you have 25 or more life. mana={2}{W} type=Creature @@ -1428,7 +1428,7 @@ type=Instant [card] name=Aphemia, the Cacophony abilities=flying -auto=@each my endofturn:may moveto(exile) target(enchantment|myGraveyrad) && token(Zombie,Creature Zombie,2/2,black) +auto=@each my endofturn:may moveto(exile) target(enchantment|myGraveyard) && token(Zombie,Creature Zombie,2/2,black) text=Flying -- At the beginning of your end step, you may exile an enchantment card from your graveyard. If you do, create a 2/2 black Zombie creature token. mana={1}{B} type=Legendary Enchantment Creature @@ -4297,7 +4297,7 @@ type=Artifact [card] name=Bloodthirsty Aerialist abilities=flying -auto=@lifeof(player): counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) text=Flying -- Whenever you gain life, put a +1/+1 counter on Bloodthirsty Aerialist. mana={1}{B}{B} type=Creature @@ -4716,7 +4716,7 @@ type=Sorcery [/card] [card] name=Boon Reflection -auto=@lifeof(player) except(Boon Reflection): life:thatmuch +auto=@lifeof(player) from(*[-Boon Reflection]):life:thatmuch text=If you would gain life, you gain twice that much life instead. mana={4}{W} type=Enchantment @@ -9451,7 +9451,7 @@ toughness=3 [/card] [card] name=Dawn of Hope -auto=@lifeof(player):pay({2}) draw:1 +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):pay({2}) draw:1 auto={3}{W}:create(soldier:creature soldier:1/1:white:lifelink) text=Whenever you gain life, you may pay {2}. If you do, draw a card. -- {3}{W}: Create a 1/1 white Soldier creature token with lifelink. mana={1}{W} @@ -13045,7 +13045,7 @@ type=Sorcery [/card] [card] name=Epicure of Blood -auto=@lifeof(player):life:-1 opponent +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality]):life:-1 opponent text=Whenever you gain life, each opponent loses 1 life. mana={4}{B} type=Creature @@ -13893,7 +13893,7 @@ type=Instant [card] name=Famished Paladin auto=doesnotuntap -auto=@lifeof(player):untap(this) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):untap(this) text=Famished Paladin doesn't untap during your untap step. -- Whenever you gain life, untap Famished Paladin. mana={1}{W} type=Creature @@ -14834,8 +14834,10 @@ type=Enchantment [/card] [card] name=Firesong and Sunspeaker -auto=lord(instant,sorcery[red]|mycastingzone): lifelink -auto=@lifeof(player) from (*[instant;sorcery[white]]|mystack):damage:3 target(creature,player,planeswalker) +auto=@damaged(creature) from(*[instant;sorcery;red]|mystack,mygraveyard):life:thatmuch controller +auto=@damageof(player) from(*[instant;sorcery;red]|mystack,mygraveyard):life:thatmuch controller +auto=@damagefoeof(player) from(*[instant;sorcery;red]|mystack,mygraveyard):life:thatmuch controller +auto=@lifeof(player) from(*[instant;sorcery;white]|mystack,mygraveyard)):damage:3 target(creature,player) text=Red instant and sorcery spells you control have lifelink. -- Whenever a white instant or sorcery spell causes you to gain life, Firesong and Sunspeaker deals 3 damage to target creature or player. mana={4}{R}{W} type=Legendary Creature @@ -16573,7 +16575,7 @@ type=Sorcery [/card] [card] name=Gideon's Company -auto=@lifeof(player):counter(1/1,2) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,2) auto={3}{W}:counter(0/0,1,Loyalty) target(planeswalker[gideon]) text=Whenever you gain life, put two +1/+1 counters on Gideon's Company. -- {3}{W}: Put a loyalty counter on target Gideon planeswalker. mana={3}{W} @@ -18562,7 +18564,7 @@ type=Legendary Land [/card] [card] name=Hallowed Priest -auto=@lifeof(player):counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) text=Whenever you gain life, put a +1/+1 counter on Hallowed Priest mana={1}{W} type=Creature @@ -19207,7 +19209,7 @@ name=Heliod, Sun-Crowned abilities=indestructible auto=this(variable{type:manaw}<5) transforms((removetypes,newability[becomes(Legendary Enchantment God)])) auto=this(variable{type:manaw}>4) transforms((Legendary Enchantment Creature)) -auto=@lifeof(player):counter(1/1,1) target(creature,enchantment|myBattlefield) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) target(creature,enchantment|myBattlefield) auto={1}{W}:lifelink target(other creature) ueot text=Indestructible -- As long as your devotion to white is less than five, Heliod isn’t a creature. -- Whenever you gain life, put a +1/+1 counter on target creature or enchantment you control. -- {1}{W}: Another target creature gains lifelink until end of turn. mana={2}{W} @@ -25823,7 +25825,7 @@ subtype=Equipment [/card] [card] name=Marauding Blight-Priest -auto=@lifeof(player):life:-1 opponent +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):life:-1 opponent text=Whenever you gain life, each opponent loses 1 life. mana={2}{B} type=Creature @@ -29625,7 +29627,7 @@ toughness=3 [card] name=Oloro, Ageless Ascetic auto=@each my upkeep:life:2 controller -auto=@lifeof(player):pay({1}) draw:1 controller && life:-1 opponent +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):pay({1}) draw:1 controller && life:-1 opponent #wagic doesn't have command zone text=At the beginning of your upkeep, you gain 2 life. -- Whenever you gain life, you may pay {1}. If you do, draw a card and each opponent loses 1 life. -- At the beginning of your upkeep, if Oloro, Ageless Ascetic is in the command zone, you gain 2 life. mana={3}{W}{U}{B} @@ -34345,7 +34347,8 @@ toughness=2 [card] name=Rhox Faithmender abilities=lifelink -auto=@lifeof(player) except(Rhox Faithmender): life:thatmuch +auto=@lifeof(player) from(*[-Rhox Faithmender]):life:thatmuch +auto=@damaged(creature,player) from(Rhox Faithmender|myBattlefield):life:thatmuch text=Lifelink (Damage dealt by this creature also causes you to gain that much life.) -- If you would gain life, you gain twice that much life instead. mana={3}{W} type=Creature @@ -36625,7 +36628,7 @@ toughness=5 [card] name=Scion of the Swarm abilities=flying -auto=@lifeof(player):counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) text=Flying -- Whenever you gain life, put a +1/+1 counter on Scion of the Swarm. mana={3}{B}{B} type=Creature @@ -40640,7 +40643,7 @@ toughness=4 [card] name=Spellpyre Phoenix abilities=flying -auto=moveTo(myHand) target(*[instant;sorcery{_cycling_}|myGravyeard) +auto=moveTo(myHand) target(*[instant;sorcery{_cycling_}|myGraveyard) autograveyard=if type(@cycled(*|myHand)~morethan~2 then moveTo(myhand) target(Spellpyre Phoenix|myGraveyard)) text=Flying -- When Spellpyre Phoenix enters the battlefield, you may return target instant or sorcery card with a cycling ability from your graveyard to your hand. -- At the beginning of each end step, if you cycled two or more cards this turn, return Spellpyre Phoenix from your graveyard to your hand. mana={3}{R}{R} @@ -46234,7 +46237,7 @@ toughness=4 [/card] [card] name=Twinblade Paladin -auto=@lifeof(player): counter(1/1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1) auto=this(controllerlife > 24) double strike text=Whenever you gain life, put a +1/+1 counter on Twinblade Paladin. -- As long as you have 25 or more life, Twinblade Paladin has double strike. (It deals both first-strike and regular combat damage.) mana={3}{W} @@ -48083,8 +48086,8 @@ toughness=4 [/card] [card] name=Vito, Thorn of the Dusk Rose -auto=@lifeof(player):dynamicability -auto={3}{B}{B}:all(creature|myBattlefield) lifelink ueot +auto=@lifeof(player):life:-thatmuch opponent +auto={3}{B}{B}:all(creature|myBattlefield) transforms((,newability[lifelink])) ueot text=Whenever you gain life, target opponent loses that much life. -- {3}{B}{B}: Creatures you control gain lifelink until end of turn. mana={2}{B} type=Legendary Creature @@ -49165,7 +49168,7 @@ type=Artifact [/card] [card] name=Well of Lost Dreams -auto=@lifeof(player):foreach:life: may pay({lifeof}) draw:thatmuch controller +auto=@lifeof(player):thisforeach(variable{thatmuch}) ability$!name(Pay 1 and draw 1) pay[[{1}]] name(Pay 1 and draw 1) draw:1?name(Don't pay) donothing!$ controller text=Whenever you gain life, you may pay {X}, where X is less than or equal to the amount of life you gained. If you do, draw X cards. mana={4} type=Artifact diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 596b2921b..86b7cd17d 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -1973,7 +1973,7 @@ type=Enchantment [/card] [card] name=Ajani's Pridemate -auto=@lifeof(player):counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) text=Whenever you gain life, put a +1/+1 counter on Ajani's Pridemate. mana={1}{W} type=Creature @@ -5145,7 +5145,7 @@ toughness=4 [card] name=Archangel of Thune abilities=flying,lifelink -auto=@lifeof(player):all(creature|mybattlefield) counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):all(creature|mybattlefield) counter(1/1,1) text=Flying. -- Lifelink. -- Whenever you gain life, put a +1/+1 counter on each creature you control. mana={3}{W}{W} type=Creature @@ -12217,7 +12217,7 @@ type=Enchantment [/card] [card] name=Bloodbond Vampire -auto=@lifeof(player):counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) text=Whenever you gain life, put a +1/+1 counter on Bloodbond Vampire. mana={2}{B}{B} type=Creature @@ -20322,7 +20322,7 @@ toughness=1 [card] name=Cliffhaven Vampire abilities=flying -auto=@lifeof(player):life:-1 opponent +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):life:-1 opponent text=Flying -- Whenever you gain life, each opponent loses 1 life. mana={2}{W}{B} type=Creature @@ -27886,7 +27886,7 @@ subtype=Aura [card] name=Defiant Bloodlord abilities=flying -auto=@lifeof(player):life:-thatmuch target(opponent) +auto=@lifeof(player):life:-thatmuch opponent text=Flying -- Whenever you gain life, target opponent loses that much life. mana={5}{B}{B} type=Creature @@ -32113,7 +32113,7 @@ toughness=4 [card] name=Drogskol Reaver abilities=flying,double strike,lifelink -auto=@lifeof(player):draw:1 controller +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):draw:1 controller text=Flying, double strike, lifelink -- Whenever you gain life, draw a card. mana={5}{W}{U} type=Creature @@ -61130,7 +61130,7 @@ toughness=2 [/card] [card] name=Kalastria Nightwatch -auto=@lifeof(player):flying ueot +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):flying ueot text=Whenever you gain life, Kalastria Nightwatch gains flying until end of turn. mana={4}{B} type=Creature @@ -61527,7 +61527,7 @@ type=Sorcery [/card] [card] name=Karlov of the Ghost Council -auto=@lifeof(player):counter(1/1,2) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,2) auto={W}{B}{C(1/1,-6)}:moveto(exile) target(creature) text=Whenever you gain life, put two +1/+1 counters on Karlov of the Ghost Council. -- {W}{B}, Remove six +1/+1 counters from Karlov of the Ghost Council: Exile target creature. mana={W}{B} @@ -70027,7 +70027,7 @@ toughness=1 [card] name=Malakir Familiar abilities=flying,deathtouch -auto=@lifeof(player):1/1 ueot +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):1/1 ueot text=Flying, deathtouch -- Whenever you gain life, Malakir Familiar gets +1/+1 until end of turn. mana={2}{B} type=Creature @@ -80014,7 +80014,7 @@ toughness=1 [/card] [card] name=Nirkana Assassin -auto=@lifeof(player):deathtouch ueot +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):deathtouch ueot text=Whenever you gain life, Nirkana Assassin gains deathtouch until end of turn. (Any amount of damage it deals to a creature is enough to destroy it.) mana={2}{B} type=Creature @@ -98753,7 +98753,7 @@ toughness=3 [/card] [card] name=Sanguine Bond -auto=@lifeof(player):dynamicability +auto=@lifeof(player):life:-thatmuch opponent text=Whenever you gain life, target opponent loses that much life. mana={3}{B}{B} type=Enchantment @@ -101056,7 +101056,7 @@ type=Instant [/card] [card] name=Searing Meditation -auto=@lifeof(player):pay({2}) target(creature,player) damage:2 +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):pay({2}) target(creature,player) damage:2 text=Whenever you gain life, you may pay {2}. If you do, Searing Meditation deals 2 damage to target creature or player. mana={1}{R}{W} type=Enchantment @@ -102261,7 +102261,7 @@ type=Sorcery [/card] [card] name=Serene Steward -auto=@lifeof(player):pay({W}) counter(1/1) target(creature) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):pay({W}) counter(1/1) target(creature) text=Whenever you gain life, you may pay {W}. If you do, put a +1/+1 counter on target creature. mana={1}{W} type=Creature @@ -130975,7 +130975,7 @@ toughness=5 [card] name=Wall of Limbs abilities=defender -auto=@lifeof(player):counter(1/1,1) +auto=@lifeof(player) from(*[-Alhammarret's Archive;-Angel of Vitality;-Boon Reflection]):counter(1/1,1) auto={5}{B}{B}{S}:name(Lose Life) target(player) life:-storedpower text=Defender (This creature can't attack.) -- Whenever you gain life, put a +1/+1 counter on Wall of Limbs. -- {5}{B}{B}, Sacrifice Wall of Limbs: Target player loses X life, where X is Wall of Limbs's power. mana={2}{B} diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 8baca8589..a825a8210 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -1686,8 +1686,9 @@ public: bool limitOnceATurn; int triggeredTurn; TrCardMutated(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc,bool once = false,bool limitOnceATurn = false) : - Trigger(observer, id, source,once, tc) + Trigger(observer, id, source,once, tc),limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) @@ -1889,20 +1890,26 @@ public: TargetChooser * fromTc; int type;//this allows damagenoncombat and combatdamage to share this trigger bool sourceUntapped, thiscontroller, thisopponent; + bool limitOnceATurn; + int triggeredTurn; MTGCardInstance * gainException; //added exception to avid a gainlife loop (eg. Angels of Vitality) - TrLifeGained(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0,bool sourceUntapped = false,bool once = false, bool thiscontroller = false, bool thisopponent = false, MTGCardInstance * gainException = NULL) : - Trigger(observer, id, source, once , tc), fromTc(fromTc), type(type) , sourceUntapped(sourceUntapped) , thiscontroller(thiscontroller) , thisopponent(thisopponent), gainException(gainException) + TrLifeGained(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, TargetChooser * fromTc = NULL, int type = 0,bool sourceUntapped = false,bool once = false, bool thiscontroller = false, bool thisopponent = false, bool limitOnceATurn = false, MTGCardInstance * gainException = NULL) : + Trigger(observer, id, source, once , tc), fromTc(fromTc), type(type) , sourceUntapped(sourceUntapped), thiscontroller(thiscontroller), thisopponent(thisopponent), limitOnceATurn(limitOnceATurn), gainException(gainException) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) { WEventLife * e = dynamic_cast (event); if (!e) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (sourceUntapped && source->isTapped() == 1) return 0; if (!tc->canTarget(e->player)) return 0; - if (fromTc && !fromTc->canTarget(e->player)) return 0; + //if (fromTc && !fromTc->canTarget(e->player)) return 0; + if (fromTc && !fromTc->canTarget(e->source)) return 0; //Now it's possible to specify if a source can trigger or not the event of life gain if (gainException && e->source && !strcmp(gainException->data->name.c_str(), e->source->data->name.c_str())) return 0; //If the source of life gain it's the exception card don't gain life (loop avoidance); if (type == 1 && (e->amount > 0)) return 0; if (type == 0 && (e->amount < 0)) return 0; @@ -1914,6 +1921,7 @@ public: return 0; e->player->thatmuch = abs(e->amount); this->source->thatmuch = abs(e->amount); + triggeredTurn = game->turn; return 1; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index 2c1f4fa25..48d209c65 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1299,9 +1299,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,true,false, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,true,false,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,true,false); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,true,false,limitOnceATurn); } //Lifed current opponent @@ -1310,9 +1310,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,true, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,true,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,true); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,true,limitOnceATurn); } //Lifed static @@ -1321,9 +1321,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,false, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,false,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,false); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 0,sourceUntapped,once,false,false,limitOnceATurn); } //Life Loss current player @@ -1332,9 +1332,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,true,false, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,true,false,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,true,false); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,true,false,limitOnceATurn); } //Life Loss current opponent @@ -1343,9 +1343,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,true, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,true,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,true); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,true,limitOnceATurn); } //Life Loss static @@ -1354,9 +1354,9 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell TargetChooser *fromTc = parseSimpleTC(s, "from", card); TargetChooser *exception = parseSimpleTC(s, "except", card); // Added a new keyword except to specify a life gain/loss card exception in order to avoid life gain loop (eg. Angels of Vitality) if(exception) - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,false, exception->source); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,false,limitOnceATurn,exception->source); else - return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,false); + return NEW TrLifeGained(observer, id, card, tc, fromTc, 1,sourceUntapped,once,false,false,limitOnceATurn); } //Card Damaged and killed by a creature this turn diff --git a/projects/mtg/src/MTGRules.cpp b/projects/mtg/src/MTGRules.cpp index c6e44252f..4b9933208 100644 --- a/projects/mtg/src/MTGRules.cpp +++ b/projects/mtg/src/MTGRules.cpp @@ -3854,7 +3854,7 @@ int MTGLifelinkRule::receiveEvent(WEvent * event) MTGCardInstance * card = d->source; if (d->damage > 0 && card && (card->basicAbilities[(int)Constants::LIFELINK]||card->LKIbasicAbilities[(int)Constants::LIFELINK])) { - card->controller()->gainLife(d->damage, source); + card->controller()->gainLife(d->damage, card); return 1; } }