diff --git a/forge-ai/src/main/java/forge/ai/AiCostDecision.java b/forge-ai/src/main/java/forge/ai/AiCostDecision.java index b147420577f..a677c2ddf90 100644 --- a/forge-ai/src/main/java/forge/ai/AiCostDecision.java +++ b/forge-ai/src/main/java/forge/ai/AiCostDecision.java @@ -267,6 +267,15 @@ public class AiCostDecision extends CostDecisionMakerBase { return PaymentDecision.number(c); } + @Override + public PaymentDecision visit(CostRollDice cost) { + Integer c = cost.convertAmount(); + if (c == null) { + c = AbilityUtils.calculateAmount(source, cost.getAmount(), ability); + } + return PaymentDecision.number(c); + } + @Override public PaymentDecision visit(CostGainControl cost) { if (cost.payCostFromSource()) { 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 80a0021c52f..fae4d70df52 100644 --- a/forge-game/src/main/java/forge/game/cost/Cost.java +++ b/forge-game/src/main/java/forge/game/cost/Cost.java @@ -363,6 +363,13 @@ public class Cost implements Serializable { return new CostFlipCoin(splitStr[0]); } + if (parse.startsWith("RollDice<")) { + // RollDice + final String[] splitStr = abCostParse(parse, 4); + final String description = splitStr.length > 3 ? splitStr[3] : null; + return new CostRollDice(splitStr[0], splitStr[1], splitStr[2], description); + } + if (parse.startsWith("Discard<")) { // Discard final String[] splitStr = abCostParse(parse, 3); diff --git a/forge-game/src/main/java/forge/game/cost/CostRollDice.java b/forge-game/src/main/java/forge/game/cost/CostRollDice.java new file mode 100644 index 00000000000..67355994a34 --- /dev/null +++ b/forge-game/src/main/java/forge/game/cost/CostRollDice.java @@ -0,0 +1,68 @@ +package forge.game.cost; + +import forge.game.ability.effects.RollDiceEffect; +import forge.game.player.Player; +import forge.game.spellability.SpellAbility; + +/** + * This is for the "RollDice" Cost + */ +public class CostRollDice extends CostPart { + + /** + * Serializables need a version ID. + */ + private static final long serialVersionUID = 1L; + + private final String resultSVar; + + /** + * Instantiates a new cost RollDice. + * + * @param amount + * the amount + */ + public CostRollDice(final String amount, final String sides, final String resultSVar, final String description) { + super(amount, sides, description); + this.resultSVar = resultSVar; + } + + /* + * (non-Javadoc) + * + * @see + * forge.card.cost.CostPart#canPay(forge.card.spellability.SpellAbility, + * forge.Card, forge.Player, forge.card.cost.Cost) + */ + @Override + public final boolean canPay(final SpellAbility ability, final Player payer) { + return true; + } + + @Override + public final String toString() { + final StringBuilder sb = new StringBuilder(); + + sb.append("Roll ").append(getAmount()); + + if (this.getTypeDescription() == null) { + sb.append("d").append(getType()); + } else { + sb.append(" ").append(this.getTypeDescription()); + } + + return sb.toString(); + } + + @Override + public boolean payAsDecided(Player payer, PaymentDecision pd, SpellAbility sa) { + int sides = Integer.parseInt(getType()); + int result = RollDiceEffect.rollDiceForPlayer(sa, payer, pd.c, sides); + sa.setSVar(resultSVar, Integer.toString(result)); + return true; + } + + public T accept(ICostVisitor visitor) { + return visitor.visit(this); + } +} diff --git a/forge-game/src/main/java/forge/game/cost/ICostVisitor.java b/forge-game/src/main/java/forge/game/cost/ICostVisitor.java index 1b46b741e7e..89b69c2c2e1 100644 --- a/forge-game/src/main/java/forge/game/cost/ICostVisitor.java +++ b/forge-game/src/main/java/forge/game/cost/ICostVisitor.java @@ -12,6 +12,7 @@ public interface ICostVisitor { T visit(CostExiledMoveToGrave cost); T visit(CostExert cost); T visit(CostFlipCoin cost); + T visit(CostRollDice cost); T visit(CostMill cost); T visit(CostAddMana cost); T visit(CostPayLife cost); @@ -84,6 +85,11 @@ public interface ICostVisitor { return null; } + @Override + public T visit(CostRollDice cost) { + return null; + } + @Override public T visit(CostMill cost) { return null; @@ -173,7 +179,7 @@ public interface ICostVisitor { public T visit(CostUnattach cost) { return null; } - + @Override public T visit(CostTapType cost) { return null; diff --git a/forge-game/src/main/java/forge/util/MessageUtil.java b/forge-game/src/main/java/forge/util/MessageUtil.java index 431054e395f..a73c34179e7 100644 --- a/forge-game/src/main/java/forge/util/MessageUtil.java +++ b/forge-game/src/main/java/forge/util/MessageUtil.java @@ -53,6 +53,7 @@ public class MessageUtil { case Protection: return Localizer.getInstance().getMessage("lblPlayerChooseValue", choser, value); case RollDice: + case PutCounter:// For Clay Golem cost text return value; case Vote: String chooser = StringUtils.capitalize(mayBeYou(player, target)); diff --git a/forge-gui/res/cardsfolder/upcoming/clay_golem.txt b/forge-gui/res/cardsfolder/upcoming/clay_golem.txt new file mode 100644 index 00000000000..d6e35596511 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/clay_golem.txt @@ -0,0 +1,9 @@ +Name:Clay Golem +ManaCost:4 +Types:Artifact Creature Golem +PT:4/4 +A:AB$ PutCounter | Cost$ 6 RollDice<1/8/X> | ConditionPresent$ Card.Self+IsNotMonstrous | Monstrosity$ True | CounterNum$ X | CounterType$ P1P1 | StackDescription$ SpellDescription | SpellDescription$ Monstrosity X, where X is the result. (If this creature isn't monstrous, put X +1/+1 counters on it and it becomes monstrous.) +T:Mode$ BecomeMonstrous | ValidCard$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigDestroy | TriggerDescription$ Berserk — When CARDNAME becomes monstrous, destroy target permanent. +SVar:TrigDestroy:DB$ Destroy | ValidTgts$ Permanent +DeckHas:Ability$Counters +Oracle:{6}, Roll a d8: Monstrosity X, where X is the result. (If this creature isn't monstrous, put X +1/+1 counters on it and it becomes monstrous.)\nBerserk — When Clay Golem becomes monstrous, destroy target permanent. diff --git a/forge-gui/res/languages/de-DE.properties b/forge-gui/res/languages/de-DE.properties index 9fb09465aa6..416513b0180 100644 --- a/forge-gui/res/languages/de-DE.properties +++ b/forge-gui/res/languages/de-DE.properties @@ -1725,6 +1725,7 @@ lblDoYouWantPayNLife=Möchtest du {0} Leben bezahlen? lblDoyouWantTo=Möchtest du lblDoYouWantMillNCardsOrDoAction=Möchtest du {0} Karte(n) von der Bibliothek auf den Friedhof legen? {1} lblDoYouWantFlipNCoinAction=Möchtest du {0} Münze(n) werfen? +lblDoYouWantRollNDiceAction=Do you want to roll {0}{1}? lblDoYouWantRemoveNTargetTypeCounterFromCard=Möchtest du {0} {1}-Marken von {2} entfernen? lblDoYouWantRemoveCountersFromCard=Möchtest du Marken von {0} entfernen? lblDoYouWantExileNCardsFromYourLibrary=Möchtest du {0} Karte(n) von deiner Bibliothek ins Exil schicken? diff --git a/forge-gui/res/languages/en-US.properties b/forge-gui/res/languages/en-US.properties index 545850e5a64..f66bd7b7cd4 100644 --- a/forge-gui/res/languages/en-US.properties +++ b/forge-gui/res/languages/en-US.properties @@ -1725,6 +1725,7 @@ lblDoYouWantPayNLife=Do you want to pay {0} life? lblDoyouWantTo=Do you want to lblDoYouWantMillNCardsOrDoAction=Do you want to mill {0} card(s)? {1} lblDoYouWantFlipNCoinAction=Do you want to flip {0} coin(s)? +lblDoYouWantRollNDiceAction=Do you want to roll {0}{1}? lblDoYouWantRemoveNTargetTypeCounterFromCard=Do you want to remove {0} {1} counter from {2}? lblDoYouWantRemoveCountersFromCard=Do you want to remove counters from {0}? lblDoYouWantExileNCardsFromYourLibrary=Do you want to exile {0} card(s) from your library? diff --git a/forge-gui/res/languages/es-ES.properties b/forge-gui/res/languages/es-ES.properties index 670c71b1f39..fbc8c2ee7bd 100644 --- a/forge-gui/res/languages/es-ES.properties +++ b/forge-gui/res/languages/es-ES.properties @@ -1724,6 +1724,7 @@ lblDoYouWantPayNLife=¿Quieres pagar {0} de vida? lblDoyouWantTo=¿Quieres lblDoYouWantMillNCardsOrDoAction=¿Quieres moler {0} carta(s)? {1} lblDoYouWantFlipNCoinAction=¿Quieres lanzar {0} moneda(s)? +lblDoYouWantRollNDiceAction=Do you want to roll {0}{1}? lblDoYouWantRemoveNTargetTypeCounterFromCard=¿Quieres quitar el contador {0} {1} de {2}? lblDoYouWantRemoveCountersFromCard=¿Quieres quitar los contadores de {0}? lblDoYouWantExileNCardsFromYourLibrary=¿Quieres exiliar {0} carta(s) de tu biblioteca? diff --git a/forge-gui/res/languages/it-IT.properties b/forge-gui/res/languages/it-IT.properties index 8c488fb82f9..705c55d8a55 100644 --- a/forge-gui/res/languages/it-IT.properties +++ b/forge-gui/res/languages/it-IT.properties @@ -1724,6 +1724,7 @@ lblDoYouWantPayNLife=Vuoi pagare {0} punti vita? lblDoyouWantTo=Vuoi lblDoYouWantMillNCardsOrDoAction=Vuoi macinare {0} carta/e? {1} lblDoYouWantFlipNCoinAction=Vuoi lanciare {0} moneta/e? +lblDoYouWantRollNDiceAction=Do you want to roll {0}{1}? lblDoYouWantRemoveNTargetTypeCounterFromCard=Vuoi rimuovere {0} segnalino {1} da {2}? lblDoYouWantRemoveCountersFromCard=Vuoi rimuovere i segnalini da {0}? lblDoYouWantExileNCardsFromYourLibrary=Vuoi esiliare {0} carta/e dal tuo grimorio? diff --git a/forge-gui/res/languages/ja-JP.properties b/forge-gui/res/languages/ja-JP.properties index dd183bd0b6b..5792fd342ac 100644 --- a/forge-gui/res/languages/ja-JP.properties +++ b/forge-gui/res/languages/ja-JP.properties @@ -1724,7 +1724,8 @@ lblDoYouWantPay=プレイしますか? lblDoYouWantPayNLife={0}点のライフを支払いますか? lblDoyouWantTo=この行動をしてもいい? lblDoYouWantMillNCardsOrDoAction={0}枚のカードを切削しますか? {1} -lblDoYouWantFlipNCoinOrDoAction={0}枚のコイントスをしますか? {1} +lblDoYouWantFlipNCoinAction={0}枚のコイントスをしますか? +lblDoYouWantRollNDiceAction={0}{1}を投げますか? lblDoYouWantRemoveNTargetTypeCounterFromCard={2}から {1}個の {0}カウンターを取り除きますか? lblDoYouWantRemoveCountersFromCard={0}からカウンターを取り除きますか? lblDoYouWantExileNCardsFromYourLibrary=ライブラリーから {0}枚のカードを追放しますか? diff --git a/forge-gui/res/languages/zh-CN.properties b/forge-gui/res/languages/zh-CN.properties index 533f8a7552d..1f0cc199f83 100644 --- a/forge-gui/res/languages/zh-CN.properties +++ b/forge-gui/res/languages/zh-CN.properties @@ -1725,6 +1725,7 @@ lblDoYouWantPayNLife=你想要支付{0}点生命吗? lblDoyouWantTo=你想要 lblDoYouWantMillNCardsOrDoAction=你想要磨{0}张牌吗? {1} lblDoYouWantFlipNCoinAction=你想要抛{0}个硬币吗? +lblDoYouWantRollNDiceAction=Do you want to roll {0}{1}? lblDoYouWantRemoveNTargetTypeCounterFromCard=你想要从{2}移除{0}个{1}指示物吗? lblDoYouWantRemoveCountersFromCard=你想要从{0}删除指示物吗? lblDoYouWantExileNCardsFromYourLibrary=你想要从你的牌库放逐{0}张牌吗? diff --git a/forge-gui/src/main/java/forge/player/HumanCostDecision.java b/forge-gui/src/main/java/forge/player/HumanCostDecision.java index 6e3920266d5..63fac618df4 100644 --- a/forge-gui/src/main/java/forge/player/HumanCostDecision.java +++ b/forge-gui/src/main/java/forge/player/HumanCostDecision.java @@ -482,6 +482,22 @@ public class HumanCostDecision extends CostDecisionMakerBase { return PaymentDecision.number(c); } + @Override + public PaymentDecision visit(final CostRollDice cost) { + final String amount = cost.getAmount(); + Integer c = cost.convertAmount(); + + if (c == null) { + c = AbilityUtils.calculateAmount(source, amount, ability); + } + + if (!player.getController().confirmPayment(cost, Localizer.getInstance().getMessage("lblDoYouWantRollNDiceAction", String.valueOf(c), "d" + cost.getType()), ability)) { + return null; + } + + return PaymentDecision.number(c); + } + @Override public PaymentDecision visit(final CostGainControl cost) { final String amount = cost.getAmount(); diff --git a/forge-gui/src/main/java/forge/player/HumanPlay.java b/forge-gui/src/main/java/forge/player/HumanPlay.java index f7e120b8e51..a410e3e3006 100644 --- a/forge-gui/src/main/java/forge/player/HumanPlay.java +++ b/forge-gui/src/main/java/forge/player/HumanPlay.java @@ -349,6 +349,18 @@ public class HumanPlay { else part.payAsDecided(p, pd, sourceAbility); } + else if (part instanceof CostRollDice) { + if (!part.canPay(sourceAbility, p)) { + return false; + } + + PaymentDecision pd = part.accept(hcd); + + if (pd == null) + return false; + else + part.payAsDecided(p, pd, sourceAbility); + } else if (part instanceof CostDamage) { if (!part.canPay(sourceAbility, p)) { return false;