From 3fdc788f33894a33278f850368042ff4f228c4cc Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 26 Feb 2023 10:12:17 +0100 Subject: [PATCH 1/4] Fix Detention Sphere --- .../src/main/java/forge/ai/ability/PermanentNoncreatureAi.java | 2 +- forge-gui/res/cardsfolder/d/detention_sphere.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/PermanentNoncreatureAi.java b/forge-ai/src/main/java/forge/ai/ability/PermanentNoncreatureAi.java index 8921a2ae27a..a4d9b8215c5 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PermanentNoncreatureAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PermanentNoncreatureAi.java @@ -37,7 +37,7 @@ public class PermanentNoncreatureAi extends PermanentAi { // Check for valid targets before casting if (host.hasSVar("OblivionRing")) { SpellAbility effectExile = AbilityFactory.getAbility(host.getSVar("TrigExile"), host); - final ZoneType origin = ZoneType.listValueOf(effectExile.getParam("Origin")).get(0); + final ZoneType origin = ZoneType.listValueOf(effectExile.getParamOrDefault("Origin", "Battlefield")).get(0); effectExile.setActivatingPlayer(ai, true); CardCollection targets = CardLists.getTargetableCards(game.getCardsIn(origin), effectExile); if (sourceName.equals("Suspension Field") diff --git a/forge-gui/res/cardsfolder/d/detention_sphere.txt b/forge-gui/res/cardsfolder/d/detention_sphere.txt index cbdc89294d3..5409fb0865d 100644 --- a/forge-gui/res/cardsfolder/d/detention_sphere.txt +++ b/forge-gui/res/cardsfolder/d/detention_sphere.txt @@ -2,7 +2,7 @@ Name:Detention Sphere ManaCost:1 W U Types:Enchantment T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Card.Self | OptionalDecider$ You | Execute$ TrigExile | TriggerDescription$ When CARDNAME enters the battlefield, you may exile target nonland permanent not named Detention Sphere and all other permanents with the same name as that permanent. -SVar:TrigExile:DB$ Pump | ValidTgts$ Permanent.nonLand+notnamedDetention Sphere | TgtPrompt$ Choose target nonland permanent not named Detention Sphere | SubAbility$ DBChangeZoneAll +SVar:TrigExile:DB$ Pump | ValidTgts$ Permanent.nonLand+notnamedDetention Sphere | IsCurse$ True | TgtPrompt$ Choose target nonland permanent not named Detention Sphere | SubAbility$ DBChangeZoneAll SVar:DBChangeZoneAll:DB$ ChangeZoneAll | ChangeType$ Targeted.Self,Targeted.sameName | Origin$ Battlefield | Destination$ Exile | RememberChanged$ True | ForgetOtherRemembered$ True T:Mode$ ChangesZone | Origin$ Battlefield | Destination$ Any | ValidCard$ Card.Self | Execute$ TrigReturn | TriggerDescription$ When CARDNAME leaves the battlefield, return the exiled cards to the battlefield under their owner's control. SVar:TrigReturn:DB$ ChangeZoneAll | ChangeType$ Card.IsRemembered | Origin$ Exile | Destination$ Battlefield From 7720844e487163f307979faec30f809330c36c0f Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 26 Feb 2023 10:12:56 +0100 Subject: [PATCH 2/4] Fix Cunning Giant NPE --- forge-ai/src/main/java/forge/ai/AiAttackController.java | 1 + forge-game/src/main/java/forge/game/combat/Combat.java | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/AiAttackController.java b/forge-ai/src/main/java/forge/ai/AiAttackController.java index e431ef91f2f..2a2a81a0553 100644 --- a/forge-ai/src/main/java/forge/ai/AiAttackController.java +++ b/forge-ai/src/main/java/forge/ai/AiAttackController.java @@ -816,6 +816,7 @@ public class AiAttackController { if (combat.getAttackConstraints().getRequirements().get(attacker) == null) continue; // check defenders in order of maximum requirements for (Pair e : combat.getAttackConstraints().getRequirements().get(attacker).getSortedRequirements()) { + // TODO check if desired defender would also have the same amount if (e.getRight() == 0) continue; GameEntity mustAttackDefMaybe = e.getLeft(); // Gideon Jura returns LKI diff --git a/forge-game/src/main/java/forge/game/combat/Combat.java b/forge-game/src/main/java/forge/game/combat/Combat.java index 3c84a335955..4c29741a434 100644 --- a/forge-game/src/main/java/forge/game/combat/Combat.java +++ b/forge-game/src/main/java/forge/game/combat/Combat.java @@ -42,6 +42,7 @@ import forge.game.GameEntityCounterTable; import forge.game.GameLogEntryType; import forge.game.GameObjectMap; import forge.game.ability.AbilityKey; +import forge.game.ability.ApiType; import forge.game.card.Card; import forge.game.card.CardCollection; import forge.game.card.CardCollectionView; @@ -795,7 +796,7 @@ public class Combat { assigningPlayer = orderedBlockers.get(0).getController(); } - final SpellAbility emptySA = new SpellAbility.EmptySa(attacker); + final SpellAbility emptySA = new SpellAbility.EmptySa(ApiType.Cleanup, attacker); boolean assignToPlayer = false; if (StaticAbilityAssignCombatDamageAsUnblocked.assignCombatDamageAsUnblocked(attacker, false)) { @@ -846,8 +847,7 @@ public class Combat { // If the Attacker is unblocked, or it's a trampler and has 0 blockers, deal damage to defender if (defender instanceof Card && attacker.hasKeyword("Trample:Planeswalker")) { if (orderedBlockers == null || orderedBlockers.isEmpty()) { - CardCollection cc = new CardCollection(); - cc.add((Card)defender); + CardCollection cc = new CardCollection((Card) defender); orderedBlockers = cc; } else { orderedBlockers.add((Card) defender); @@ -862,7 +862,7 @@ public class Combat { attackers.remove(attacker); if (assignCombatDamageToCreature) { Card chosen = attacker.getController().getController().chooseCardsForEffect(getDefendersCreatures(), - null, Localizer.getInstance().getMessage("lblChooseCreature"), 1, 1, false, null).get(0); + emptySA, Localizer.getInstance().getMessage("lblChooseCreature"), 1, 1, false, null).get(0); damageMap.put(attacker, chosen, damageDealt); } else if (trampler || !band.isBlocked()) { // this is called after declare blockers, no worries 'bout nulls in isBlocked damageMap.put(attacker, defender, damageDealt); From 89f4d8ff67add477d99775e6966b5061ac4effd3 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 26 Feb 2023 10:15:05 +0100 Subject: [PATCH 3/4] Fix Zephyrim --- forge-ai/src/main/java/forge/ai/ComputerUtilMana.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java index 1fdd6cc49ed..d4419d083f4 100644 --- a/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java +++ b/forge-ai/src/main/java/forge/ai/ComputerUtilMana.java @@ -1324,9 +1324,9 @@ public class ComputerUtilMana { public static ManaCostBeingPaid calculateManaCost(final SpellAbility sa, final boolean test, final int extraMana) { Card card = sa.getHostCard(); Zone castFromBackup = null; - if (test && sa.isSpell()) { + if (test && sa.isSpell() && !card.isInZone(ZoneType.Stack)) { castFromBackup = card.getCastFrom(); - sa.getHostCard().setCastFrom(card.getZone() != null ? card.getZone() : null); + card.setCastFrom(card.getZone() != null ? card.getZone() : null); } Cost payCosts = CostAdjustment.adjust(sa.getPayCosts(), sa); From 08ae04ab8b0de0778f3b8043fd4b5cb1acaf57cc Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Sun, 26 Feb 2023 10:17:47 +0100 Subject: [PATCH 4/4] Fix Silver Scrutiny --- forge-game/src/main/java/forge/game/ForgeScript.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/forge-game/src/main/java/forge/game/ForgeScript.java b/forge-game/src/main/java/forge/game/ForgeScript.java index 7863f76d321..277476cc742 100644 --- a/forge-game/src/main/java/forge/game/ForgeScript.java +++ b/forge-game/src/main/java/forge/game/ForgeScript.java @@ -188,7 +188,7 @@ public class ForgeScript { } else if (property.startsWith("XCost")) { String comparator = property.substring(5, 7); int y = AbilityUtils.calculateAmount(sa.getHostCard(), property.substring(7), sa); - return Expressions.compare(sa.getXManaCostPaid(), comparator, y); + return Expressions.compare(sa.getXManaCostPaid() == null ? 0 : sa.getXManaCostPaid(), comparator, y); } else if (property.equals("hasTapCost")) { Cost cost = sa.getPayCosts(); return cost != null && cost.hasTapCost();