From 65fc79a746b528927b78a5349e8e7180402d6686 Mon Sep 17 00:00:00 2001 From: tool4EvEr Date: Tue, 2 Mar 2021 19:33:40 +0100 Subject: [PATCH] Force player choice for mandatory costs --- forge-game/src/main/java/forge/game/cost/Cost.java | 1 + .../res/cardsfolder/m/minion_of_the_wastes.txt | 2 +- forge-gui/res/cardsfolder/n/nameless_race.txt | 2 +- forge-gui/res/cardsfolder/p/phyrexian_processor.txt | 2 +- .../main/java/forge/player/HumanCostDecision.java | 3 ++- .../java/forge/player/PlayerControllerHuman.java | 13 ++++++++++--- 6 files changed, 16 insertions(+), 7 deletions(-) diff --git a/forge-game/src/main/java/forge/game/cost/Cost.java b/forge-game/src/main/java/forge/game/cost/Cost.java index 986e6d791e3..1b05fa48913 100644 --- a/forge-game/src/main/java/forge/game/cost/Cost.java +++ b/forge-game/src/main/java/forge/game/cost/Cost.java @@ -515,6 +515,7 @@ public class Cost implements Serializable { public final Cost copy() { Cost toRet = new Cost(); toRet.isAbility = this.isAbility; + toRet.isMandatory = this.isMandatory; for (CostPart cp : this.costParts) { toRet.costParts.add(cp.copy()); } diff --git a/forge-gui/res/cardsfolder/m/minion_of_the_wastes.txt b/forge-gui/res/cardsfolder/m/minion_of_the_wastes.txt index 17367608230..024251e1a28 100644 --- a/forge-gui/res/cardsfolder/m/minion_of_the_wastes.txt +++ b/forge-gui/res/cardsfolder/m/minion_of_the_wastes.txt @@ -4,7 +4,7 @@ Types:Creature Minion PT:*/* K:Trample R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ PayLife | Description$ As CARDNAME enters the battlefield, pay any amount of life. -SVar:PayLife:AB$ StoreSVar | Cost$ PayLife | References$ X | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay +SVar:PayLife:AB$ StoreSVar | Cost$ Mandatory PayLife | References$ X | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay SVar:MoveToPlay:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ All | Destination$ Battlefield S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ LifePaidOnETB | SetToughness$ LifePaidOnETB | Description$ CARDNAME's power and toughness are each equal to the life paid as it entered the battlefield. SVar:X:Count$xPaid diff --git a/forge-gui/res/cardsfolder/n/nameless_race.txt b/forge-gui/res/cardsfolder/n/nameless_race.txt index 3b40c7f8628..61d7483f0b2 100644 --- a/forge-gui/res/cardsfolder/n/nameless_race.txt +++ b/forge-gui/res/cardsfolder/n/nameless_race.txt @@ -4,7 +4,7 @@ Types:Creature PT:*/* K:Trample R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ PayLife | Description$ As CARDNAME enters the battlefield, pay any amount of life. The amount you pay can't be more than the total number of white nontoken permanents your opponents control plus the total number of white cards in their graveyards. -SVar:PayLife:AB$ StoreSVar | Cost$ PayLife | XMaxLimit$ Limit | References$ X,Limit,Active,Buried | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay +SVar:PayLife:AB$ StoreSVar | Cost$ Mandatory PayLife | XMaxLimit$ Limit | References$ X,Limit,Active,Buried | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay SVar:MoveToPlay:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ All | Destination$ Battlefield #Dont use References, when the variable is set by StoreSVar S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ LifePaidOnETB | SetToughness$ LifePaidOnETB | Description$ CARDNAME's power and toughness are each equal to the life paid as it entered the battlefield. diff --git a/forge-gui/res/cardsfolder/p/phyrexian_processor.txt b/forge-gui/res/cardsfolder/p/phyrexian_processor.txt index 3d197468e7d..899947c154f 100644 --- a/forge-gui/res/cardsfolder/p/phyrexian_processor.txt +++ b/forge-gui/res/cardsfolder/p/phyrexian_processor.txt @@ -2,7 +2,7 @@ Name:Phyrexian Processor ManaCost:4 Types:Artifact R:Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | ReplaceWith$ PayLife | Description$ As CARDNAME enters the battlefield, pay any amount of life. -SVar:PayLife:AB$ StoreSVar | Cost$ PayLife | References$ X | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay +SVar:PayLife:AB$ StoreSVar | Cost$ Mandatory PayLife | References$ X | SVar$ LifePaidOnETB | Type$ Calculate | Expression$ X | SubAbility$ MoveToPlay SVar:MoveToPlay:DB$ ChangeZone | Defined$ ReplacedCard | Origin$ All | Destination$ Battlefield A:AB$ Token | Cost$ 4 T | TokenAmount$ 1 | TokenScript$ b_x_x_minion | TokenOwner$ You | TokenPower$ LifePaidOnETB | TokenToughness$ LifePaidOnETB | LegacyImage$ b x x minion usg | SpellDescription$ Create an X/X black Minion creature token, where X is the life paid as CARDNAME entered the battlefield. SVar:X:Count$xPaid diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index ab78a6733f4..f536459e504 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -555,7 +555,8 @@ public class HumanCostDecision extends CostDecisionMakerBase { c = AbilityUtils.calculateAmount(source, amount, ability); } - if (player.canPayLife(c) && player.getController().confirmPayment(cost, Localizer.getInstance().getMessage("lblPayNLifeConfirm", String.valueOf(c)),ability)) { + // for costs declared mandatory, this is only reachable with a valid amount + if (ability.getPayCosts().isMandatory() || (player.canPayLife(c) && player.getController().confirmPayment(cost, Localizer.getInstance().getMessage("lblPayNLifeConfirm", String.valueOf(c)),ability))) { return PaymentDecision.number(c); } return null; diff --git a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java index af5eb165785..e8444f0bacb 100644 --- a/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java +++ b/forge-gui/src/main/java/forge/player/PlayerControllerHuman.java @@ -327,10 +327,10 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont public Integer announceRequirements(final SpellAbility ability, final String announce) { int max = Integer.MAX_VALUE; boolean canChooseZero = true; + Cost cost = ability.getPayCosts(); if ("X".equals(announce)) { canChooseZero = !ability.hasParam("XCantBe0"); - Cost cost = ability.getPayCosts(); if (ability.hasParam("XMaxLimit")) { max = Math.min(max, AbilityUtils.calculateAmount(ability.getHostCard(), ability.getParam("XMaxLimit"), ability)); } @@ -355,8 +355,15 @@ public class PlayerControllerHuman extends PlayerController implements IGameCont if (min > max) { return null; } - return getGui().getInteger(localizer.getMessage("lblChooseAnnounceForCard", announce, - CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max, min + 9); + + if (cost.isMandatory()) { + return chooseNumber(ability, localizer.getMessage("lblChooseAnnounceForCard", announce, + CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max); + } + else { + return getGui().getInteger(localizer.getMessage("lblChooseAnnounceForCard", announce, + CardTranslation.getTranslatedName(ability.getHostCard().getName())) , min, max, min + 9); + } } @Override