From 469ada0e4c75139d7c45de7a7a79f8f4ce97dc01 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Fri, 18 Mar 2022 11:55:21 +0100 Subject: [PATCH] Fix some payment NPE --- forge-ai/src/main/java/forge/ai/PlayerControllerAi.java | 2 ++ forge-ai/src/main/java/forge/ai/ability/PermanentAi.java | 3 ++- forge-game/src/main/java/forge/game/combat/CombatUtil.java | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java index 536dabf7d79..8ea8826d578 100644 --- a/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java +++ b/forge-ai/src/main/java/forge/ai/PlayerControllerAi.java @@ -699,6 +699,7 @@ public class PlayerControllerAi extends PlayerController { // TODO replace with EmptySa final Ability ability = new AbilityStatic(c, cost, null) { @Override public void resolve() {} }; ability.setActivatingPlayer(c.getController()); + ability.setCardState(sa.getCardState()); // FIXME: This is a hack to check if the AI can play the "exile from library" pay costs (Cumulative Upkeep, // e.g. Thought Lash). We have to do it and bail early if the AI can't pay, because otherwise the AI will @@ -1020,6 +1021,7 @@ public class PlayerControllerAi extends PlayerController { emptyAbility.setActivatingPlayer(player); emptyAbility.setTriggeringObjects(sa.getTriggeringObjects()); emptyAbility.setSVars(sa.getSVars()); + emptyAbility.setCardState(sa.getCardState()); emptyAbility.setXManaCostPaid(sa.getRootAbility().getXManaCostPaid()); if (ComputerUtilCost.willPayUnlessCost(sa, player, cost, alreadyPaid, allPayers) && ComputerUtilCost.canPayCost(emptyAbility, player, true)) { ComputerUtil.playNoStack(player, emptyAbility, getGame(), true); // AI needs something to resolve to pay that cost diff --git a/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java b/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java index a656bd1ec32..b13afdea52a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PermanentAi.java @@ -180,8 +180,9 @@ public class PermanentAi extends SpellAbilityAi { final SpellAbility emptyAbility = new SpellAbility.EmptySa(card, ai); emptyAbility.setPayCosts(new Cost(costs, true)); emptyAbility.setTargetRestrictions(sa.getTargetRestrictions()); - + emptyAbility.setCardState(sa.getCardState()); emptyAbility.setActivatingPlayer(ai); + if (!ComputerUtilCost.canPayCost(emptyAbility, ai, true)) { // AiPlayDecision.AnotherTime return false; 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 22e72d3516c..8483277238b 100644 --- a/forge-game/src/main/java/forge/game/combat/CombatUtil.java +++ b/forge-game/src/main/java/forge/game/combat/CombatUtil.java @@ -301,6 +301,7 @@ public class CombatUtil { // Not a great solution, but prevents a crash by passing a fake SA for Propaganda payments // If there's a better way of handling this somewhere deeper in the code, feel free to remove final SpellAbility fakeSA = new SpellAbility.EmptySa(attacker, attacker.getController()); + fakeSA.setCardState(attacker.getCurrentState()); return attacker.getController().getController().payManaOptional(attacker, attackCost, fakeSA, "Pay additional cost to declare " + attacker + " an attacker", ManaPaymentPurpose.DeclareAttacker); } @@ -345,6 +346,7 @@ public class CombatUtil { } SpellAbility fakeSA = new SpellAbility.EmptySa(blocker, blocker.getController()); + fakeSA.setCardState(blocker.getCurrentState()); return blocker.getController().getController().payManaOptional(blocker, blockCost, fakeSA, "Pay cost to declare " + blocker + " a blocker. ", ManaPaymentPurpose.DeclareBlocker); }