From 2f7a30f920161a4b3449878e2a9c1ab76c5c78fd Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Wed, 14 Apr 2021 20:30:17 +0200 Subject: [PATCH 1/4] Fix Multiplayer LTB triggers --- .../src/main/java/forge/ai/PlayerControllerAi.java | 2 +- forge-game/src/main/java/forge/game/Game.java | 2 +- forge-game/src/main/java/forge/game/card/Card.java | 14 +++++++++----- .../src/main/java/forge/game/player/Player.java | 2 +- .../java/forge/game/spellability/SpellAbility.java | 2 +- .../src/main/java/forge/game/zone/MagicStack.java | 2 +- .../java/forge/player/PlayerControllerHuman.java | 2 +- 7 files changed, 15 insertions(+), 11 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 334fd63fd30..4902eebdcd9 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -1029,7 +1029,7 @@ public class PlayerControllerAi extends PlayerController { */ if (sa.isMayChooseNewTargets() && !sa.setupTargets()) { if (sa.isSpell()) { - sa.getHostCard().ceaseToExist(); + sa.getHostCard().ceaseToExist(false); } continue; } diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 1a3659d3d2d..527d7ee523d 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -783,7 +783,7 @@ public class Game { cc.removeEncodedCard(c); cc.removeRemembered(c); } - c.ceaseToExist(); + c.ceaseToExist(false); } else { // return stolen permanents if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) { 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 1aaf6a1dba9..63de2504845 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -6756,11 +6756,15 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } } - public void ceaseToExist() { - getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone); - getZone().remove(this); - setZone(null); - getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); + public void ceaseToExist(boolean skipTrig) { + // CR 800.4d if card is controlled by opponent, LTB should trigger + if (skipTrig && getOwner().equals(getController())) { + getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone); + } + game.getAction().moveTo(ZoneType.None, this, null); + if (skipTrig && getOwner().equals(getController())) { + getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); + } } public void forceTurnFaceUp() { 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 b5dd3af1353..bc8f479f3ef 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -133,7 +133,7 @@ import forge.util.collect.FCollectionView; public class Player extends GameEntity implements Comparable { public static final List ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield, ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante, - ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.Merged, ZoneType.Subgame)); + ZoneType.Sideboard, ZoneType.PlanarDeck, ZoneType.SchemeDeck, ZoneType.Merged, ZoneType.Subgame, ZoneType.None)); private final Map commanderDamage = Maps.newHashMap(); diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 6245c3fe132..145c9fe8413 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -2361,7 +2361,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit public void rollback() { for (Card c : rollbackEffects) { - c.ceaseToExist(); + c.ceaseToExist(true); } rollbackEffects.clear(); } 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 0c0e5ea7500..434d854065a 100644 --- a/forge-game/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-game/src/main/java/forge/game/zone/MagicStack.java @@ -586,7 +586,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable Date: Wed, 14 Apr 2021 20:37:11 +0200 Subject: [PATCH 2/4] Fix logic --- forge-game/src/main/java/forge/game/card/Card.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 63de2504845..03c17d5808d 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -6758,11 +6758,11 @@ public class Card extends GameEntity implements Comparable, IHasSVars { public void ceaseToExist(boolean skipTrig) { // CR 800.4d if card is controlled by opponent, LTB should trigger - if (skipTrig && getOwner().equals(getController())) { + if (skipTrig || getOwner().equals(getController())) { getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone); } game.getAction().moveTo(ZoneType.None, this, null); - if (skipTrig && getOwner().equals(getController())) { + if (skipTrig || getOwner().equals(getController())) { getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); } } From 5aaf39f40b2f67184bcc66f1a4e9a6af25a502bf Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 15 Apr 2021 20:20:52 +0200 Subject: [PATCH 3/4] LTB triggers for opponents --- forge-game/src/main/java/forge/game/Game.java | 13 +++++++++++-- forge-game/src/main/java/forge/game/card/Card.java | 12 ++++++------ .../java/forge/game/trigger/TriggerHandler.java | 4 ++-- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java index 527d7ee523d..cf68f0b4cb7 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -768,13 +768,20 @@ public class Game { } else { p.revealFaceDownCards(); } + + for (Card c : cards) { + // CR 800.4d if card is controlled by opponent, LTB should trigger + if (c.getOwner().equals(p) && c.getController().equals(p)) { + c.getCurrentState().clearTriggers(); + } + } - for(Card c : cards) { + for (Card c : cards) { if (c.getController().equals(p) && (c.isPlane() || c.isPhenomenon())) { planarControllerLost = true; } - if(isMultiplayer) { + if (isMultiplayer) { // unattach all "Enchant Player" c.removeAttachedTo(p); if (c.getOwner().equals(p)) { @@ -784,6 +791,8 @@ public class Game { cc.removeRemembered(c); } c.ceaseToExist(false); + // CR 603.2f owner of trigger source lost game + triggerHandler.clearDelayedTrigger(c); } else { // return stolen permanents if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) { 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 03c17d5808d..2e590f74a3c 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -6757,13 +6757,13 @@ public class Card extends GameEntity implements Comparable, IHasSVars { } public void ceaseToExist(boolean skipTrig) { - // CR 800.4d if card is controlled by opponent, LTB should trigger - if (skipTrig || getOwner().equals(getController())) { - getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone); + // CR 603.6c other players LTB triggers should work + if (skipTrig) { + getZone().remove(this); + setZone(getOwner().getZone(ZoneType.None)); } - game.getAction().moveTo(ZoneType.None, this, null); - if (skipTrig || getOwner().equals(getController())) { - getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); + else { + game.getAction().moveTo(ZoneType.None, this, null); } } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index 7ddf5b28cff..d990767b3ab 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -633,8 +633,8 @@ public class TriggerHandler { public void onPlayerLost(Player p) { List lost = new ArrayList<>(); for (Trigger t : delayedTriggers) { - // CR 603.2f owner of trigger source lost game || 800.4d trigger controller lost game - if (game.getCardState(t.getHostCard(), null) == null || t.getHostCard().getOwner().equals(p)) { + // CR 800.4d trigger controller lost game + if (t.getHostCard().getOwner().equals(p)) { lost.add(t); } } From 237b0324c1bf2a37098043b5f588b431c197fdc9 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Thu, 15 Apr 2021 20:23:07 +0200 Subject: [PATCH 4/4] Clean up --- forge-game/src/main/java/forge/game/Game.java | 2 +- .../src/main/java/forge/game/trigger/TriggerHandler.java | 7 +++---- 2 files changed, 4 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 cf68f0b4cb7..0527a1e0063 100644 --- a/forge-game/src/main/java/forge/game/Game.java +++ b/forge-game/src/main/java/forge/game/Game.java @@ -768,7 +768,7 @@ public class Game { } else { p.revealFaceDownCards(); } - + for (Card c : cards) { // CR 800.4d if card is controlled by opponent, LTB should trigger if (c.getOwner().equals(p) && c.getController().equals(p)) { diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java index d990767b3ab..656829d12b1 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerHandler.java @@ -631,13 +631,12 @@ public class TriggerHandler { } public void onPlayerLost(Player p) { - List lost = new ArrayList<>(); - for (Trigger t : delayedTriggers) { + List lost = new ArrayList<>(delayedTriggers); + for (Trigger t : lost) { // CR 800.4d trigger controller lost game if (t.getHostCard().getOwner().equals(p)) { - lost.add(t); + delayedTriggers.remove(t); } } - delayedTriggers.removeAll(lost); } }