Merge branch 'fixmp' into 'master'

Fix Multiplayer LTB triggers

Closes #1324

See merge request core-developers/forge!4511
This commit is contained in:
Michael Kamensky
2021-04-16 04:59:35 +00:00
8 changed files with 31 additions and 19 deletions

View File

@@ -1029,7 +1029,7 @@ public class PlayerControllerAi extends PlayerController {
*/ */
if (sa.isMayChooseNewTargets() && !sa.setupTargets()) { if (sa.isMayChooseNewTargets() && !sa.setupTargets()) {
if (sa.isSpell()) { if (sa.isSpell()) {
sa.getHostCard().ceaseToExist(); sa.getHostCard().ceaseToExist(false);
} }
continue; continue;
} }

View File

@@ -769,6 +769,13 @@ public class Game {
p.revealFaceDownCards(); 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())) { if (c.getController().equals(p) && (c.isPlane() || c.isPhenomenon())) {
planarControllerLost = true; planarControllerLost = true;
@@ -783,7 +790,9 @@ public class Game {
cc.removeEncodedCard(c); cc.removeEncodedCard(c);
cc.removeRemembered(c); cc.removeRemembered(c);
} }
c.ceaseToExist(); c.ceaseToExist(false);
// CR 603.2f owner of trigger source lost game
triggerHandler.clearDelayedTrigger(c);
} else { } else {
// return stolen permanents // return stolen permanents
if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) { if (c.getController().equals(p) && c.isInZone(ZoneType.Battlefield)) {

View File

@@ -6756,11 +6756,15 @@ public class Card extends GameEntity implements Comparable<Card>, IHasSVars {
} }
} }
public void ceaseToExist() { public void ceaseToExist(boolean skipTrig) {
getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone); // CR 603.6c other players LTB triggers should work
if (skipTrig) {
getZone().remove(this); getZone().remove(this);
setZone(null); setZone(getOwner().getZone(ZoneType.None));
getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone); }
else {
game.getAction().moveTo(ZoneType.None, this, null);
}
} }
public void forceTurnFaceUp() { public void forceTurnFaceUp() {

View File

@@ -133,7 +133,7 @@ import forge.util.collect.FCollectionView;
public class Player extends GameEntity implements Comparable<Player> { public class Player extends GameEntity implements Comparable<Player> {
public static final List<ZoneType> ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield, public static final List<ZoneType> ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield,
ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante, 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<Card, Integer> commanderDamage = Maps.newHashMap(); private final Map<Card, Integer> commanderDamage = Maps.newHashMap();

View File

@@ -2361,7 +2361,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
public void rollback() { public void rollback() {
for (Card c : rollbackEffects) { for (Card c : rollbackEffects) {
c.ceaseToExist(); c.ceaseToExist(true);
} }
rollbackEffects.clear(); rollbackEffects.clear();
} }

View File

@@ -631,13 +631,12 @@ public class TriggerHandler {
} }
public void onPlayerLost(Player p) { public void onPlayerLost(Player p) {
List<Trigger> lost = new ArrayList<>(); List<Trigger> lost = new ArrayList<>(delayedTriggers);
for (Trigger t : delayedTriggers) { for (Trigger t : lost) {
// CR 603.2f owner of trigger source lost game || 800.4d trigger controller lost game // CR 800.4d trigger controller lost game
if (game.getCardState(t.getHostCard(), null) == null || t.getHostCard().getOwner().equals(p)) { if (t.getHostCard().getOwner().equals(p)) {
lost.add(t); delayedTriggers.remove(t);
} }
} }
delayedTriggers.removeAll(lost);
} }
} }

View File

@@ -586,7 +586,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable<SpellAbil
} }
if (source.isCopiedSpell() && source.isInZone(ZoneType.Stack)) { if (source.isCopiedSpell() && source.isInZone(ZoneType.Stack)) {
source.ceaseToExist(); source.ceaseToExist(true);
return; return;
} }

View File

@@ -2841,7 +2841,7 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont
continue; continue;
} }
c.getZone().remove(c); c.getZone().remove(c);
c.ceaseToExist(); c.ceaseToExist(true);
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats."); sb.append(p).append(" removes ").append(c).append(" from game due to Dev Cheats.");