RolledDie: support (un)natural results

This commit is contained in:
TRT
2022-07-20 14:49:26 +02:00
parent 728b2e4e0e
commit 8b51190f7e
5 changed files with 25 additions and 14 deletions

View File

@@ -84,6 +84,7 @@ public enum AbilityKey {
Mana("Mana"), Mana("Mana"),
MergedCards("MergedCards"), MergedCards("MergedCards"),
Mode("Mode"), Mode("Mode"),
Modifier("Modifier"),
MonstrosityAmount("MonstrosityAmount"), MonstrosityAmount("MonstrosityAmount"),
NewCard("NewCard"), NewCard("NewCard"),
NewCounterAmount("NewCounterAmount"), NewCounterAmount("NewCounterAmount"),

View File

@@ -8,6 +8,8 @@ import java.util.Map;
import forge.game.event.GameEventRollDie; import forge.game.event.GameEventRollDie;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import com.google.common.collect.Lists;
import forge.game.ability.AbilityKey; import forge.game.ability.AbilityKey;
import forge.game.ability.AbilityUtils; import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect; 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) { 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, int modifier, List<Integer> rollsResult) {
private static int rollDiceForPlayer(SpellAbility sa, Player player, int amount, int sides, int ignore, List<Integer> rollsResult) {
int advantage = getRollAdvange(player); int advantage = getRollAdvange(player);
amount += advantage; amount += advantage;
int total = 0; int total = 0;
List<Integer> rolls = (rollsResult == null ? new ArrayList<>() : rollsResult); List<Integer> naturalRolls = (rollsResult == null ? new ArrayList<>() : rollsResult);
for (int i = 0; i < amount; i++) { for (int i = 0; i < amount; i++) {
int roll = MyRandom.getRandom().nextInt(sides) + 1; int roll = MyRandom.getRandom().nextInt(sides) + 1;
// Play the die roll sound // Play the die roll sound
player.getGame().fireEvent(new GameEventRollDie()); player.getGame().fireEvent(new GameEventRollDie());
player.roll(); player.roll();
rolls.add(roll); naturalRolls.add(roll);
total += roll; total += roll;
} }
if (amount > 0) { 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); player.getGame().getAction().notifyOfValue(sa, player, message, null);
} }
rolls.sort(null); naturalRolls.sort(null);
// Ignore lowest rolls // Ignore lowest rolls
advantage += ignore; advantage += ignore;
if (advantage > 0) { if (advantage > 0) {
for (int i = advantage - 1; i >= 0; --i) { for (int i = advantage - 1; i >= 0; --i) {
total -= rolls.get(i); total -= naturalRolls.get(i);
rolls.remove(i); naturalRolls.remove(i);
} }
} }
List<Integer> rolls = Lists.newArrayList();
for (Integer i : naturalRolls) {
rolls.add(i + modifier);
}
total += modifier;
// Run triggers // Run triggers
for (Integer roll : rolls) { for (Integer roll : rolls) {
final Map<AbilityKey, Object> runParams = AbilityKey.newMap(); final Map<AbilityKey, Object> runParams = AbilityKey.newMap();
runParams.put(AbilityKey.Player, player); runParams.put(AbilityKey.Player, player);
runParams.put(AbilityKey.Sides, sides); runParams.put(AbilityKey.Sides, sides);
runParams.put(AbilityKey.Modifier, modifier);
runParams.put(AbilityKey.Result, roll); runParams.put(AbilityKey.Result, roll);
player.getGame().getTriggerHandler().runTrigger(TriggerType.RolledDie, runParams, false); 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); final int ignore = AbilityUtils.calculateAmount(host, sa.getParamOrDefault("IgnoreLower", "0"), sa);
List<Integer> rolls = new ArrayList<>(); List<Integer> 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")) { if (sa.hasParam("ResultSVar")) {
sa.setSVar(sa.getParam("ResultSVar"), Integer.toString(total)); sa.setSVar(sa.getParam("ResultSVar"), Integer.toString(total));
} }

View File

@@ -26,7 +26,10 @@ public class TriggerRolledDie extends Trigger {
} }
if (hasParam("ValidResult")) { if (hasParam("ValidResult")) {
String[] params = getParam("ValidResult").split(","); 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) { for (String param : params) {
if (StringUtils.isNumeric(param)) { if (StringUtils.isNumeric(param)) {
if (param.equals("" + result)) return true; if (param.equals("" + result)) return true;

View File

@@ -2,6 +2,6 @@ Name:Critical Hit
ManaCost:1 R ManaCost:1 R
Types:Instant Types:Instant
A:SP$ Pump | KW$ Double Strike | ValidTgts$ Creature 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 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.) 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.)

View File

@@ -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:TrigRollDice:DB$ RollDice | Sides$ 4 | ResultSVar$ X | SubAbility$ DBScry
SVar:DBScry:DB$ Scry | ScryNum$ X SVar:DBScry:DB$ Scry | ScryNum$ X
SVar:X:Number$0 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 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. 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.