From f6f2d5e4dea63bce5aedcd28dacf2d61531857fd Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 2 Jun 2021 18:56:52 +0200 Subject: [PATCH 1/9] Fix Attachments not phasing back in when the card attached to does --- .../main/java/forge/game/ability/effects/PhasesEffect.java | 2 +- forge-game/src/main/java/forge/game/card/Card.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/PhasesEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PhasesEffect.java index cc4bc385c12..4c0f1995f72 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PhasesEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PhasesEffect.java @@ -72,7 +72,7 @@ public class PhasesEffect extends SpellAbilityEffect { for (final Card tgtC : tgtCards) { if (!tgtC.isPhasedOut()) { tgtC.phase(false); - if ( tgtC.isPhasedOut()) { + if (tgtC.isPhasedOut()) { tgtC.setWontPhaseInNormal(wontPhaseInNormal); } } 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 9c518a4d416..4c7f9df4897 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4608,8 +4608,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { setDirectlyPhasedOut(direct); } - if (hasCardAttachments()) { - for (final Card eq : getAttachedCards()) { + // CR 702.25g + if (!getAllAttachedCards().isEmpty()) { + for (final Card eq : getAllAttachedCards()) { if (eq.isPhasedOut() == phasingIn) { eq.phase(fromUntapStep, false); } From 58866b0595f9d2ab40ce7a009732397b9fc799d1 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 2 Jun 2021 19:57:30 +0200 Subject: [PATCH 2/9] when phasing out end Until --- forge-game/src/main/java/forge/game/card/Card.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 4c7f9df4897..132095e538a 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4627,7 +4627,6 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } private boolean switchPhaseState(final boolean fromUntapStep) { - if (phasedOut && hasKeyword("CARDNAME can't phase in.")) { return false; } @@ -4646,6 +4645,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // If this is currently PhasedIn, it's about to phase out. // Run trigger before it does because triggers don't work with phased out objects getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false); + runLeavesPlayCommands(); + runUntapCommands(); } setPhasedOut(!phasedOut); From db8595800848cf7bcbe52fe829af4ed66eb06a68 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 2 Jun 2021 20:56:59 +0200 Subject: [PATCH 3/9] Fix effects on phased out cards --- .../java/forge/game/ability/effects/ChangeZoneEffect.java | 2 +- forge-game/src/main/java/forge/game/card/Card.java | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) 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 a660dca451e..7d2d07e1985 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 @@ -502,7 +502,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { // gameCard is LKI in that case, the card is not in game anymore // or the timestamp did change // this should check Self too - if (gameCard == null || !tgtC.equalsWithTimestamp(gameCard)) { + if (gameCard == null || !tgtC.equalsWithTimestamp(gameCard) || gameCard.isPhasedOut()) { continue; } if (sa.usesTargeting() && !gameCard.canBeTargetedBy(sa)) { 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 132095e538a..e88d4af3292 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4645,8 +4645,9 @@ public class Card extends GameEntity implements Comparable, IHasSVars { // If this is currently PhasedIn, it's about to phase out. // Run trigger before it does because triggers don't work with phased out objects getGame().getTriggerHandler().runTrigger(TriggerType.PhaseOut, runParams, false); - runLeavesPlayCommands(); + // when it doesn't exist the game will no longer see it as tapped runUntapCommands(); + // TODO need to run UntilHostLeavesPlay commands but only when worded "for as long as" } setPhasedOut(!phasedOut); @@ -5770,11 +5771,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public final boolean canBeDestroyed() { - return isInPlay() && (!hasKeyword(Keyword.INDESTRUCTIBLE) || (isCreature() && getNetToughness() <= 0)); + return isInPlay() && !isPhasedOut() && (!hasKeyword(Keyword.INDESTRUCTIBLE) || (isCreature() && getNetToughness() <= 0)); } public final boolean canBeSacrificed() { - return isInPlay() && !this.isPhasedOut() && !hasKeyword("CARDNAME can't be sacrificed."); + return isInPlay() && !isPhasedOut() && !hasKeyword("CARDNAME can't be sacrificed."); } @Override From d0d14b900695fbebbdc496feda06d26cea342908 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 2 Jun 2021 22:26:21 +0200 Subject: [PATCH 4/9] Fix missing trigger when phased out --- .../src/main/java/forge/game/ability/SpellAbilityEffect.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 fc62803172a..f41a8bf9390 100644 --- a/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java +++ b/forge-game/src/main/java/forge/game/ability/SpellAbilityEffect.java @@ -21,6 +21,7 @@ import forge.game.GameObject; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; +import forge.game.card.CardUtil; import forge.game.card.CardZoneTable; import forge.game.combat.Combat; import forge.game.phase.PhaseType; @@ -296,7 +297,7 @@ public abstract class SpellAbilityEffect { } delTrig.append("| TriggerDescription$ ").append(desc); - final Trigger trig = TriggerHandler.parseTrigger(delTrig.toString(), sa.getHostCard(), intrinsic); + final Trigger trig = TriggerHandler.parseTrigger(delTrig.toString(), CardUtil.getLKICopy(sa.getHostCard()), intrinsic); for (final Card c : crds) { trig.addRemembered(c); From 2d53623ab26d35136dbced0ebe71b8b358c18d29 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 2 Jun 2021 23:10:13 +0200 Subject: [PATCH 5/9] Fix echo cost not skipable with phasing --- forge-game/src/main/java/forge/game/phase/PhaseHandler.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java index 3adc5e03416..9974a79bebf 100644 --- a/forge-game/src/main/java/forge/game/phase/PhaseHandler.java +++ b/forge-game/src/main/java/forge/game/phase/PhaseHandler.java @@ -475,7 +475,7 @@ public class PhaseHandler implements java.io.Serializable { boolean manaBurns = game.getRules().hasManaBurn() || (game.getStaticEffects().getGlobalRuleChange(GlobalRuleChange.manaBurn)); if (manaBurns) { - p.loseLife(burn,true); + p.loseLife(burn, true); } } @@ -485,7 +485,7 @@ public class PhaseHandler implements java.io.Serializable { break; case UPKEEP: - for (Card c : game.getCardsIn(ZoneType.Battlefield)) { + for (Card c : game.getCardsIncludePhasingIn(ZoneType.Battlefield)) { c.getDamageHistory().setNotAttackedSinceLastUpkeepOf(playerTurn); c.getDamageHistory().setNotBlockedSinceLastUpkeepOf(playerTurn); c.getDamageHistory().setNotBeenBlockedSinceLastUpkeepOf(playerTurn); From 83dc9b688b63d5106dff31f8140d60753397261b Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 3 Jun 2021 00:27:16 +0200 Subject: [PATCH 6/9] Fix for phasing --- forge-game/src/main/java/forge/game/Game.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index a4ef170fe74..f322fd5ad39 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -756,7 +756,7 @@ public class Game { // Rule 800.4 Losing a Multiplayer game CardCollectionView cards = this.getCardsInGame(); boolean planarControllerLost = false; - boolean isMultiplayer = this.getPlayers().size() > 2; + boolean isMultiplayer = getPlayers().size() > 2; // 702.142f & 707.9 // If a player leaves the game, all face-down cards that player owns must be revealed to all players. @@ -793,16 +793,16 @@ public class Game { } getAction().ceaseToExist(c, false); // CR 603.2f owner of trigger source lost game - triggerHandler.clearDelayedTrigger(c); + getTriggerHandler().clearDelayedTrigger(c); } else { // return stolen permanents - if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) { + if ((c.getController().equals(p) || c.getZone().getPlayer().equals(p)) && c.isInZone(ZoneType.Battlefield)) { c.removeTempController(p); getAction().controllerChangeZoneCorrection(c); } c.removeTempController(p); if (c.getController().equals(p)) { - this.getAction().exile(c, null); + getAction().exile(c, null); } } } else { @@ -830,7 +830,7 @@ public class Game { } // Remove leftover items from - this.getStack().removeInstancesControlledBy(p); + getStack().removeInstancesControlledBy(p); getTriggerHandler().onPlayerLost(p); From c648a8ccbcac008dc09dd9cf9b437c3b206a71d9 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 3 Jun 2021 06:22:15 +0200 Subject: [PATCH 7/9] Stop counting phased out cards --- forge-game/src/main/java/forge/game/card/Card.java | 2 ++ forge-game/src/main/java/forge/game/card/CardProperty.java | 5 +++++ forge-game/src/main/java/forge/game/card/CardUtil.java | 2 ++ 3 files changed, 9 insertions(+) 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 e88d4af3292..8424f34c356 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -4661,6 +4661,8 @@ public class Card extends GameEntity implements Comparable, IHasSVars { getGame().getTriggerHandler().registerActiveTrigger(this, false); getGame().getTriggerHandler().runTrigger(TriggerType.PhaseIn, runParams, false); } + + game.updateLastStateForCard(this); return true; } 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 b477bcc6010..a6b61a78995 100644 --- a/forge-game/src/main/java/forge/game/card/CardProperty.java +++ b/forge-game/src/main/java/forge/game/card/CardProperty.java @@ -47,6 +47,11 @@ public class CardProperty { final Card lki = game.getChangeZoneLKIInfo(card); final Player controller = lki.getController(); + // CR 702.25b if card is phased out it will not count unless specifically asked for + if (card.isPhasedOut() && !property.contains("phasedOut")) { + return false; + } + // by name can also have color names, so needs to happen before colors. if (property.startsWith("named")) { String name = TextUtil.fastReplace(property.substring(5), ";", ","); // for some legendary cards 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 1d57962e6ab..f6181cdf596 100644 --- a/forge-game/src/main/java/forge/game/card/CardUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardUtil.java @@ -253,6 +253,8 @@ public final class CardUtil { newCopy.setCounters(Maps.newHashMap(in.getCounters())); newCopy.setColor(in.determineColor().getColor()); + newCopy.setPhasedOut(in.isPhasedOut()); + newCopy.setReceivedDamageFromThisTurn(in.getReceivedDamageFromThisTurn()); newCopy.setDamageHistory(in.getDamageHistory()); for (Card c : in.getBlockedThisTurn()) { From dccf161d540a9a6a8327f3a000b128d5f482b162 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 3 Jun 2021 12:04:47 +0200 Subject: [PATCH 8/9] Fix Untap of card that should't after phasing in --- forge-game/src/main/java/forge/game/phase/Untap.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/forge-game/src/main/java/forge/game/phase/Untap.java b/forge-game/src/main/java/forge/game/phase/Untap.java index e5f2ffdc0e6..1fec36dc06b 100644 --- a/forge-game/src/main/java/forge/game/phase/Untap.java +++ b/forge-game/src/main/java/forge/game/phase/Untap.java @@ -71,6 +71,8 @@ public class Untap extends Phase { final Player turn = game.getPhaseHandler().getPlayerTurn(); Untap.doPhasing(turn); + + game.getAction().checkStaticAbilities(); doUntap(); } From 08d6b11adde3767fa276b210b0e457c3778eb426 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 3 Jun 2021 12:28:16 +0200 Subject: [PATCH 9/9] Clean up --- forge-ai/src/main/java/forge/ai/AiAttackController.java | 1 - forge-core/src/main/java/forge/card/CardAiHints.java | 3 --- forge-gui/res/cardsfolder/a/azors_elocutors.txt | 2 +- 3 files changed, 1 insertion(+), 5 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index 9f78b5b3336..e0c01f01feb 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -676,7 +676,6 @@ public class AiAttackController { * @return a {@link forge.game.combat.Combat} object. */ public final void declareAttackers(final Combat combat) { - if (this.attackers.isEmpty()) { return; } diff --git a/forge-core/src/main/java/forge/card/CardAiHints.java b/forge-core/src/main/java/forge/card/CardAiHints.java index a7b2c8e7255..746f7297a4f 100644 --- a/forge-core/src/main/java/forge/card/CardAiHints.java +++ b/forge-core/src/main/java/forge/card/CardAiHints.java @@ -6,7 +6,6 @@ package forge.card; */ public class CardAiHints { - private final boolean isRemovedFromAIDecks; private final boolean isRemovedFromRandomDecks; private final boolean isRemovedFromNonCommanderDecks; @@ -15,7 +14,6 @@ public class CardAiHints { private final DeckHints deckNeeds; private final DeckHints deckHas; - public CardAiHints(boolean remAi, boolean remRandom, boolean remUnlessCommander, DeckHints dh, DeckHints dn, DeckHints has) { isRemovedFromAIDecks = remAi; isRemovedFromRandomDecks = remRandom; @@ -90,5 +88,4 @@ public class CardAiHints { } } - } diff --git a/forge-gui/res/cardsfolder/a/azors_elocutors.txt b/forge-gui/res/cardsfolder/a/azors_elocutors.txt index bebbf501851..852b6471dee 100644 --- a/forge-gui/res/cardsfolder/a/azors_elocutors.txt +++ b/forge-gui/res/cardsfolder/a/azors_elocutors.txt @@ -8,5 +8,5 @@ SVar:WinGame:DB$ WinsGame | Defined$ You | ConditionCheckSVar$ TalkedEnough | Co SVar:TalkedEnough:Count$CardCounters.FILIBUSTER T:Mode$ DamageDone | ValidTarget$ You | TriggerZones$ Battlefield | Execute$ RemoveCounter | TriggerDescription$ Whenever a source deals damage to you, remove a filibuster counter from CARDNAME. SVar:RemoveCounter:DB$ RemoveCounter | Defined$ Self | CounterType$ FILIBUSTER | CounterNum$ 1 -SVar:Picture:http://www.wizards.com/global/images/magic/general/azors_elocutors.jpg +SVar:AIEvaluationModifier:30 Oracle:At the beginning of your upkeep, put a filibuster counter on Azor's Elocutors. Then if Azor's Elocutors has five or more filibuster counters on it, you win the game.\nWhenever a source deals damage to you, remove a filibuster counter from Azor's Elocutors.