From 6625907180b5ca2b3ecb72be1155eaea1cc8548a Mon Sep 17 00:00:00 2001 From: Vittorio Alfieri Date: Fri, 21 Jul 2023 21:12:38 +0200 Subject: [PATCH] Fixed some primitives from issue #1085, improved some cards for AI combo (from Discord channel), added "isattacker" keyword to check if creature is attacking, added "couldattack" keyword to check if creature can attack, improved some triggers to add turnlimit option. --- .../bin/Res/sets/primitives/borderline.txt | 45 +++++++++-------- projects/mtg/bin/Res/sets/primitives/mtg.txt | 16 +++--- .../bin/Res/sets/primitives/planeswalkers.txt | 10 ++-- projects/mtg/include/AllAbilities.h | 50 +++++++++++++++---- projects/mtg/src/MTGAbility.cpp | 12 ++--- projects/mtg/src/WParsedInt.cpp | 24 +++++---- 6 files changed, 96 insertions(+), 61 deletions(-) diff --git a/projects/mtg/bin/Res/sets/primitives/borderline.txt b/projects/mtg/bin/Res/sets/primitives/borderline.txt index cb0a456df..fcc9f57c0 100644 --- a/projects/mtg/bin/Res/sets/primitives/borderline.txt +++ b/projects/mtg/bin/Res/sets/primitives/borderline.txt @@ -1,7 +1,7 @@ grade=borderline #Bordeline Primitives Pack for Wagic the Homebrew. #Please keep these card alphabetized, and try to have the "name=" line at the top of each card -#I sorted this programmatically - Thanks to Vitty85 20-07-2023 +#I sorted this programmatically - Thanks to Vitty85 21-07-2023 [card] name=+2 Mace auto={3}:equip @@ -18979,7 +18979,7 @@ type=Land [card] name=Corruption of Towashi auto=name(Incubate 4) name(Incubate 4) token(Incubator) and!( counter(1/1.4) )! -auto=@transformed(*[-instant;-sorcery]|myzones) turnlimited:may name(Draw a card) draw:1 controller +auto=@transformed(*|mybattlefield) turnlimited:may name(Draw a card) draw:1 controller text=When Corruption of Towashi enters the battlefield, incubate 4. (Create an Incubator token with four +1/+1 counters on it and "{2}: Transform this artifact." It transforms into a 0/0 Phyrexian artifact creature.) -- Whenever a permanent you control transforms or a permanent enters the battlefield under your control transformed, you may draw a card. Do this only once each turn. mana={4}{U} type=Enchantment @@ -20336,7 +20336,7 @@ toughness=2 [/card] [card] name=Cult of the Waxing Moon -auto=@transformed(creature[-human]|myBattlefield):name(Create wolf) _WOLFTOKEN_ +auto=@transformed(creature[-human]|myBattlefield):may name(Create wolf) _WOLFTOKEN_ text=Whenever a permanent you control transforms into a non-Human creature, put a 2/2 green Wolf creature token onto the battlefield. mana={4}{G} type=Creature @@ -36853,12 +36853,12 @@ toughness=4 [/card] [card] name=Garth One-Eye -auto=this(cantargetcard(*[-disenchant]) {1}{W}{T}:name(Choose disenchant) becomes(disenchant) forever && activate castcard(copied noevent named!:disenchant:!) -auto=this(cantargetcard(*[-braingeyser]) {X}{U}{U}{T}:name(Choose braingeyser) name(Choose braingeyser) transforms((,newability[becomes(braingeyser)],newability[activate castcard(copied noevent named!:braingeyser:! costx!:x:!)])) forever -auto=this(cantargetcard(*[-terror]) {1}{B}{T}:name(Choose terror) becomes(terror) forever && activate castcard(copied noevent named!:terror:!) -auto=this(cantargetcard(*[-shivan]) {4}{R}{R}{T}:name(Choose shivan dragon) becomes(shivan) forever && activate castcard(copied noevent named!:shivan dragon:!) -auto=this(cantargetcard(*[-regrowth]) {1}{G}{T}:name(Choose regrowth) becomes(regrowth) forever && activate castcard(copied noevent named!:regrowth:!) -auto=this(cantargetcard(*[-lotus]) {0}{T}:name(Choose black lotus) becomes(lotus) forever && activate castcard(copied noevent named!:black lotus:!) +auto=this(cantargetcard(*[-disenchant]) {1}{W}{T}:name(Choose disenchant) becomes(disenchant) forever && activate castcard(copied named!:disenchant:!) +auto=this(cantargetcard(*[-braingeyser]) {X}{U}{U}{T}:name(Choose braingeyser) name(Choose braingeyser) transforms((,newability[becomes(braingeyser)],newability[activate castcard(copied named!:braingeyser:! costx!:x:!)])) forever +auto=this(cantargetcard(*[-terror]) {1}{B}{T}:name(Choose terror) becomes(terror) forever && activate castcard(copied named!:terror:!) +auto=this(cantargetcard(*[-shivan]) {4}{R}{R}{T}:name(Choose shivan dragon) becomes(shivan) forever && activate castcard(copied named!:shivan dragon:!) +auto=this(cantargetcard(*[-regrowth]) {1}{G}{T}:name(Choose regrowth) becomes(regrowth) forever && activate castcard(copied named!:regrowth:!) +auto=this(cantargetcard(*[-lotus]) {T}:name(Choose black lotus) becomes(lotus) forever && activate castcard(copied putinplay named!:black lotus:!) text={T}: Choose a card name that hasn't been chosen from among Disenchant, Braingeyser, Terror, Shivan Dragon, Regrowth, and Black Lotus. Create a copy of the card with the chosen name. You may cast the copy. (You still pay its costs.) mana={W}{U}{B}{R}{G} type=Legendary Creature @@ -36974,7 +36974,7 @@ name=Gavony Dawnguard aicode=activate transforms((,newability[if type(creature[zpos<=4;manacost<=3]|myLibrary)~morethan~0 then target(creature[zpos<=4;manacost<=3]|myLibrary) moveTo(myHand) and!( all(other *[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! )! else all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! ])) oneshot auto=if type(*[day;night]|battlefield)~equalto~0 then name(It becomes day) activate castcard(noevent named!:Day:!) auto=@transformed(*[day;night]|battlefield):name(Look top 4 cards) reveal:4 optionone name(Get a creature) target(creature[manacost<=3]|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<4>*|reveal) bottomoflibrary optiontwoend revealend -auto=_WARD_(1) +auto=@targeted(this) from(*|opponentzones):choice name(This spell costs 1 more) name(This spell costs 1 more) target(*|opponentzones) transforms((,newability[pay[[{1}]] name(pay 1 mana) donothing?fizzle])) oneshot text=Ward {1} -- If it's neither day nor night, it becomes day as Gavony Dawnguard enters the battlefield. -- Whenever day becomes night or night becomes day, look at the top four cards of your library. You may reveal a creature card with mana value 3 or less from among them and put it into your hand. Put the rest on the bottom of your library in any order. type=Creature subtype=Human Soldier @@ -37297,8 +37297,7 @@ type=Sorcery [card] name=Geode Golem abilities=trample -auto=@combatdamagefoeof(player) from(this):may activate castcard(normal) target(*[iscommander]|mycommandzone) -auto=@combatdamageof(player) from(this):may activate castcard(normal) target(*[iscommander]|mycommandzone) +auto=@combatdamaged(player) from(this):may name(Cast the commander) target(*[iscommander]|mycommandzone) activate castcard(normal) text=Trample -- Whenever Geode Golem deals combat damage to a player, you may cast your commander from the command zone without paying its mana cost. (You still pay any additional costs.) mana={5} type=Artifact Creature @@ -40442,10 +40441,11 @@ toughness=2 [/card] [card] name=Gor Muldrak, Amphinologist -auto=lord(*|mybattlefield) protection from(salamander) -auto=preventalldamage to(controller) from(creature[salamander]) -auto=@each my endofturn restriction{type(creature|opponentbattlefield)~morethan~type(creature|mybattlefield)}:token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) -auto=@each my endofturn restriction{type(creature|opponentbattlefield)~lessthan~type(creature|mybattlefield)}:token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) opponent +auto=lord(*|mybattlefield) transforms((,newability[protection from(*[salamander])])) +auto=preventalldamage to(controller) from(*[salamander]) +auto=@each my endofturn restriction{type(creature|opponentbattlefield)~morethan~type(creature|mybattlefield)}:name(Create salamander) name(Create salamander) token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) +auto=@each my endofturn restriction{type(creature|opponentbattlefield)~lessthan~type(creature|mybattlefield)}:name(Create salamander) name(Create salamander) token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) opponent +auto=@each my endofturn restriction{type(creature|opponentbattlefield)~equalto~type(creature|mybattlefield)}:name(Create salamander) name(Create salamander) token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) && token(Salamander Warrior,Creature Warrior Salamander,4/3,blue) opponent text=You and permanents you control have protection from Salamanders. -- At the beginning of your end step, each player who controls the fewest creatures creates a 4/3 blue Salamander Warrior creature token. mana={1}{G}{U} type=Legendary Creature @@ -40466,8 +40466,7 @@ toughness=2 [card] name=Goreclaw, Terror of Qal Sisma auto=lord(creature[power>=4]|mycastingzone) altercost(colorless,-2) -auto=_ATTACKING_all(creature[power>=4]|myBattlefield) 1/1 ueot -auto=_ATTACKING_all(creature[power>=4]|myBattlefield) trample ueot +auto=_ATTACKING_name(All creatures gain 1/1 and trample) all(creature[power>=4]|myBattlefield) transforms((,newability[1/1],newability[trample])) ueot text=Creature spells you cast with power 4 or greater cost {2} less to cast. -- Whenever Goreclaw, Terror of Qal Sisma attacks, each creature you control with power 4 or greater gets +1/+1 and gains trample until end of turn. mana={3}{G} type=Legendary Creature @@ -41151,7 +41150,7 @@ toughness=1 [card] name=Grazilaxx, Illithid Scholar auto=@combat(blocked) source(creature|myBattlefield):may name(Return to hand) all(trigger[to]) moveto(ownerhand) -auto=@each combatdamage restriction{opponentdamagedbycombat}:name(Draw card) draw:1 controller +auto=@combatdamagefoeof(player) from(creature|mybattlefield):name(Draw card) draw:1 controller text=Whenever a creature you control becomes blocked, you may return it to its owner's hand. -- Whenever one or more creatures you control deal combat damage to a player, draw a card. mana={1}{U}{U} type=Legendary Creature @@ -80357,8 +80356,10 @@ toughness=4 [/card] [card] name=Rosie Cotton of South Lane -auto=token(Food) -auto=@tokencreated(*|myBattlefield):name(Put 1/1 counter) target(other creature|myBattlefield) counter(1/1) +auto=token(Food) and!( name(Put 1/1 counter) target(other creature|myBattlefield) counter(1/1) )! +auto=@tokencreated(*|myBattlefield) restriction{compare(ishuman)~morethan~0}:name(Put 1/1 counter) name(Put 1/1 counter) target(other creature|myBattlefield) counter(1/1) +auto=@tokencreated(*|myBattlefield) restriction{compare(ishuman)~equalto~0,type(Scurry Oak|mybattlefield)~equalto~0}:name(Put 1/1 counter) name(Put 1/1 counter) target(other creature|myBattlefield) counter(1/1) +auto=@tokencreated(*|myBattlefield) restriction{compare(ishuman)~equalto~0,type(Scurry Oak|mybattlefield)~morethan~0}:name(Put 1/1 counter) name(Put 1/1 counter) name(Put 1/1 counter) target(Scurry Oak|mybattlefield) counter(1/1) text=When Rosie Cotton of South Lane enters the battlefield, create a Food token. (It's an artifact with "{2}, {T}, Sacrifice this artifact: You gain 3 life.") -- Whenever you create a token, put a +1/+1 counter on target creature you control other than Rosie. mana={2}{W} type=Legendary Creature @@ -85516,7 +85517,7 @@ type=Instant [card] name=Shalai and Hallar abilities=flying,vigilance -auto=@counteradded(1/1) source(creature|myBattlefield):damage:1 target(opponent) +auto=@counteradded(1/1) from(creature|myBattlefield):name(Deal damage) damage:1 target(opponent) text=Flying, vigilance -- Whenever one or more +1/+1 counters are put on a creature you control, Shalai and Hallar deals that much damage to target opponent. mana={1}{R}{G}{W} type=Legendary Creature diff --git a/projects/mtg/bin/Res/sets/primitives/mtg.txt b/projects/mtg/bin/Res/sets/primitives/mtg.txt index 9c48b6e36..e31d1a431 100644 --- a/projects/mtg/bin/Res/sets/primitives/mtg.txt +++ b/projects/mtg/bin/Res/sets/primitives/mtg.txt @@ -1,6 +1,6 @@ #Primitives Pack for Wagic the Homebrew. #Please keep these card alphabetized, and try to have the "name=" line at the top of each card -#I sorted this programmatically so the other comments are removed except for AUTO_DEFINE - Vitty85 20-07-2023 +#I sorted this programmatically so the other comments are removed except for AUTO_DEFINE - Vitty85 21-07-2023 [card] name=Abandon Reason target=creature @@ -45418,8 +45418,8 @@ toughness=5 [/card] [card] name=Gerrard Capashen -auto=@each my upkeep:name(target opponent) target(opponent) life:type:*:targetedpersonshand controller -auto=this(attacking) {3}{W}:tap target(creature) +auto=@each my upkeep:name(Gain life) name(Gain life) life:type:*:opponenthand controller +auto=this(variable{isattacker}>0) transforms((,newability[{3}{W} restriction{compare(currentphase)~lessthan~9}:name(Tap a creature) name(Tap a creature) transforms((,newability[mustattack],newability[name(Tap a creature) name(Tap a creature) target(creature|battlefield) tap])) ueot])) text=At the beginning of your upkeep, you gain 1 life for each card in target opponent's hand. -- {3}{W}: Tap target creature. Activate this ability only if Gerrard Capashen is attacking. mana={3}{W}{W} type=Legendary Creature @@ -46426,8 +46426,8 @@ subtype=Aura [/card] [card] name=Gift of the Gargantuan -aicode=activate target(*[creature;land;zpos<=4]|mylibrary) moveto(myhand) -auto=name(look) reveal:4 optionone name(Get a card) target(creature,land|reveal) moveto(myhand) optiononeend optiontwo name(put on bottom) target(<4>*|reveal) bottomoflibrary optiontwoend revealend +aicode=activate transforms((,newability[if type(creature[zpos<=4]|mylibrary)~morethan~0 then if type(land[zpos<=4]|mylibrary)~morethan~0 then target(creature[zpos<=4]|mylibrary) moveto(myhand) and!( target(land[zpos<=4]|mylibrary) moveto(myhand) and!( all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! )! )!],newability[if type(creature[zpos<=4]|mylibrary)~morethan~0 then if type(land[zpos<=4]|mylibrary)~equalto~0 then target(creature[zpos<=4]|mylibrary) moveto(myhand) and!( all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! )!],newability[if type(creature[zpos<=4]|mylibrary)~equalto~0 then if type(land[zpos<=4]|mylibrary)~morethan~0 then target(land[zpos<=4]|mylibrary) moveto(myhand) and!( all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! )!],newability[if type(creature[zpos<=4]|mylibrary)~morethan~0 then if type(land[zpos<=4]|mylibrary)~equalto~0 then target(creature[zpos<=4]|mylibrary) moveto(myhand) and!( all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )! )!],newability[if type(creature[zpos<=4]|mylibrary)~equalto~0 then if type(land[zpos<=4]|mylibrary)~equalto~0 then all(*[zpos<=4]|mylibrary) moveto(myreveal) and!( bottomoflibrary )!])) oneshot +auto=name(Look top 4 cards) reveal:4 optionone name(Get a creature or land) target(*[creature;land]|reveal) moveto(myhand) and!( transforms((,newability[if cantargetcard(*[land]|*) then if type(creature|reveal)~morethan~0 then choice name(Get a creature) name(Get a creature) name(Get a creature) target(creature|reveal) moveto(myhand)],newability[if cantargetcard(*[creature]|*) then if type(land|reveal)~morethan~0 then choice name(Get a land) name(Get a land) name(Get a land) target(land|reveal) moveto(myhand)],newability[choice name(Don't choose another card) donothing])) oneshot )! optiononeend optiontwo name(Put on bottom) target(<4>*|reveal) bottomoflibrary optiontwoend revealend text=Look at the top four cards of your library. You may reveal a creature card and/or a land card from among them and put the revealed cards into your hand. Put the rest on the bottom of your library in any order. mana={2}{G} type=Sorcery @@ -50575,7 +50575,7 @@ type=Instant [card] name=Grip of Phyresis target=equipment -auto=moveto(mybattlefield) and!( transforms((,newability[create(Phyrexian Germ:Creature Phyrexian Germ:0/0:black) livingweapon])) oneshot )! +auto=moveto(mybattlefield) and!( transforms((Stolen,newability[token(Phyrexian Germ^Creature Phyrexian Germ^0/0^black) and!( name(Choose stolen equipment) target(equipment[stolen&-attached]|mybattlefield) transforms((,newability[name(Attach to phyrexian) rehook target(phyrexian[token&fresh&-geared]|mybattlefield)])) ueot )!])) oneshot )! text=Gain control of target Equipment, then create a 0/0 black Phyrexian Germ creature token and attach that Equipment to it. mana={2}{U} type=Instant @@ -51642,8 +51642,8 @@ toughness=2 [/card] [card] name=Gutter Grime -auto=@movedTo(creature[-token]|graveyard) from(myBattlefield):counter(0/0,1,Slime) -auto=@counteradded(0/0,1,Slime) from(this):token(Ooze,Creature Ooze,type:enchantment{counter(0/0,1,Slime)}:mybattlefield/type:enchantment{counter(0/0,1,Slime)}:mybattlefield cdaactive,green) +auto=@movedTo(creature[-token]|graveyard) from(myBattlefield):name(Add slime counter) counter(0/0,1,Slime) && token(Ooze,Creature Ooze Slimed,0/0,green) +auto=thisforeach(variable{hascntslime}>0) lord(ooze[token&slimed]|mybattlefield) 1/1 text=Whenever a notoken creature you control dies, put a slime counter on Gutter Grime, then create a green Ooze creature token with "This creature's power and toughness are each equal to the number of slime counters on Gutter Grime." mana={4}{G} type=Enchantment diff --git a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt index 8fc9adda5..ecf1bdb16 100644 --- a/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt +++ b/projects/mtg/bin/Res/sets/primitives/planeswalkers.txt @@ -1,6 +1,6 @@ #Planeswalkers Primitives Pack for Wagic the Homebrew. #Please keep these card alphabetized, and try to have the "name=" line at the top of each card -#We sorted this in alphabetical order - Luruz & Vitty85 12-07-2023 +#We sorted this in alphabetical order - Luruz & Vitty85 21-07-2023 [card] name=Abian, Luvion Usurper auto=counter(0/0,5,loyalty) @@ -1042,11 +1042,11 @@ color=black,green [/card] [card] name=Garruk, Savage Herald -aicode=activate transforms((,newability[if type(creature[zpos=1]|mylibrary)~morethan~0 then target(creature[zpos=1]|mylibrary) moveto(ownerHand) else target(*[zpos=1]|mylibrary) moveto(bottomoflibrary)])) ueot +aicode=activate transforms((,newability[if type(creature[zpos=1]|mylibrary)~morethan~0 then target(creature[zpos=1]|mylibrary) moveto(myhand) else target(*[zpos=1]|mylibrary) moveto(myreveal) and!( bottomoflibrary )!])) ueot auto=counter(0/0,5,loyalty) -auto={C(0/0,1,Loyalty)}:name(+1: Reveal the top card) reveal:1 optionone target(creature|reveal) moveto(myhand) optiononeend optiontwo name(Put in bottom of library) target(<1>*|reveal) moveto(bottomoflibrary) optiontwoend revealend -auto={C(0/0,-2,Loyalty)}:name(-2: Deals damage to target creature) target(creature|mybattlefield) transforms((,newability[target(other creature) dynamicability])) oneshot -auto={C(0/0,-7,Loyalty)}:name(-7: Creatures you control assign damage) all(creature|myBattlefield) transforms((,newability[@combat(blocked,turnlimited) source(this):may name(assign combat damage to defending player) thisforeach(power>=1) damage:1 opponent && fog from(this)])) +auto={C(0/0,1,Loyalty)}:name(+1: Reveal the top card) reveal:1 optionone name(Put in hand) target(creature|reveal) moveto(myhand) optiononeend optiontwo name(Put on bottom) target(<1>*|reveal) bottomoflibrary optiontwoend revealend +auto={C(0/0,-2,Loyalty)}:name(-2: Deals damage to target creature) target(creature|mybattlefield) transforms((,newability[name(Damage other creature) target(other creature|battlefield) dynamicability])) oneshot +auto={C(0/0,-7,Loyalty)}:name(-7: Creatures you control assign damage) all(creature|myBattlefield) transforms((,newability[@combat(blocked) source(this) turnlimited:may name(assign combat damage to defending player) thisforeach(power>=1) damage:1 opponent && fog from(this)])) ueot text=+1: Reveal the top card of your library. If it's a creature card, put it into your hand. Otherwise, put it on the bottom of your library. -- −2: Target creature you control deals damage equal to its power to another target creature. -- −7: Until end of turn, creatures you control gain "You may have this creature assign its combat damage as though it weren't blocked." mana={4}{G}{G} type=Legendary Planeswalker diff --git a/projects/mtg/include/AllAbilities.h b/projects/mtg/include/AllAbilities.h index 96794ea84..491b8a778 100644 --- a/projects/mtg/include/AllAbilities.h +++ b/projects/mtg/include/AllAbilities.h @@ -230,9 +230,12 @@ class TrCardTapped: public Trigger { public: bool tap; - TrCardTapped(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false) : - Trigger(observer, id, source, once, tc), tap(tap) + bool limitOnceATurn; + int triggeredTurn; + TrCardTapped(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false, bool limitOnceATurn = false) : + Trigger(observer, id, source, once, tc), tap(tap), limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) @@ -241,9 +244,12 @@ public: if (!e) return 0; if (e->noTrigger) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (e->before == e->after) return 0; if (e->after != tap) return 0; if (!tc->canTarget(e->card)) return 0; + triggeredTurn = game->turn; return 1; } @@ -257,18 +263,24 @@ class TrCardTappedformana: public Trigger { public: bool tap; - TrCardTappedformana(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false) : - Trigger(observer, id, source, once, tc), tap(tap) + bool limitOnceATurn; + int triggeredTurn; + TrCardTappedformana(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool tap = true, bool once = false, bool limitOnceATurn = false) : + Trigger(observer, id, source, once, tc), tap(tap), limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) { WEventCardTappedForMana * e = dynamic_cast (event); if (!e) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (e->before == e->after) return 0; if (e->after != tap) return 0; if (!tc->canTarget(e->card)) return 0; + triggeredTurn = game->turn; return 1; } @@ -309,16 +321,22 @@ public: class TrCardPhasesIn: public Trigger { public: - TrCardPhasesIn(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false) : - Trigger(observer, id, source, once, tc) + bool limitOnceATurn; + int triggeredTurn; + TrCardPhasesIn(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false, bool limitOnceATurn = false) : + Trigger(observer, id, source, once, tc), limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) { WEventCardPhasesIn * e = dynamic_cast (event); if (!e) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (!tc->canTarget(e->card)) return 0; + triggeredTurn = game->turn; return 1; } @@ -331,16 +349,22 @@ public: class TrCardFaceUp: public Trigger { public: - TrCardFaceUp(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false) : - Trigger(observer, id, source, once, tc) + bool limitOnceATurn; + int triggeredTurn; + TrCardFaceUp(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false, bool limitOnceATurn = false) : + Trigger(observer, id, source, once, tc), limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) { WEventCardFaceUp * e = dynamic_cast (event); if (!e) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (!tc->canTarget(e->card)) return 0; + triggeredTurn = game->turn; return 1; } @@ -353,16 +377,22 @@ public: class TrCardTransformed: public Trigger { public: - TrCardTransformed(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false) : - Trigger(observer, id, source, once, tc) + bool limitOnceATurn; + int triggeredTurn; + TrCardTransformed(GameObserver* observer, int id, MTGCardInstance * source, TargetChooser * tc, bool once = false, bool limitOnceATurn = false) : + Trigger(observer, id, source, once, tc), limitOnceATurn(limitOnceATurn) { + triggeredTurn = -1; } int triggerOnEventImpl(WEvent * event) { WEventCardTransforms * e = dynamic_cast (event); if (!e) return 0; + if (limitOnceATurn && triggeredTurn == game->turn) + return 0; if (!tc->canTarget(e->card)) return 0; + triggeredTurn = game->turn; return 1; } diff --git a/projects/mtg/src/MTGAbility.cpp b/projects/mtg/src/MTGAbility.cpp index acff7a0a8..d44ef7f61 100644 --- a/projects/mtg/src/MTGAbility.cpp +++ b/projects/mtg/src/MTGAbility.cpp @@ -1315,15 +1315,15 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell //Card unTapped if (TargetChooser *tc = parseSimpleTC(s,"untapped", card)) - return NEW TrCardTapped(observer, id, card, tc, false, once); + return NEW TrCardTapped(observer, id, card, tc, false, once, limitOnceATurn); //Card Tapped if (TargetChooser *tc = parseSimpleTC(s,"tapped", card)) - return NEW TrCardTapped(observer, id, card, tc, true, once); + return NEW TrCardTapped(observer, id, card, tc, true, once, limitOnceATurn); //Card Tapped for mana if (TargetChooser *tc = parseSimpleTC(s,"tappedformana", card)) - return NEW TrCardTappedformana(observer, id, card, tc, true, once); + return NEW TrCardTappedformana(observer, id, card, tc, true, once, limitOnceATurn); //Card Produced some mana if (TargetChooser *tc = parseSimpleTC(s,"producedmana", card)) @@ -1331,15 +1331,15 @@ TriggeredAbility * AbilityFactory::parseTrigger(string s, string, int id, Spell //Card Transforms if (TargetChooser *tc = parseSimpleTC(s,"transformed", card)) - return NEW TrCardTransformed(observer, id, card, tc, once); + return NEW TrCardTransformed(observer, id, card, tc, once, limitOnceATurn); //Card Faces Up if (TargetChooser *tc = parseSimpleTC(s,"facedup", card)) - return NEW TrCardFaceUp(observer, id, card, tc, once); + return NEW TrCardFaceUp(observer, id, card, tc, once, limitOnceATurn); //Card Phases In if (TargetChooser *tc = parseSimpleTC(s,"phasedin", card)) - return NEW TrCardPhasesIn(observer, id, card, tc, once); + return NEW TrCardPhasesIn(observer, id, card, tc, once, limitOnceATurn); //Card Exerted if (TargetChooser *tc = parseSimpleTC(s,"exerted", card)) diff --git a/projects/mtg/src/WParsedInt.cpp b/projects/mtg/src/WParsedInt.cpp index d5547deb9..ad7f3a856 100644 --- a/projects/mtg/src/WParsedInt.cpp +++ b/projects/mtg/src/WParsedInt.cpp @@ -1527,16 +1527,16 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card) } } } - else if(s.find("startingplayer") != string::npos){ //Return who was the starting player (0 is controller, 1 is opponent). + else if(s.find("startingplayer") != string::npos){ // Return who was the starting player (0 is controller, 1 is opponent). intValue = card->controller()->getObserver()->turn%2; if(card->controller()->getObserver()->currentlyActing() != card->controller()) intValue = 1 - intValue; } - else if (s == "pinstsorcount" || s == "oinstsorcount") // Return the number of instant or sorceries that were casted this turn by controller or opponent. + else if (s == "pinstsorcount" || s == "oinstsorcount") //Return the number of instant or sorceries that were casted this turn by controller or opponent. { intValue = (s == "pinstsorcount")?card->controller()->game->stack->seenThisTurn("*[instant;sorcery]", Constants::CAST_ALL):card->controller()->opponent()->game->stack->seenThisTurn("*[instant;sorcery]", Constants::CAST_ALL); } - else if ((s.find("palldead") != string::npos) || (s.find("oalldead") != string::npos)) // Return the number of cards of a specific type that died this turn for controller or opponent. + else if ((s.find("palldead") != string::npos) || (s.find("oalldead") != string::npos)) //Return the number of cards of a specific type that died this turn for controller or opponent. { int hasdeadtype = 0; MTGGameZone * grave = (s.find("oalldead") != string::npos)?card->controller()->opponent()->game->graveyard:card->controller()->game->graveyard; @@ -1547,7 +1547,7 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card) MTGCardInstance * checkCard = grave->cardsSeenThisTurn[gy]; if(checkCard->hasType(checktype) && ((checkCard->previousZone == checkCurrent->game->battlefield)|| - (checkCard->previousZone == checkCurrent->opponent()->game->battlefield))//died from battlefield + (checkCard->previousZone == checkCurrent->opponent()->game->battlefield)) //died from battlefield ) { hasdeadtype++; @@ -1555,7 +1555,7 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card) } intValue = hasdeadtype; } - else if (s.find("bothalldead") != string::npos) // Return the number of cards of a specific type that died this turn. + else if (s.find("bothalldead") != string::npos) //Return the number of cards of a specific type that died this turn. { int hasdeadtype = 0; string checktype = s.substr(11); @@ -1654,26 +1654,30 @@ void WParsedInt::extendedParse(string s, Spell * spell, MTGCardInstance * card) } } } - else if (s == "pringtemptations" || s == "oringtemptations") // How many times the player has been tempted by the Ring. + else if (s == "pringtemptations" || s == "oringtemptations") //How many times the player has been tempted by the Ring. { intValue = (s == "pringtemptations")?card->controller()->ringTemptations:card->controller()->opponent()->ringTemptations; } - else if (s == "iscommander" || s == "ringbearer") // Return 1 if card is the commander -- Return 1 if card is the Ring bearer + else if (s == "iscommander" || s == "ringbearer") //Return 1 if card is the commander -- Return 1 if card is the Ring bearer { intValue = (s == "iscommander")?card->isCommander:card->isRingBearer; } - else if (s == "oppotgt" || s == "ctrltgt") // Return 1 if card targeted the opponent -- Return 1 if card targeted its controller + else if (s == "oppotgt" || s == "ctrltgt") //Return 1 if card targeted the opponent -- Return 1 if card targeted its controller { intValue = 0; Player* p = (s == "oppotgt")?card->controller()->opponent():card->controller(); if(card->playerTarget == p) intValue = 1; } - else if (s == "kicked") + else if (s == "isattacker" || s == "couldattack") //Return 1 if creature is attacking. -- Return 1 if creature can attack. + { + intValue = (s == "isattacker")?card->isAttacker():card->canAttack(); + } + else if (s == "kicked") //Return the number of times kicker has been paid { intValue = card->kicked; } - else if(!intValue)//found nothing, try parsing a atoi + else if(!intValue) //Found nothing, try parsing a atoi { intValue = atoi(s.c_str()); }