From 8157172a9fecf1c7796d52fa065fabf107ed10ec Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 1 Jun 2021 17:53:38 +0200 Subject: [PATCH 1/5] Fix City in a Bottle --- .../src/main/java/forge/game/ability/AbilityUtils.java | 3 ++- forge-game/src/main/java/forge/game/card/CardProperty.java | 2 +- forge-game/src/main/java/forge/game/combat/CombatUtil.java | 4 ---- forge-game/src/main/java/forge/game/player/Player.java | 5 ----- forge-gui/res/cardsfolder/c/city_in_a_bottle.txt | 2 +- 5 files changed, 4 insertions(+), 12 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 7d8a11fb820..b1b7d415f21 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -3351,7 +3351,8 @@ public class AbilityUtils { } if (value.equals("OpponentsAttackedThisTurn")) { - return doXMath(player.getAttackedOpponentsThisTurn().size(), m, source, ctb); + final PlayerCollection opps = game.getPlayersAttackedThisTurn().get(player); + return doXMath(opps == null ? 0 : opps.size(), m, source, ctb); } return doXMath(0, m, source, ctb); 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 968a8a61e6e..b477bcc6010 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -1704,7 +1704,7 @@ public class CardProperty { } else if (property.startsWith("set")) { final String setCode = property.substring(3, 6); final PaperCard setCard = StaticData.instance().getCommonCards().getCardFromEdition(card.getName(), CardDb.SetPreference.Earliest); - if (!setCard.getEdition().equals(setCode)) { + if (setCard != null && !setCard.getEdition().equals(setCode)) { return false; } } else if (property.startsWith("inZone")) { diff --git a/forge-game/src/main/java/forge/game/combat/CombatUtil.java b/forge-game/src/main/java/forge/game/combat/CombatUtil.java index f82a9bf8089..1f21fe3606c 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -369,10 +369,6 @@ public class CombatUtil { c.getDamageHistory().clearNotAttackedSinceLastUpkeepOf(); c.getController().addCreaturesAttackedThisTurn(c); c.getController().incrementAttackersDeclaredThisTurn(); - - if (combat.getDefenderByAttacker(c) != null && combat.getDefenderByAttacker(c) instanceof Player) { - c.getController().addAttackedOpponentThisTurn(combat.getDefenderPlayerByAttacker(c)); - } } // checkDeclareAttackers /** diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 9e744aa4359..d49e3433c78 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -1958,10 +1958,6 @@ public class Player extends GameEntity implements Comparable { attackersDeclaredThisTurn = 0; } - public final PlayerCollection getAttackedOpponentsThisTurn() { return attackedOpponentsThisTurn; } - public final void addAttackedOpponentThisTurn(Player p) { attackedOpponentsThisTurn.add(p); } - public final void resetAttackedOpponentsThisTurn() { attackedOpponentsThisTurn.clear(); } - public final void altWinBySpellEffect(final String sourceName) { if (cantWin()) { System.out.println("Tried to win, but currently can't."); @@ -2498,7 +2494,6 @@ public class Player extends GameEntity implements Comparable { resetSacrificedThisTurn(); clearAssignedDamage(); resetAttackersDeclaredThisTurn(); - resetAttackedOpponentsThisTurn(); setRevolt(false); resetProwl(); setSpellsCastLastTurn(getSpellsCastThisTurn()); diff --git a/forge-gui/res/cardsfolder/c/city_in_a_bottle.txt b/forge-gui/res/cardsfolder/c/city_in_a_bottle.txt index 1b1034af96d..f68431217da 100644 --- a/forge-gui/res/cardsfolder/c/city_in_a_bottle.txt +++ b/forge-gui/res/cardsfolder/c/city_in_a_bottle.txt @@ -1,7 +1,7 @@ Name:City in a Bottle ManaCost:2 Types:Artifact -T:Mode$ Always | TriggerZones$ Battlefield | IsPresent$ Permanent.nontoken+setARN+Other | Execute$ TrigSac | TriggerDescription$ Whenever one or more other nontoken permanents with a name originally printed in the Arabian Nights expansion are on the battlefield, their controllers sacrifice them. +T:Mode$ Always | TriggerZones$ Battlefield | IsPresent$ Permanent.nonToken+setARN+Other | Execute$ TrigSac | TriggerDescription$ Whenever one or more other nontoken permanents with a name originally printed in the Arabian Nights expansion are on the battlefield, their controllers sacrifice them. SVar:TrigSac:DB$ SacrificeAll | ValidCards$ Permanent.nontoken+setARN+Other S:Mode$ CantPlayLand | ValidCard$ Card.setARN | Description$ Players can't cast spells or play lands with a name originally printed in the Arabian Nights expansion. S:Mode$ CantBeCast | ValidCard$ Card.setARN From 931411b6e4457a9b8d698936eb6ffc26cbc328f9 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 1 Jun 2021 18:38:26 +0200 Subject: [PATCH 2/5] Fix Wandering Archaic --- .../java/forge/game/ability/SpellAbilityEffect.java | 2 +- .../java/forge/game/ability/effects/DigEffect.java | 6 +++--- .../forge/game/ability/effects/DigMultipleEffect.java | 11 +++++------ .../w/wandering_archaic_explore_the_vastlands.txt | 3 +-- 4 files changed, 10 insertions(+), 12 deletions(-) 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 6fd4c17f575..fc62803172a 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -198,7 +198,7 @@ public abstract class SpellAbilityEffect { // Players protected final static PlayerCollection getTargetPlayers(final SpellAbility sa) { return getPlayers(false, "Defined", sa); } protected final static PlayerCollection getTargetPlayers(final SpellAbility sa, final String definedParam) { return getPlayers(false, definedParam, sa); } - protected final static PlayerCollection getDefinedPlayersOrTargeted(final SpellAbility sa ) { return getPlayers(true, "Defined", sa); } + protected final static PlayerCollection getDefinedPlayersOrTargeted(final SpellAbility sa) { return getPlayers(true, "Defined", sa); } protected final static PlayerCollection getDefinedPlayersOrTargeted(final SpellAbility sa, final String definedParam) { return getPlayers(true, definedParam, sa); } private static PlayerCollection getPlayers(final boolean definedFirst, final String definedParam, final SpellAbility sa) { 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 1932709764e..467fd6d72af 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 @@ -184,7 +184,7 @@ public class DigEffect extends SpellAbilityEffect { } } if (sa.hasParam("Choser")) { - final FCollectionView choosers = AbilityUtils.getDefinedPlayers(sa.getHostCard(), sa.getParam("Choser"), sa); + final FCollectionView choosers = AbilityUtils.getDefinedPlayers(host, sa.getParam("Choser"), sa); if (!choosers.isEmpty()) { chooser = player.getController().chooseSingleEntityForEffect(choosers, null, sa, Localizer.getInstance().getMessage("lblChooser") + ":", false, p, null); } @@ -221,8 +221,8 @@ public class DigEffect extends SpellAbilityEffect { // Optional abilities that use a dialog box to prompt the user to skip the ability (e.g. Explorer's Scope, Quest for Ula's Temple) if (optional && mayBeSkipped && !valid.isEmpty()) { - String prompt = !optionalAbilityPrompt.isEmpty() ? optionalAbilityPrompt : Localizer.getInstance().getMessage("lblWouldYouLikeProceedWithOptionalAbility") + " " + sa.getHostCard() + "?\n\n(" + sa.getDescription() + ")"; - if (!p.getController().confirmAction(sa, null, TextUtil.fastReplace(prompt, "CARDNAME", CardTranslation.getTranslatedName(sa.getHostCard().getName())))) { + String prompt = !optionalAbilityPrompt.isEmpty() ? optionalAbilityPrompt : Localizer.getInstance().getMessage("lblWouldYouLikeProceedWithOptionalAbility") + " " + host + "?\n\n(" + sa.getDescription() + ")"; + if (!p.getController().confirmAction(sa, null, TextUtil.fastReplace(prompt, "CARDNAME", CardTranslation.getTranslatedName(host.getName())))) { return; } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java index a06854fbe46..d59984d04e8 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DigMultipleEffect.java @@ -26,7 +26,6 @@ public class DigMultipleEffect extends SpellAbilityEffect { final Card host = sa.getHostCard(); final Player player = sa.getActivatingPlayer(); final Game game = player.getGame(); - Player chooser = player; int numToDig = AbilityUtils.calculateAmount(host, sa.getParam("DigNum"), sa); final ZoneType srcZone = sa.hasParam("SourceZone") ? ZoneType.smartValueOf(sa.getParam("SourceZone")) : ZoneType.Library; @@ -40,13 +39,13 @@ public class DigMultipleEffect extends SpellAbilityEffect { boolean chooseOptional = sa.hasParam("Optional"); CardZoneTable table = new CardZoneTable(); - for (final Player p : getTargetPlayers(sa)) { - if (sa.usesTargeting() && !p.canBeTargetedBy(sa)) { + for (final Player chooser : getDefinedPlayersOrTargeted(sa)) { + if (sa.usesTargeting() && !chooser.canBeTargetedBy(sa)) { continue; } final CardCollection top = new CardCollection(); final CardCollection rest = new CardCollection(); - final PlayerZone sourceZone = p.getZone(srcZone); + final PlayerZone sourceZone = chooser.getZone(srcZone); numToDig = Math.min(numToDig, sourceZone.size()); for (int i = 0; i < numToDig; i++) { @@ -60,10 +59,10 @@ public class DigMultipleEffect extends SpellAbilityEffect { rest.addAll(top); if (sa.hasParam("Reveal")) { - game.getAction().reveal(top, p, false); + game.getAction().reveal(top, chooser, false); } else { // reveal cards first - game.getAction().revealTo(top, player); + game.getAction().revealTo(top, chooser); } Map validMap = Maps.newHashMap(); diff --git a/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt b/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt index 85c4862a634..f3c5a9ddb03 100644 --- a/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt +++ b/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt @@ -12,8 +12,7 @@ ALTERNATE Name:Explore the Vastlands ManaCost:3 Types:Sorcery -A:SP$ RepeatEach | RepeatPlayers$ Player | RepeatSubAbility$ DBDig | SpellDescription$ Each player looks at the top five cards of their library and may reveal a land card and/or an instant or sorcery card from among them. Each player puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. Each player gains 3 life. -SVar:DBDig:DB$ Dig | Defined$ Player.IsRemembered | Choser$ Player.IsRemembered | DigNum$ 5 | ChangeNum$ 1 | ChangeValid$ Land,Instant,Sorcery | RestRandomOrder$ True | SubAbility$ DBGainLife | SpellDescription$ Each player looks at the top five cards of their library, reveals a land card and/or an instant or sorcery card from among them, then puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. +A:SP$ DigMultiple | Defined$ Player | DigNum$ 5 | Optional$ True | ChangeValid$ Land,Instant,Sorcery | RestRandomOrder$ True | SpellDescription$ Each player may reveal a land card and/or an instant or sorcery card from among them, then puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. SVar:DBGainLife:DB$ GainLife | Defined$ Player | LifeAmount$ 3 DeckHas:Ability$LifeGain DeckHints:Type$Instant|Sorcery From 29a4fdb47ad716f4121d0082a3c69863e75bef61 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 1 Jun 2021 21:47:58 +0200 Subject: [PATCH 3/5] prevent StackDescription from revealing face --- forge-game/src/main/java/forge/game/card/CardUtil.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/forge-game/src/main/java/forge/game/card/CardUtil.java b/forge-game/src/main/java/forge/game/card/CardUtil.java index f1e86cdc08f..1d57962e6ab 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -221,6 +221,8 @@ public final class CardUtil { newCopy.getCurrentState().copyFrom(in.getState(in.getFaceupCardStateName()), true); if (in.isFaceDown()) { + // prevent StackDescription from revealing face + newCopy.setName(in.toString()); newCopy.turnFaceDownNoUpdate(); } From beff3d483208c2acb72b08c78dcfcc248241c9b3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 1 Jun 2021 22:11:01 +0200 Subject: [PATCH 4/5] Fix Runaway Carriage --- forge-gui/res/cardsfolder/r/runaway_carriage.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/r/runaway_carriage.txt b/forge-gui/res/cardsfolder/r/runaway_carriage.txt index 44470f5b2d0..e157bd07062 100644 --- a/forge-gui/res/cardsfolder/r/runaway_carriage.txt +++ b/forge-gui/res/cardsfolder/r/runaway_carriage.txt @@ -5,7 +5,7 @@ PT:5/6 K:Trample T:Mode$ Attacks | ValidCard$ Card.Self | Execute$ DelTrig | TriggerDescription$ Whenever CARDNAME attacks or blocks, sacrifice it at end of combat. T:Mode$ Blocks | ValidCard$ Card.Self | Execute$ DelTrig | Secondary$ True | TriggerDescription$ Whenever CARDNAME attacks or blocks, sacrifice it at end of combat. -SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | ValidPlayer$ Player | Execute$ TrigSacrifice | TriggerDescription$ Sacrifice CARDNAME at end of combat. +SVar:DelTrig:DB$ DelayedTrigger | Mode$ Phase | Phase$ EndCombat | RememberObjects$ Self | ValidPlayer$ Player | Execute$ TrigSacrifice | TriggerDescription$ Sacrifice CARDNAME at end of combat. SVar:TrigSacrifice:DB$ SacrificeAll | Defined$ DelayTriggerRememberedLKI SVar:SacrificeEndCombat:True Oracle:Trample\nWhen Runaway Carriage attacks or blocks, sacrifice it at end of combat. From faeb73d8b7deff060eec2c2a65013f3798966234 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 1 Jun 2021 22:29:15 +0200 Subject: [PATCH 5/5] Clean up --- .../cardsfolder/w/wandering_archaic_explore_the_vastlands.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt b/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt index f3c5a9ddb03..75049133171 100644 --- a/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt +++ b/forge-gui/res/cardsfolder/w/wandering_archaic_explore_the_vastlands.txt @@ -12,7 +12,7 @@ ALTERNATE Name:Explore the Vastlands ManaCost:3 Types:Sorcery -A:SP$ DigMultiple | Defined$ Player | DigNum$ 5 | Optional$ True | ChangeValid$ Land,Instant,Sorcery | RestRandomOrder$ True | SpellDescription$ Each player may reveal a land card and/or an instant or sorcery card from among them, then puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. +A:SP$ DigMultiple | Defined$ Player | DigNum$ 5 | Optional$ True | ChangeValid$ Land,Spell.HasNoSubtype Aura | RestRandomOrder$ True | SpellDescription$ Each player may reveal a land card and/or an instant or sorcery card from among them, then puts the cards they revealed this way into their hand and the rest on the bottom of their library in a random order. SVar:DBGainLife:DB$ GainLife | Defined$ Player | LifeAmount$ 3 DeckHas:Ability$LifeGain DeckHints:Type$Instant|Sorcery