From 2933922572db504d2f7cdc0d6c1c318f841aeb10 Mon Sep 17 00:00:00 2001 From: tool4ever Date: Thu, 4 Jan 2024 07:49:28 +0100 Subject: [PATCH 1/2] Update huatli_poet_of_unity_roar_of_the_fifth_people.txt --- .../h/huatli_poet_of_unity_roar_of_the_fifth_people.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/h/huatli_poet_of_unity_roar_of_the_fifth_people.txt b/forge-gui/res/cardsfolder/h/huatli_poet_of_unity_roar_of_the_fifth_people.txt index 5dc174b5077..179d4dfdc3f 100644 --- a/forge-gui/res/cardsfolder/h/huatli_poet_of_unity_roar_of_the_fifth_people.txt +++ b/forge-gui/res/cardsfolder/h/huatli_poet_of_unity_roar_of_the_fifth_people.txt @@ -20,7 +20,7 @@ Colors:white,red,green Types:Enchantment Saga K:Chapter:4:DBToken,DBMana,DBSearch,DBPumpAll SVar:DBToken:DB$ Token | TokenOwner$ You | TokenScript$ g_3_3_dinosaur | TokenAmount$ 2 | SpellDescription$ Create two 3/3 green Dinosaur creature tokens. -SVar:DBMana:DB$ Animate | Defined$ Self | staticAbilities$ Static | SpellDescription$ CARDNAME gains "Creatures you control have '{T}: Add {R}, {G}, or {W}.'" +SVar:DBMana:DB$ Animate | Defined$ Self | staticAbilities$ Static | Duration$ Permanenent | SpellDescription$ CARDNAME gains "Creatures you control have '{T}: Add {R}, {G}, or {W}.'" SVar:Static:Mode$ Continuous | EffectZone$ Battlefield | Affected$ Creature.YouCtrl | AddAbility$ Mana | Description$ Creatures you control have '{T}: Add {R}, {G}, or {W}. SVar:Mana:AB$ Mana | Cost$ T | Produced$ Combo R G W | Amount$ 1 | SpellDescription$ Add {R}, {G}, or {W}. SVar:DBSearch:DB$ ChangeZone | Origin$ Library | Destination$ Hand | ChangeType$ Card.Dinosaur | ChangeNum$ 1 | SpellDescription$ Search your library for a Dinosaur card, reveal it, put it into your hand, then shuffle. From 1e135e8d3b1219f628d6adc439e67d2fbdfc9ded Mon Sep 17 00:00:00 2001 From: tool4ever Date: Thu, 4 Jan 2024 16:47:58 +0100 Subject: [PATCH 2/2] Support for Midnight Crusader Shuttle (#4478) --- .../java/forge/ai/ability/ChangeZoneAi.java | 3 +- .../game/ability/SpellAbilityEffect.java | 29 +++++++---------- .../effects/ChangeCombatantsEffect.java | 29 ++++------------- .../ability/effects/ChangeZoneEffect.java | 4 +-- .../ability/effects/ControlGainEffect.java | 32 ++----------------- .../forge/game/ability/effects/DigEffect.java | 2 +- .../game/ability/effects/DigUntilEffect.java | 2 +- .../game/ability/effects/MeldEffect.java | 2 +- .../game/ability/effects/TokenEffectBase.java | 2 +- .../java/forge/game/card/CardFactoryUtil.java | 4 +-- .../java/forge/game/card/CardProperty.java | 4 +++ .../a/adeline_resplendent_cathar.txt | 2 +- forge-gui/res/cardsfolder/c/capricopian.txt | 2 +- forge-gui/res/cardsfolder/h/hans_eriksson.txt | 2 +- .../res/cardsfolder/m/misleading_signpost.txt | 2 +- forge-gui/res/cardsfolder/p/portal_mage.txt | 2 +- .../cardsfolder/t/tahngarth_first_mate.txt | 4 ++- .../res/cardsfolder/w/windshaper_planetar.txt | 3 +- .../cardsfolder/z/zara_renegade_recruiter.txt | 2 +- 19 files changed, 44 insertions(+), 88 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java index c1075bc5f8b..5dbe7c483de 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChangeZoneAi.java @@ -344,12 +344,11 @@ private static boolean hiddenOriginCanPlayAI(final Player ai, final SpellAbility Iterable pDefined = Lists.newArrayList(source.getController()); final TargetRestrictions tgt = sa.getTargetRestrictions(); if (tgt != null && tgt.canTgtPlayer()) { + sa.resetTargets(); boolean isCurse = sa.isCurse(); if (isCurse && sa.canTarget(opponent)) { - sa.resetTargets(); sa.getTargets().add(opponent); } else if (!isCurse && sa.canTarget(ai)) { - sa.resetTargets(); sa.getTargets().add(ai); } if (!sa.isTargetNumberValid()) { diff --git a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java index 59fc6f49176..0f23570d41c 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -611,46 +611,41 @@ public void run() { } } - protected static boolean addToCombat(Card c, Player controller, SpellAbility sa, String attackingParam, String blockingParam) { + protected static boolean addToCombat(Card c, SpellAbility sa, String attackingParam, String blockingParam) { final Card host = sa.getHostCard(); - final Game game = controller.getGame(); + final Game game = host.getGame(); if (!c.isCreature() || !game.getPhaseHandler().inCombat()) { return false; } boolean combatChanged = false; final Combat combat = game.getCombat(); - if (sa.hasParam(attackingParam) && combat.getAttackingPlayer().equals(controller)) { + if (sa.hasParam(attackingParam) && combat.getAttackingPlayer().equals(c.getController())) { String attacking = sa.getParam(attackingParam); GameEntity defender = null; FCollection defs = null; // important to update defenders here, maybe some PW got removed combat.initConstraints(); - if (sa.hasParam("ChoosePlayerOrPlaneswalker")) { - PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(sa.hasParam("ForEach") ? c : host, attacking, sa); - defs = new FCollection<>(defendingPlayers); - defs.addAll(Iterables.filter(combat.getDefendingPlaneswalkers(), CardPredicates.isControlledByAnyOf(defendingPlayers))); - } else if ("True".equalsIgnoreCase(attacking)) { + if ("True".equalsIgnoreCase(attacking)) { defs = (FCollection) combat.getDefenders(); } else { - defs = AbilityUtils.getDefinedEntities(host, attacking, sa); + defs = AbilityUtils.getDefinedEntities(sa.hasParam("ForEach") ? c : host, attacking.split(","), sa); } if (defs != null) { Map params = Maps.newHashMap(); params.put("Attacker", c); - Player chooser; - if (sa.hasParam("Chooser")) { - chooser = Iterables.getFirst(AbilityUtils.getDefinedPlayers(host, sa.getParam("Chooser"), sa), null); - } else { - chooser = controller; - } - defender = chooser.getController().chooseSingleEntityForEffect(defs, sa, + defender = sa.getActivatingPlayer().getController().chooseSingleEntityForEffect(defs, sa, Localizer.getInstance().getMessage("lblChooseDefenderToAttackWithCard", CardTranslation.getTranslatedName(c.getName())), false, params); } - if (defender != null) { + final GameEntity originalDefender = combat.getDefenderByAttacker(c); + if (defender != null && + (originalDefender == null || !originalDefender.equals(defender))) { + // we might be reselecting + combat.removeFromCombat(c); + combat.addAttacker(c, defender); combat.getBandOfAttacker(c).setBlocked(false); combatChanged = true; diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeCombatantsEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeCombatantsEffect.java index 395a3459a6d..b54e4cbec60 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeCombatantsEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeCombatantsEffect.java @@ -1,16 +1,10 @@ package forge.game.ability.effects; -import java.util.Map; - -import com.google.common.collect.Maps; - import forge.game.Game; import forge.game.GameEntity; import forge.game.ability.AbilityKey; import forge.game.ability.SpellAbilityEffect; import forge.game.card.Card; -import forge.game.combat.AttackingBand; -import forge.game.combat.Combat; import forge.game.event.GameEventCombatChanged; import forge.game.player.Player; import forge.game.spellability.SpellAbility; @@ -18,7 +12,6 @@ import forge.util.CardTranslation; import forge.util.Lang; import forge.util.Localizer; -import forge.util.collect.FCollection; public class ChangeCombatantsEffect extends SpellAbilityEffect { @@ -36,33 +29,24 @@ protected String getStackDescription(SpellAbility sa) { @Override public void resolve(SpellAbility sa) { boolean isCombatChanged = false; + final boolean isOptional = sa.hasParam("Optional"); final Player activator = sa.getActivatingPlayer(); final Game game = activator.getGame(); + // TODO: may expand this effect for defined blocker (False Orders, General Jarkeld, Sorrow's Path, Ydwen Efreet) for (final Card c : getTargetCards(sa)) { String cardString = CardTranslation.getTranslatedName(c.getName()) + " (" + c.getId() + ")"; - boolean isOptional = sa.hasParam("Optional"); if (isOptional && !activator.getController().confirmAction(sa, null, Localizer.getInstance().getMessage("lblChangeCombatantOption", cardString), null)) { continue; } - final Combat combat = game.getCombat(); - final GameEntity originalDefender = combat.getDefenderByAttacker(c); - final FCollection defs = new FCollection<>(sa.hasParam("PlayerOnly") ? combat.getDefendingPlayers() : combat.getDefenders()); + final GameEntity originalDefender = game.getCombat().getDefenderByAttacker(c); - String title = Localizer.getInstance().getMessage("lblChooseDefenderToAttackWithCard", cardString); - Map params = Maps.newHashMap(); - params.put("Attacker", c); + if (addToCombat(c, sa, "Attacking", "Blocking")) { + isCombatChanged = true; + GameEntity defender = game.getCombat().getDefenderByAttacker(c); - final GameEntity defender = activator.getController().chooseSingleEntityForEffect(defs, sa, title, false, params); - if (originalDefender != null && !originalDefender.equals(defender)) { - AttackingBand ab = combat.getBandOfAttacker(c); - if (ab != null) { - combat.unregisterAttacker(c, ab); - ab.removeAttacker(c); - } - combat.addAttacker(c, defender); // retarget triggers to the new defender (e.g. Ulamog, Ceaseless Hunger + Portal Mage) for (SpellAbilityStackInstance si : game.getStack()) { if (si.isTrigger() && c.equals(si.getSourceCard()) @@ -75,7 +59,6 @@ public void resolve(SpellAbility sa) { } } } - isCombatChanged = true; } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index f98109e9db2..1e50f59344f 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -673,7 +673,7 @@ private void changeKnownOriginResolve(final SpellAbility sa) { if (sa.hasParam("LeaveBattlefield")) { addLeaveBattlefieldReplacement(movedCard, sa, sa.getParam("LeaveBattlefield")); } - if (addToCombat(movedCard, movedCard.getController(), sa, "Attacking", "Blocking")) { + if (addToCombat(movedCard, sa, "Attacking", "Blocking")) { combatChanged = true; } if (sa.isNinjutsu()) { @@ -1369,7 +1369,7 @@ else if (c.isAura()) { // When it should enter the battlefield attached to an il } } - if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) { + if (addToCombat(c, sa, "Attacking", "Blocking")) { combatChanged = true; } diff --git a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java index 1f8b462ea58..e1bff50efac 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ControlGainEffect.java @@ -18,7 +18,6 @@ import forge.game.card.CardCollectionView; import forge.game.card.CardLists; import forge.game.event.GameEventCardStatsChanged; -import forge.game.event.GameEventCombatChanged; import forge.game.player.Player; import forge.game.spellability.SpellAbility; import forge.game.trigger.TriggerType; @@ -149,7 +148,6 @@ public void resolve(SpellAbility sa) { return; } - boolean combatChanged = false; CardCollection untapped = new CardCollection(); for (Card tgtC : tgtCards) { if (!tgtC.isInPlay() || !tgtC.canBeControlledBy(newController)) { @@ -176,25 +174,10 @@ public void resolve(SpellAbility sa) { if (tgtC.untap(true)) untapped.add(tgtC); } - final List kws = Lists.newArrayList(); - final List hiddenKws = Lists.newArrayList(); - if (null != keywords) { - for (final String kw : keywords) { - if (kw.startsWith("HIDDEN")) { - hiddenKws.add(kw.substring(7)); - } else { - kws.add(kw); - } - } - } - - if (!kws.isEmpty()) { - tgtC.addChangedCardKeywords(kws, Lists.newArrayList(), false, tStamp, 0); + if (keywords != null) { + tgtC.addChangedCardKeywords(keywords, Lists.newArrayList(), false, tStamp, 0); game.fireEvent(new GameEventCardStatsChanged(tgtC)); } - if (!hiddenKws.isEmpty()) { - tgtC.addHiddenExtrinsicKeywords(tStamp, 0, hiddenKws); - } if (remember && !source.isRemembered(tgtC)) { source.addRemembered(tgtC); @@ -244,7 +227,6 @@ public void resolve(SpellAbility sa) { @Override public void run() { - tgtC.removeHiddenExtrinsicKeywords(tStamp, 0); tgtC.removeChangedCardKeywords(tStamp, 0); } }; @@ -252,11 +234,8 @@ public void run() { } game.getAction().controllerChangeZoneCorrection(tgtC); - - if (addToCombat(tgtC, tgtC.getController(), sa, "Attacking", "Blocking")) { - combatChanged = true; - } } // end foreach target + if (!untapped.isEmpty()) { final Map runParams = AbilityKey.newMap(); final Map map = Maps.newHashMap(); @@ -264,11 +243,6 @@ public void run() { runParams.put(AbilityKey.Map, map); game.getTriggerHandler().runTrigger(TriggerType.UntapAll, runParams, false); } - - if (combatChanged) { - game.updateCombatForView(); - game.fireEvent(new GameEventCombatChanged()); - } } /** diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java index 57556d3459f..de69738efac 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigEffect.java @@ -411,7 +411,7 @@ else if (!sa.hasParam("NoLooking")) { } c = game.getAction().moveTo(c.getController().getZone(destZone1), c, sa, moveParams); if (destZone1.equals(ZoneType.Battlefield)) { - if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) { + if (addToCombat(c, sa, "Attacking", "Blocking")) { combatChanged = true; } } else if (destZone1.equals(ZoneType.Exile)) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java index c3382bc1c39..2c95137cf1b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigUntilEffect.java @@ -239,7 +239,7 @@ public void resolve(SpellAbility sa) { c.setTapped(true); } m = game.getAction().moveTo(c.getController().getZone(foundDest), c, sa, moveParams); - if (addToCombat(c, c.getController(), sa, "Attacking", "Blocking")) { + if (addToCombat(c, sa, "Attacking", "Blocking")) { combatChanged = true; } } else if (sa.hasParam("NoMoveFound")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/MeldEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MeldEffect.java index 04d9c642539..64678a63093 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MeldEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MeldEffect.java @@ -65,7 +65,7 @@ public void resolve(SpellAbility sa) { PlayerZoneBattlefield bf = (PlayerZoneBattlefield)controller.getZone(ZoneType.Battlefield); bf.addToMelded(secondary); Card movedCard = game.getAction().changeZone(primary.getZone(), bf, primary, 0, sa); - if (addToCombat(movedCard, movedCard.getController(), sa, "Attacking", "Blocking")) { + if (addToCombat(movedCard, sa, "Attacking", "Blocking")) { game.updateCombatForView(); game.fireEvent(new GameEventCombatChanged()); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/TokenEffectBase.java b/forge-game/src/main/java/forge/game/ability/effects/TokenEffectBase.java index 22fbd18f468..8734b8e9b90 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TokenEffectBase.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TokenEffectBase.java @@ -185,7 +185,7 @@ protected TokenCreateTable makeTokenTable(TokenCreateTable tokenTable, final boo addSelfTrigger(sa, sa.getParam("AtEOTTrig"), moved); } - if (addToCombat(moved, tok.getController(), sa, "TokenAttacking", "TokenBlocking")) { + if (addToCombat(moved, sa, "TokenAttacking", "TokenBlocking")) { combatChanged.setTrue(); } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index b097d3a5666..a7478f74eb4 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -1566,8 +1566,8 @@ public static void addTriggerAbility(final KeywordInterface inst, final Card car final String actualTrigger = "Mode$ Attacks | ValidCard$ Card.Self | Secondary$ True" + " | TriggerDescription$ Myriad (" + inst.getReminderText() + ")"; - final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | Optional$ True | TokenAttacking$ Remembered" - + "| ForEach$ OppNonDefendingPlayer | ChoosePlayerOrPlaneswalker$ True | AtEOT$ ExileCombat | CleanupForEach$ True"; + final String copyStr = "DB$ CopyPermanent | Defined$ Self | TokenTapped$ True | Optional$ True | TokenAttacking$ Player.IsRemembered,Valid Planeswalker.ControlledBy Remembered" + + "| ForEach$ OppNonDefendingPlayer | AtEOT$ ExileCombat | CleanupForEach$ True"; final SpellAbility copySA = AbilityFactory.getAbility(copyStr, card); copySA.setIntrinsic(intrinsic); diff --git a/forge-game/src/main/java/forge/game/card/CardProperty.java b/forge-game/src/main/java/forge/game/card/CardProperty.java index 6eddea05c85..8a7a805c7c5 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -241,6 +241,10 @@ public static boolean cardHasProperty(Card card, String property, Player sourceC if (!lp.contains(card.getProtectingPlayer())) { return false; } + } else if (property.equals("Defending")) { + if (game.getCombat() == null || !game.getCombat().getAttackersAndDefenders().values().contains(card)) { + return false; + } } else if (property.startsWith("DefendingPlayer")) { Player p = property.endsWith("Ctrl") ? controller : card.getOwner(); if (!game.getPhaseHandler().inCombat()) { diff --git a/forge-gui/res/cardsfolder/a/adeline_resplendent_cathar.txt b/forge-gui/res/cardsfolder/a/adeline_resplendent_cathar.txt index 55e8eb7cb1c..3f987c0ba42 100644 --- a/forge-gui/res/cardsfolder/a/adeline_resplendent_cathar.txt +++ b/forge-gui/res/cardsfolder/a/adeline_resplendent_cathar.txt @@ -7,6 +7,6 @@ S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ SVar:X:Count$Valid Creature.YouCtrl T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ DBRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control. SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Opponent | ChangeZoneTable$ True | RepeatSubAbility$ DBToken -SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ Remembered | ChoosePlayerOrPlaneswalker$ True | TokenOwner$ You +SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ Player.IsRemembered,Valid Planeswalker.ControlledBy Remembered | TokenOwner$ You DeckHas:Ability$Token Oracle:Vigilance\nAdeline, Resplendent Cathar's power is equal to the number of creatures you control.\nWhenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control. diff --git a/forge-gui/res/cardsfolder/c/capricopian.txt b/forge-gui/res/cardsfolder/c/capricopian.txt index 14a80953511..7f0e16812cf 100644 --- a/forge-gui/res/cardsfolder/c/capricopian.txt +++ b/forge-gui/res/cardsfolder/c/capricopian.txt @@ -5,6 +5,6 @@ PT:0/0 K:etbCounter:P1P1:X SVar:X:Count$xPaid A:AB$ PutCounter | Cost$ 2 | Activator$ Player | IsPresent$ Card.Self+attackingYou | Defined$ Self | CounterType$ P1P1 | CounterNum$ 1 | SubAbility$ DBReselect | ActivationPhases$ Declare Attackers | AILogic$ AlwaysWithNoTgt | SpellDescription$ Put a +1/+1 counter on CARDNAME, then you may reselect which player CARDNAME is attacking. Only the player CARDNAME is attacking may activate this ability and only during the declare attackers step. (It can't attack its controller.) -SVar:DBReselect:DB$ ChangeCombatants | Defined$ Self | AILogic$ WeakestOppExceptCtrl | PlayerOnly$ True +SVar:DBReselect:DB$ ChangeCombatants | Defined$ Self | AILogic$ WeakestOppExceptCtrl | Attacking$ Player.OpponentOf CardController DeckHas:Ability$Counters Oracle:Capricopian enters the battlefield with X +1/+1 counters on it.\n{2}: Put a +1/+1 counter on Capricopian, then you may reselect which player Capricopian is attacking. Only the player Capricopian is attacking may activate this ability and only during the declare attackers step. (It can't attack its controller.) diff --git a/forge-gui/res/cardsfolder/h/hans_eriksson.txt b/forge-gui/res/cardsfolder/h/hans_eriksson.txt index 8a7b3f9fc89..3179942414c 100644 --- a/forge-gui/res/cardsfolder/h/hans_eriksson.txt +++ b/forge-gui/res/cardsfolder/h/hans_eriksson.txt @@ -3,7 +3,7 @@ ManaCost:2 R G Types:Legendary Creature Human Scout PT:1/4 T:Mode$ Attacks | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDig | TriggerDescription$ Whenever CARDNAME attacks, reveal the top card of your library. If it's a creature card, put it onto the battlefield tapped and attacking defending player or a planeswalker they control. Otherwise, put that card into your hand. When you put a creature card onto the battlefield this way, it fights CARDNAME. -SVar:TrigDig:DB$ Dig | DigNum$ 1 | ChangeNum$ All | Optional$ True | Reveal$ True | ChangeValid$ Creature | DestinationZone$ Battlefield | DestinationZone2$ Hand | Tapped$ True | Attacking$ DefendingPlayer | ChoosePlayerOrPlaneswalker$ True | RememberChanged$ True | SubAbility$ DBImmediateTriggerCheck +SVar:TrigDig:DB$ Dig | DigNum$ 1 | ChangeNum$ All | Optional$ True | Reveal$ True | ChangeValid$ Creature | DestinationZone$ Battlefield | DestinationZone2$ Hand | Tapped$ True | Attacking$ DefendingPlayer,Valid Planeswalker.ControlledBy DefendingPlayer | RememberChanged$ True | SubAbility$ DBImmediateTriggerCheck SVar:DBImmediateTriggerCheck:DB$ ImmediateTrigger | Execute$ DBFight | ConditionDefined$ Remembered | ConditionPresent$ Creature | ConditionCompare$ GE1 | TriggerDescription$ When you put a creature card onto the battlefield this way, it fights Hans Eriksson. SVar:DBFight:DB$ Fight | Defined$ Remembered | ExtraDefined$ Self | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True diff --git a/forge-gui/res/cardsfolder/m/misleading_signpost.txt b/forge-gui/res/cardsfolder/m/misleading_signpost.txt index 5c21363075e..8264e23c358 100644 --- a/forge-gui/res/cardsfolder/m/misleading_signpost.txt +++ b/forge-gui/res/cardsfolder/m/misleading_signpost.txt @@ -3,7 +3,7 @@ ManaCost:2 U Types:Artifact K:Flash T:Mode$ ChangesZone | Phase$ Declare Attackers | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeAttacker | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield during the declare attackers step, you may reselect which player or permanent target attacking creature is attacking. (It can't attack its controller or their permanents.) -SVar:TrigChangeAttacker:DB$ ChangeCombatants | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature +SVar:TrigChangeAttacker:DB$ ChangeCombatants | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | Attacking$ True AI:RemoveDeck:All A:AB$ Mana | Cost$ T | Produced$ U | SpellDescription$ Add {U}. Oracle:Flash\nWhen Misleading Signpost enters the battlefield during the declare attackers step, you may reselect which player or permanent target attacking creature is attacking. (It can't attack its controller or their permanents.)\n{T}: Add {U}. diff --git a/forge-gui/res/cardsfolder/p/portal_mage.txt b/forge-gui/res/cardsfolder/p/portal_mage.txt index 6d1c9cf02a2..88e3ca68663 100644 --- a/forge-gui/res/cardsfolder/p/portal_mage.txt +++ b/forge-gui/res/cardsfolder/p/portal_mage.txt @@ -4,6 +4,6 @@ Types:Creature Human Wizard PT:2/2 K:Flash T:Mode$ ChangesZone | Phase$ Declare Attackers | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigChangeAttacker | OptionalDecider$ You | TriggerDescription$ When CARDNAME enters the battlefield during the declare attackers step, you may reselect which player or permanent target attacking creature is attacking. (It can't attack its controller or their permanents.) -SVar:TrigChangeAttacker:DB$ ChangeCombatants | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature +SVar:TrigChangeAttacker:DB$ ChangeCombatants | ValidTgts$ Creature.attacking | TgtPrompt$ Select target attacking creature | Attacking$ True AI:RemoveDeck:All Oracle:Flash\nWhen Portal Mage enters the battlefield during the declare attackers step, you may reselect which player or permanent target attacking creature is attacking. (It can't attack its controller or their permanents.) diff --git a/forge-gui/res/cardsfolder/t/tahngarth_first_mate.txt b/forge-gui/res/cardsfolder/t/tahngarth_first_mate.txt index 0f6486ca519..f34c576423d 100644 --- a/forge-gui/res/cardsfolder/t/tahngarth_first_mate.txt +++ b/forge-gui/res/cardsfolder/t/tahngarth_first_mate.txt @@ -4,6 +4,8 @@ Types:Legendary Creature Minotaur Warrior PT:5/5 S:Mode$ MinMaxBlocker | ValidCard$ Card.Self | Max$ 1 | Description$ CARDNAME can't be blocked by more than one creature. T:Mode$ AttackersDeclared | AttackingPlayer$ Player.Opponent | Execute$ TrigGainControl | TriggerZones$ Battlefield | OptionalDecider$ You | IsPresent$ Card.Self+tapped | TriggerDescription$ Whenever an opponent attacks with one or more creatures, if NICKNAME is tapped, you may have that opponent gain control of NICKNAME until end of combat. If you do, choose a player or planeswalker that opponent is attacking. NICKNAME is attacking that player or planeswalker. -SVar:TrigGainControl:DB$ GainControl | Defined$ Self | NewController$ TriggeredAttackingPlayer | LoseControl$ EndOfCombat | Attacking$ Player.Defending | Chooser$ You | ChoosePlayerOrPlaneswalker$ True +SVar:TrigGainControl:DB$ GainControl | Defined$ Self | NewController$ TriggeredAttackingPlayer | LoseControl$ EndOfCombat | RememberControlled$ True | SubAbility$ DBAttack +SVar:DBAttack:DB$ ChangeCombatants | Defined$ Remembered | Attacking$ Player.Defending,Valid Planeswalker.Defending | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True AI:RemoveDeck:All Oracle:Tahngarth, First Mate can't be blocked by more than one creature.\nWhenever an opponent attacks with one or more creatures, if Tahngarth is tapped, you may have that opponent gain control of Tahngarth until end of combat. If you do, choose a player or planeswalker that opponent is attacking. Tahngarth is attacking that player or planeswalker. diff --git a/forge-gui/res/cardsfolder/w/windshaper_planetar.txt b/forge-gui/res/cardsfolder/w/windshaper_planetar.txt index 98537762646..c36576a261c 100644 --- a/forge-gui/res/cardsfolder/w/windshaper_planetar.txt +++ b/forge-gui/res/cardsfolder/w/windshaper_planetar.txt @@ -5,7 +5,6 @@ PT:4/4 K:Flash K:Flying T:Mode$ ChangesZone | Phase$ Declare Attackers | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | Execute$ TrigEachAttacker | TriggerDescription$ When CARDNAME enters the battlefield during the declare attackers step, for each attacking creature, you may reselect which player or permanent that creature is attacking. (It can't attack its controller or their permanents.) -SVar:TrigEachAttacker:DB$ RepeatEach | RepeatCards$ Creature.attacking | RepeatSubAbility$ DBChangeAttacker -SVar:DBChangeAttacker:DB$ ChangeCombatants | Defined$ Remembered | Optional$ True +SVar:TrigEachAttacker:DB$ ChangeCombatants | Defined$ Valid Creature.attacking | Optional$ True | Attacking$ True AI:RemoveDeck:All Oracle:Flash\nFlying\nWhen Windshaper Planetar enters the battlefield during the declare attackers step, for each attacking creature, you may reselect which player or permanent that creature is attacking. (It can't attack its controller or their permanents.) diff --git a/forge-gui/res/cardsfolder/z/zara_renegade_recruiter.txt b/forge-gui/res/cardsfolder/z/zara_renegade_recruiter.txt index 8ca4a7ab6fe..91a7566d30e 100644 --- a/forge-gui/res/cardsfolder/z/zara_renegade_recruiter.txt +++ b/forge-gui/res/cardsfolder/z/zara_renegade_recruiter.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Human Pirate PT:4/3 K:Flying T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ TrigBorrow | TriggerDescription$ Whenever CARDNAME attacks, look at defending player's hand. You may put a creature card from it onto the battlefield under your control tapped and attacking that player or a planeswalker they control. Return that creature to its owner's hand at the beginning of the next end step. -SVar:TrigBorrow:DB$ ChangeZone | ChangeNum$ 1 | DefinedPlayer$ TriggeredDefendingPlayer | Chooser$ You | ChangeType$ Creature | Origin$ Hand | Destination$ Battlefield | GainControl$ True | Tapped$ True | Attacking$ DefendingPlayer | ChoosePlayerOrPlaneswalker$ True | RememberChanged$ True | SubAbility$ DBDelayTrig +SVar:TrigBorrow:DB$ ChangeZone | ChangeNum$ 1 | DefinedPlayer$ TriggeredDefendingPlayer | Chooser$ You | ChangeType$ Creature | Origin$ Hand | Destination$ Battlefield | GainControl$ True | Tapped$ True | Attacking$ DefendingPlayer,Valid Planeswalker.ControlledBy DefendingPlayer | RememberChanged$ True | SubAbility$ DBDelayTrig SVar:DBDelayTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ End of Turn | ValidPlayer$ Player | RememberObjects$ RememberedLKI | Execute$ DBChange | StackDescription$ None | SubAbility$ DBCleanup | TriggerDescription$ Return that creature to its owner's hand at the beginning of the next end step. SVar:DBChange:DB$ ChangeZone | Defined$ DelayTriggerRememberedLKI | Origin$ Battlefield | Destination$ Hand SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True