From 4c59551cf020f0af12e55714d44bd0a4ac5de3b9 Mon Sep 17 00:00:00 2001 From: Oleg Agafonov Date: Fri, 30 Jun 2023 07:15:21 +0400 Subject: [PATCH] number of triggers event - fixed game error with state based triggers (NPE in cards like Veyran, Voice of Duality); --- Mage.Sets/src/mage/cards/d/DungeonDelver.java | 3 ++- Mage.Sets/src/mage/cards/h/HamaPasharRuinSeeker.java | 3 ++- Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java | 5 +++++ Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java | 9 +++++++-- Mage.Sets/src/mage/cards/t/TeysaKarlov.java | 3 ++- Mage.Sets/src/mage/cards/v/VeyranVoiceOfDuality.java | 4 ++++ Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java | 4 ++++ .../src/main/java/mage/abilities/TriggeredAbilities.java | 3 ++- .../java/mage/game/events/NumberOfTriggersEvent.java | 1 + 9 files changed, 29 insertions(+), 6 deletions(-) diff --git a/Mage.Sets/src/mage/cards/d/DungeonDelver.java b/Mage.Sets/src/mage/cards/d/DungeonDelver.java index 269dc899db2..f7810d3cdc2 100644 --- a/Mage.Sets/src/mage/cards/d/DungeonDelver.java +++ b/Mage.Sets/src/mage/cards/d/DungeonDelver.java @@ -66,7 +66,8 @@ class DungeonDelverEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { GameEvent gameEvent = ((NumberOfTriggersEvent) event).getSourceEvent(); - return gameEvent.getType() == GameEvent.EventType.ROOM_ENTERED + return gameEvent != null + && gameEvent.getType() == GameEvent.EventType.ROOM_ENTERED && source.isControlledBy(gameEvent.getPlayerId()); } diff --git a/Mage.Sets/src/mage/cards/h/HamaPasharRuinSeeker.java b/Mage.Sets/src/mage/cards/h/HamaPasharRuinSeeker.java index 78b99a5a32d..32854057ae3 100644 --- a/Mage.Sets/src/mage/cards/h/HamaPasharRuinSeeker.java +++ b/Mage.Sets/src/mage/cards/h/HamaPasharRuinSeeker.java @@ -65,7 +65,8 @@ class HamaPasharRuinSeekerEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { GameEvent gameEvent = ((NumberOfTriggersEvent) event).getSourceEvent(); - return gameEvent.getType() == GameEvent.EventType.ROOM_ENTERED + return gameEvent != null + && gameEvent.getType() == GameEvent.EventType.ROOM_ENTERED && source.isControlledBy(gameEvent.getPlayerId()); } diff --git a/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java b/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java index c63a239b8d4..e93b57b1043 100644 --- a/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java +++ b/Mage.Sets/src/mage/cards/i/IsshinTwoHeavensAsOne.java @@ -71,7 +71,12 @@ class IsshinTwoHeavensAsOneEffect extends ReplacementEffectImpl { if (sourcePermanent == null || !sourcePermanent.isControlledBy(source.getControllerId())) { return false; } + GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + if (sourceEvent == null) { + return false; + } + switch (sourceEvent.getType()) { case ATTACKER_DECLARED: case DECLARED_ATTACKERS: diff --git a/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java b/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java index bd1b841f999..7365d136537 100644 --- a/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java +++ b/Mage.Sets/src/mage/cards/p/PrecipiceOfMortis.java @@ -69,7 +69,9 @@ class PrecipiceOfMortisEffect extends ReplacementEffectImpl { if (source.isControlledBy(event.getPlayerId())) { GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); // enters triggers - if (sourceEvent.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD && sourceEvent instanceof EntersTheBattlefieldEvent) { + if (sourceEvent != null + && sourceEvent.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD + && sourceEvent instanceof EntersTheBattlefieldEvent) { EntersTheBattlefieldEvent entersTheBattlefieldEvent = (EntersTheBattlefieldEvent) sourceEvent; // Only for entering Jedis if (entersTheBattlefieldEvent.getTarget().hasSubtype(SubType.JEDI, game)) { @@ -79,8 +81,11 @@ class PrecipiceOfMortisEffect extends ReplacementEffectImpl { } } } + // leaves triggers - if (sourceEvent.getType() == GameEvent.EventType.ZONE_CHANGE && sourceEvent instanceof ZoneChangeEvent) { + if (sourceEvent != null + && sourceEvent.getType() == GameEvent.EventType.ZONE_CHANGE + && sourceEvent instanceof ZoneChangeEvent) { ZoneChangeEvent leavesTheBattlefieldEvent = (ZoneChangeEvent) sourceEvent; if (leavesTheBattlefieldEvent.getFromZone() == Zone.BATTLEFIELD) { // Only for leaving Jedis diff --git a/Mage.Sets/src/mage/cards/t/TeysaKarlov.java b/Mage.Sets/src/mage/cards/t/TeysaKarlov.java index 1fb0fe98832..8cf1752bc29 100644 --- a/Mage.Sets/src/mage/cards/t/TeysaKarlov.java +++ b/Mage.Sets/src/mage/cards/t/TeysaKarlov.java @@ -92,7 +92,8 @@ class TeysaKarlovEffect extends ReplacementEffectImpl { && game.getPermanentOrLKIBattlefield(numberOfTriggersEvent.getSourceId()) != null && numberOfTriggersEvent.getSourceEvent() instanceof ZoneChangeEvent) { ZoneChangeEvent zEvent = (ZoneChangeEvent) numberOfTriggersEvent.getSourceEvent(); - return zEvent.isDiesEvent() + return zEvent != null + && zEvent.isDiesEvent() && zEvent.getTarget() != null && zEvent.getTarget().isCreature(game); } diff --git a/Mage.Sets/src/mage/cards/v/VeyranVoiceOfDuality.java b/Mage.Sets/src/mage/cards/v/VeyranVoiceOfDuality.java index 03d3a4c830b..9dc1cee22a8 100644 --- a/Mage.Sets/src/mage/cards/v/VeyranVoiceOfDuality.java +++ b/Mage.Sets/src/mage/cards/v/VeyranVoiceOfDuality.java @@ -75,6 +75,10 @@ class VeyranVoiceOfDualityEffect extends ReplacementEffectImpl { public boolean applies(GameEvent event, Ability source, Game game) { NumberOfTriggersEvent numberOfTriggersEvent = (NumberOfTriggersEvent) event; GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + if (sourceEvent == null) { + return false; + } + if (sourceEvent.getType() == GameEvent.EventType.SPELL_CAST || sourceEvent.getType() == GameEvent.EventType.COPIED_STACKOBJECT) { Spell spell = game.getSpell(sourceEvent.getTargetId()); diff --git a/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java b/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java index 5d2c1a96f16..9a84b815b0b 100644 --- a/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java +++ b/Mage.Sets/src/mage/cards/w/WulfgarOfIcewindDale.java @@ -78,6 +78,10 @@ class WulfgarOfIcewindDaleEffect extends ReplacementEffectImpl { return false; } GameEvent sourceEvent = numberOfTriggersEvent.getSourceEvent(); + if (sourceEvent == null) { + return false; + } + switch (sourceEvent.getType()) { case ATTACKER_DECLARED: return source.isControlledBy(sourceEvent.getPlayerId()); diff --git a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java index e97d19d2cf4..459187f9af0 100644 --- a/Mage/src/main/java/mage/abilities/TriggeredAbilities.java +++ b/Mage/src/main/java/mage/abilities/TriggeredAbilities.java @@ -95,7 +95,8 @@ public class TriggeredAbilities extends ConcurrentHashMap