From 7a192a687396a78da1a3a18436f628b3b6c38e92 Mon Sep 17 00:00:00 2001 From: tool4ever Date: Fri, 20 Sep 2024 11:53:07 +0200 Subject: [PATCH] Fix Valiant triggers failing if another player targets first (#6178) --- .../src/main/java/forge/game/ability/AbilityKey.java | 1 + forge-game/src/main/java/forge/game/card/Card.java | 8 +++++++- .../game/spellability/SpellAbilityStackInstance.java | 11 +++++++---- .../java/forge/game/trigger/TriggerBecomesTarget.java | 6 ++++++ .../src/main/java/forge/game/zone/MagicStack.java | 10 ++++++++-- forge-gui/res/cardsfolder/e/emberheart_challenger.txt | 2 +- .../res/cardsfolder/f/flowerfoot_swordmaster.txt | 2 +- forge-gui/res/cardsfolder/h/heartfire_hero.txt | 2 +- forge-gui/res/cardsfolder/m/mouse_trapper.txt | 2 +- forge-gui/res/cardsfolder/n/nettle_guard.txt | 2 +- forge-gui/res/cardsfolder/s/seedglaive_mentor.txt | 2 +- forge-gui/res/cardsfolder/v/veteran_guardmouse.txt | 2 +- forge-gui/res/cardsfolder/w/whiskerquill_scribe.txt | 2 +- .../res/cardsfolder/w/whiskervale_forerunner.txt | 2 +- 14 files changed, 38 insertions(+), 16 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index b38511f39dd..7eda7e340bc 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -137,6 +137,7 @@ public enum AbilityKey { Targets("Targets"), Token("Token"), TokenNum("TokenNum"), + Valiant("Valiant"), Vehicle("Vehicle"), Won("Won"), diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 16abe732e94..df4e2fc8cfe 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -188,7 +188,7 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr private boolean startsGameInPlay = false; private boolean drawnThisTurn = false; private boolean foughtThisTurn = false; - private boolean becameTargetThisTurn = false; + private boolean becameTargetThisTurn, valiant = false; private boolean enlistedThisCombat = false; private boolean startedTheTurnUntapped = false; private boolean cameUnderControlSinceLastUpkeep = true; // for Echo @@ -3702,6 +3702,12 @@ public class Card extends GameEntity implements Comparable, IHasSVars, ITr public void setBecameTargetThisTurn(boolean becameTargetThisTurn0) { becameTargetThisTurn = becameTargetThisTurn0; } + public boolean isValiant() { + return valiant; + } + public void setValiant(boolean v) { + valiant = v; + } public boolean hasStartedTheTurnUntapped() { return startedTheTurnUntapped; diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java index 0cb1fe08e9a..cfabe419fa2 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbilityStackInstance.java @@ -144,9 +144,6 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView { view.updateTargetPlayers(this); view.updateText(this); - // Run BecomesTargetTrigger - Map runParams = AbilityKey.newMap(); - runParams.put(AbilityKey.SourceSA, ability); Set distinctObjects = Sets.newHashSet(); for (final GameObject tgt : target) { if (oldTarget != null && oldTarget.contains(tgt)) { @@ -157,16 +154,22 @@ public class SpellAbilityStackInstance implements IIdentifiable, IHasCardView { continue; } + Map runParams = AbilityKey.newMap(); + runParams.put(AbilityKey.SourceSA, ability); if (tgt instanceof Card && !((Card) tgt).hasBecomeTargetThisTurn()) { runParams.put(AbilityKey.FirstTime, null); ((Card) tgt).setBecameTargetThisTurn(true); } + if (tgt instanceof Card && !((Card) tgt).isValiant() && cause.getController().equals(((Card) tgt).getController())) { + runParams.put(AbilityKey.Valiant, null); + ((Card) tgt).setValiant(true); + } runParams.put(AbilityKey.Target, tgt); getSourceCard().getGame().getTriggerHandler().runTrigger(TriggerType.BecomesTarget, runParams, false); } // Only run BecomesTargetOnce when at least one target is changed if (!distinctObjects.isEmpty()) { - runParams = AbilityKey.newMap(); + Map runParams = AbilityKey.newMap(); runParams.put(AbilityKey.SourceSA, ability); runParams.put(AbilityKey.Targets, distinctObjects); runParams.put(AbilityKey.Cause, cause); diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java b/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java index 798dcf8938d..e93340144e5 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerBecomesTarget.java @@ -77,6 +77,12 @@ public class TriggerBecomesTarget extends Trigger { } } + if (hasParam("Valiant")) { + if (!runParams.containsKey(AbilityKey.Valiant)) { + return false; + } + } + return true; } diff --git a/forge-game/src/main/java/forge/game/zone/MagicStack.java b/forge-game/src/main/java/forge/game/zone/MagicStack.java index 99fb6e0e15d..e60c7535549 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -437,13 +437,11 @@ public class MagicStack /* extends MyObservable */ implements Iterable chosenTargets = sp.getAllTargetChoices(); if (!chosenTargets.isEmpty()) { - runParams = AbilityKey.newMap(); SpellAbility s = sp; if (si != null) { s = si.getSpellAbility(); chosenTargets = s.getAllTargetChoices(); } - runParams.put(AbilityKey.SourceSA, s); Set distinctObjects = Sets.newHashSet(); for (final TargetChoices tc : chosenTargets) { for (final GameObject tgt : tc) { @@ -453,14 +451,22 @@ public class MagicStack /* extends MyObservable */ implements Iterable | ValidTgts$ Artifact,Enchantment | TgtPrompt$ Select target artifact or enchantment | SpellDescription$ Destroy target artifact or enchantment. Oracle:Valiant — Whenever Nettle Guard becomes the target of a spell or ability you control for the first time each turn, it gets +0/+2 until end of turn.\n{1}, Sacrifice Nettle Guard: Destroy target artifact or enchantment. diff --git a/forge-gui/res/cardsfolder/s/seedglaive_mentor.txt b/forge-gui/res/cardsfolder/s/seedglaive_mentor.txt index 172c400e626..68aa479bcb7 100644 --- a/forge-gui/res/cardsfolder/s/seedglaive_mentor.txt +++ b/forge-gui/res/cardsfolder/s/seedglaive_mentor.txt @@ -4,7 +4,7 @@ Types:Creature Mouse Soldier PT:3/2 K:Vigilance K:Haste -T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | FirstTime$ True | Execute$ TrigCounter | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, put a +1/+1 counter on it. +T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | Valiant$ True | Execute$ TrigCounter | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, put a +1/+1 counter on it. SVar:TrigCounter:DB$ PutCounter | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 DeckHas:Ability$Counters Oracle:Vigilance, haste\nValiant — Whenever Seedglaive Mentor becomes the target of a spell or ability you control for the first time each turn, put a +1/+1 counter on it. diff --git a/forge-gui/res/cardsfolder/v/veteran_guardmouse.txt b/forge-gui/res/cardsfolder/v/veteran_guardmouse.txt index e336021430b..3ab4e9b13d4 100644 --- a/forge-gui/res/cardsfolder/v/veteran_guardmouse.txt +++ b/forge-gui/res/cardsfolder/v/veteran_guardmouse.txt @@ -2,7 +2,7 @@ Name:Veteran Guardmouse ManaCost:3 RW Types:Creature Mouse Soldier PT:3/4 -T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | FirstTime$ True | Execute$ TrigPump | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, it gets +1/+0 and gains first strike until end of turn. Scry 1. (Look at the top card of your library. You may put that card on the bottom.) +T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | Valiant$ True | Execute$ TrigPump | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, it gets +1/+0 and gains first strike until end of turn. Scry 1. (Look at the top card of your library. You may put that card on the bottom.) SVar:TrigPump:DB$ Pump | Defined$ Self | NumAtt$ 1 | KW$ First Strike | SubAbility$ DBScry SVar:DBScry:DB$ Scry | ScryNum$ 1 Oracle:Valiant — Whenever Veteran Guardmouse becomes the target of a spell or ability you control for the first time each turn, it gets +1/+0 and gains first strike until end of turn. Scry 1. (Look at the top card of your library. You may put that card on the bottom.) diff --git a/forge-gui/res/cardsfolder/w/whiskerquill_scribe.txt b/forge-gui/res/cardsfolder/w/whiskerquill_scribe.txt index ecd34becec1..2eaee9c46e3 100644 --- a/forge-gui/res/cardsfolder/w/whiskerquill_scribe.txt +++ b/forge-gui/res/cardsfolder/w/whiskerquill_scribe.txt @@ -2,6 +2,6 @@ Name:Whiskerquill Scribe ManaCost:1 R Types:Creature Mouse Citizen PT:2/2 -T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | FirstTime$ True | Execute$ TrigDraw | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, you may discard a card. If you do, draw a card. +T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | Valiant$ True | Execute$ TrigDraw | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, you may discard a card. If you do, draw a card. SVar:TrigDraw:AB$ Draw | Cost$ Discard<1/Card> Oracle:Valiant — Whenever Whiskerquill Scribe becomes the target of a spell or ability you control for the first time each turn, you may discard a card. If you do, draw a card. diff --git a/forge-gui/res/cardsfolder/w/whiskervale_forerunner.txt b/forge-gui/res/cardsfolder/w/whiskervale_forerunner.txt index e9211f23507..25a829c7afb 100644 --- a/forge-gui/res/cardsfolder/w/whiskervale_forerunner.txt +++ b/forge-gui/res/cardsfolder/w/whiskervale_forerunner.txt @@ -2,7 +2,7 @@ Name:Whiskervale Forerunner ManaCost:3 W Types:Creature Mouse Bard PT:3/4 -T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | FirstTime$ True | Execute$ TrigPeekAndReveal | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, look at the top five cards of your library. You may reveal a creature card with mana value 3 or less from among them. You may put it onto the battlefield if it's your turn. If you don't put it onto the battlefield, put it into your hand. Put the rest on the bottom of your library in a random order. +T:Mode$ BecomesTarget | ValidTarget$ Card.Self | ValidSource$ SpellAbility.YouCtrl | TriggerZones$ Battlefield | Valiant$ True | Execute$ TrigPeekAndReveal | TriggerDescription$ Valiant — Whenever CARDNAME becomes the target of a spell or ability you control for the first time each turn, look at the top five cards of your library. You may reveal a creature card with mana value 3 or less from among them. You may put it onto the battlefield if it's your turn. If you don't put it onto the battlefield, put it into your hand. Put the rest on the bottom of your library in a random order. SVar:TrigPeekAndReveal:DB$ PeekAndReveal | Defined$ You | PeekAmount$ 5 | NoReveal$ True | RememberPeeked$ True | SubAbility$ PickOne SVar:PickOne:DB$ ChooseCard | Defined$ You | Amount$ 1 | ChoiceTitle$ Choose a creature card to reveal | Choices$ Card.Creature+cmcLE3+IsRemembered | ChoiceZone$ Library | Reveal$ True | SubAbility$ DBChangeZoneBattlefield SVar:DBChangeZoneBattlefield:DB$ ChangeZone | Origin$ Library | Destination$ Battlefield | Defined$ ChosenCard | ConditionPlayerTurn$ True | ConditionDefined$ Remembered | ConditionPresent$ Card.ChosenCard | ConditionCompare$ EQ1 | Optional$ True | SubAbility$ DBChangeZoneHand