diff --git a/forge-game/src/main/java/forge/game/ability/AbilityKey.java b/forge-game/src/main/java/forge/game/ability/AbilityKey.java index 588e5f37712..b09d9f6dd02 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityKey.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityKey.java @@ -84,6 +84,7 @@ public enum AbilityKey { Mana("Mana"), MergedCards("MergedCards"), Mode("Mode"), + Modifier("Modifier"), MonstrosityAmount("MonstrosityAmount"), NewCard("NewCard"), NewCounterAmount("NewCounterAmount"), diff --git a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java index 3a349fdd6ff..dc18f35e4a4 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RollDiceEffect.java @@ -8,6 +8,8 @@ import java.util.Map; import forge.game.event.GameEventRollDie; import org.apache.commons.lang3.StringUtils; +import com.google.common.collect.Lists; + import forge.game.ability.AbilityKey; import forge.game.ability.AbilityUtils; import forge.game.ability.SpellAbilityEffect; @@ -66,45 +68,51 @@ public class RollDiceEffect extends SpellAbilityEffect { } public static int rollDiceForPlayer(SpellAbility sa, Player player, int amount, int sides) { - return rollDiceForPlayer(sa, player, amount, sides, 0, null); + return rollDiceForPlayer(sa, player, amount, sides, 0, 0, null); } - - private static int rollDiceForPlayer(SpellAbility sa, Player player, int amount, int sides, int ignore, List rollsResult) { + private static int rollDiceForPlayer(SpellAbility sa, Player player, int amount, int sides, int ignore, int modifier, List rollsResult) { int advantage = getRollAdvange(player); amount += advantage; int total = 0; - List rolls = (rollsResult == null ? new ArrayList<>() : rollsResult); + List naturalRolls = (rollsResult == null ? new ArrayList<>() : rollsResult); for (int i = 0; i < amount; i++) { int roll = MyRandom.getRandom().nextInt(sides) + 1; // Play the die roll sound player.getGame().fireEvent(new GameEventRollDie()); player.roll(); - rolls.add(roll); + naturalRolls.add(roll); total += roll; } if (amount > 0) { - String message = Localizer.getInstance().getMessage("lblPlayerRolledResult", player, StringUtils.join(rolls, ", ")); + String message = Localizer.getInstance().getMessage("lblPlayerRolledResult", player, StringUtils.join(naturalRolls, ", ")); player.getGame().getAction().notifyOfValue(sa, player, message, null); } - rolls.sort(null); + naturalRolls.sort(null); // Ignore lowest rolls advantage += ignore; if (advantage > 0) { for (int i = advantage - 1; i >= 0; --i) { - total -= rolls.get(i); - rolls.remove(i); + total -= naturalRolls.get(i); + naturalRolls.remove(i); } } + List rolls = Lists.newArrayList(); + for (Integer i : naturalRolls) { + rolls.add(i + modifier); + } + total += modifier; + // Run triggers for (Integer roll : rolls) { final Map runParams = AbilityKey.newMap(); runParams.put(AbilityKey.Player, player); runParams.put(AbilityKey.Sides, sides); + runParams.put(AbilityKey.Modifier, modifier); runParams.put(AbilityKey.Result, roll); player.getGame().getTriggerHandler().runTrigger(TriggerType.RolledDie, runParams, false); } @@ -123,9 +131,8 @@ public class RollDiceEffect extends SpellAbilityEffect { final int ignore = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("IgnoreLower", "0"), sa); List rolls = new ArrayList<>(); - int total = rollDiceForPlayer(sa, player, amount, sides, ignore, rolls); + int total = rollDiceForPlayer(sa, player, amount, sides, ignore, modifier, rolls); - total += modifier; if (sa.hasParam("ResultSVar")) { sa.setSVar(sa.getParam("ResultSVar"), Integer.toString(total)); } diff --git a/forge-game/src/main/java/forge/game/trigger/TriggerRolledDie.java b/forge-game/src/main/java/forge/game/trigger/TriggerRolledDie.java index 2440dd83b9c..74e955196fd 100644 --- a/forge-game/src/main/java/forge/game/trigger/TriggerRolledDie.java +++ b/forge-game/src/main/java/forge/game/trigger/TriggerRolledDie.java @@ -26,7 +26,10 @@ public class TriggerRolledDie extends Trigger { } if (hasParam("ValidResult")) { String[] params = getParam("ValidResult").split(","); - final int result = (int) runParams.get(AbilityKey.Result); + int result = (int) runParams.get(AbilityKey.Result); + if (hasParam("Natural")) { + result -= (int) runParams.get(AbilityKey.Modifier); + } for (String param : params) { if (StringUtils.isNumeric(param)) { if (param.equals("" + result)) return true; diff --git a/forge-gui/res/cardsfolder/c/critical_hit.txt b/forge-gui/res/cardsfolder/c/critical_hit.txt index a927a02cee4..09a33480a3b 100644 --- a/forge-gui/res/cardsfolder/c/critical_hit.txt +++ b/forge-gui/res/cardsfolder/c/critical_hit.txt @@ -2,6 +2,6 @@ Name:Critical Hit ManaCost:1 R Types:Instant A:SP$ Pump | KW$ Double Strike | ValidTgts$ Creature -T:Mode$ RolledDie | TriggerZones$ Graveyard | ValidResult$ 20 | ValidPlayer$ You | Execute$ TrigReturn | TriggerDescription$ When you roll a natural 20, return CARDNAME from your graveyard to your hand. (A natural 20 is a roll that displays 20 on the die.) +T:Mode$ RolledDie | TriggerZones$ Graveyard | Natural$ True | ValidResult$ 20 | ValidPlayer$ You | Execute$ TrigReturn | TriggerDescription$ When you roll a natural 20, return CARDNAME from your graveyard to your hand. (A natural 20 is a roll that displays 20 on the die.) SVar:TrigReturn:DB$ ChangeZone | Defined$ Self | Origin$ Graveyard | Destination$ Hand Oracle:Target creature gains double strike until end of turn.\nWhen you roll a natural 20, return Critical Hit from your graveyard to your hand. (A natural 20 is a roll that displays 20 on the die.) diff --git a/forge-gui/res/cardsfolder/n/netherese_puzzle_ward.txt b/forge-gui/res/cardsfolder/n/netherese_puzzle_ward.txt index d41e9723905..412f4638b8a 100644 --- a/forge-gui/res/cardsfolder/n/netherese_puzzle_ward.txt +++ b/forge-gui/res/cardsfolder/n/netherese_puzzle_ward.txt @@ -5,6 +5,6 @@ T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | E SVar:TrigRollDice:DB$ RollDice | Sides$ 4 | ResultSVar$ X | SubAbility$ DBScry SVar:DBScry:DB$ Scry | ScryNum$ X SVar:X:Number$0 -T:Mode$ RolledDie | TriggerZones$ Battlefield | ValidResult$ Highest | ValidPlayer$ You | Execute$ TrigDraw | TriggerDescription$ Perfect Illumination — Whenever you roll a die's highest natural result, draw a card. +T:Mode$ RolledDie | TriggerZones$ Battlefield | Natural$ True | ValidResult$ Highest | ValidPlayer$ You | Execute$ TrigDraw | TriggerDescription$ Perfect Illumination — Whenever you roll a die's highest natural result, draw a card. SVar:TrigDraw:DB$ Draw | NumCards$ 1 Oracle:Focus Beam — At the beginning of your upkeep, roll a d4. Scry X, where X is the result.\nPerfect Illumination — Whenever you roll a die's highest natural result, draw a card.