[AFC] Fix OneOrMoreDiceRolledTriggeredAbility to not trigger from Chaos Dragon (#9201)

This commit is contained in:
Alex Vasile 2022-07-08 21:40:05 -04:00 committed by GitHub
parent 545b7c143d
commit 69f9331d87
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 97 additions and 10 deletions

View file

@ -0,0 +1,46 @@
package org.mage.test.cards.single.afr;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestMultiPlayerBase;
/**
* {@link VrondissRageOfAncientsTest Vrondriss, Rage of Ancients}
* Enrage Whenever Vrondiss, Rage of Ancients is dealt damage,
* you may create a 5/4 red and green Dragon Spirit creature token with
* When this creature deals damage, sacrifice it.
* Whenever you roll one or more dice, you may have Vrondiss deal 1 damage to itself.
*/
public class VrondissRageOfAncientsTest extends CardTestMultiPlayerBase {
/**
* Reported bug: https://github.com/magefree/mage/issues/8189
*
* Chaos Dragon attacking would cause Vrondiss to trigger off of every player's roll, not just Vrondiss' controller.
*
* {@link mage.cards.c.ChaosDragon Chaos Dragon}
* At the beginning of combat on your turn, each player rolls a d20.
* If one or more opponents had the highest result,
* Chaos Dragon cant attack those players or planeswalkers they control this combat.
*/
@Test
public void testChaosDragonInteraction() {
addCard(Zone.BATTLEFIELD, playerA, "Vrondiss, Rage of Ancients");
addCard(Zone.BATTLEFIELD, playerA, "Chaos Dragon");
setStrictChooseMode(true);
attack(1, playerA, "Chaos Dragon", playerB);
setDieRollResult(playerA, 10);
setDieRollResult(playerB, 11);
// setDieRollResult(playerC, 12); NOTE: Range of influence of 1, so playerC does not have to roll
setDieRollResult(playerD, 13);
// Set choice for Vrondiss triggered ability
setChoice(playerA, "No");
// Should only be one trigger since it should only trigger off of playerA's roll
execute();
assertAllCommandsUsed();
}
}

View file

@ -8,6 +8,8 @@ import mage.game.events.DiceRolledEvent;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
/** /**
* Controller rolls one or more dice.
*
* @author weirddan455 * @author weirddan455
*/ */
public class OneOrMoreDiceRolledTriggeredAbility extends TriggeredAbilityImpl { public class OneOrMoreDiceRolledTriggeredAbility extends TriggeredAbilityImpl {
@ -36,7 +38,7 @@ public class OneOrMoreDiceRolledTriggeredAbility extends TriggeredAbilityImpl {
@Override @Override
public boolean checkTrigger(GameEvent event, Game game) { public boolean checkTrigger(GameEvent event, Game game) {
if (!isControlledBy(event.getPlayerId())) { if (!isControlledBy(event.getTargetId())) {
return false; return false;
} }
int maxRoll = ((DiceRolledEvent) event) int maxRoll = ((DiceRolledEvent) event)

View file

@ -4,6 +4,7 @@ import mage.abilities.Ability;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
@ -13,8 +14,19 @@ public class DiceRolledEvent extends GameEvent {
private final int sides; private final int sides;
private final List<Object> results = new ArrayList<>(); // Integer for numerical and PlanarDieRollResult for planar private final List<Object> results = new ArrayList<>(); // Integer for numerical and PlanarDieRollResult for planar
public DiceRolledEvent(int sides, List<Object> results, Ability source) { /**
super(EventType.DICE_ROLLED, source.getControllerId(), source, source.getControllerId()); * The target ID is used to keep track of the distinction between the player who controls the ability that
* started the dice roll and the player who does the rolling.
* <p>
* The only times this distinction matters is for Chaos Dragon and Ricochet.
*
* @param sides
* @param results
* @param source
* @param targetId The player who rolled the die
*/
public DiceRolledEvent(int sides, List<Object> results, Ability source, UUID targetId) {
super(EventType.DICE_ROLLED, targetId, source, source.getControllerId());
this.sides = sides; this.sides = sides;
this.results.addAll(results); this.results.addAll(results);
} }

View file

@ -4,6 +4,8 @@ import mage.abilities.Ability;
import mage.constants.RollDieType; import mage.constants.RollDieType;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -13,8 +15,20 @@ public class RollDiceEvent extends GameEvent {
private int ignoreLowestAmount = 0; // ignore the lowest results private int ignoreLowestAmount = 0; // ignore the lowest results
private final RollDieType rollDieType; private final RollDieType rollDieType;
public RollDiceEvent(Ability source, RollDieType rollDieType, int sides, int rollsAmount) { /**
super(EventType.ROLL_DICE, source.getControllerId(), source, source.getControllerId(), rollsAmount, false); * The target ID is used to keep track of the distinction between the player who controls the ability that
* started the dice roll and the player who does the rolling.
* <p>
* The only times this distinction matters is for Chaos Dragon and Ricochet.
*
* @param source
* @param targetId The player who is rolling the die
* @param rollDieType
* @param sides
* @param rollsAmount
*/
public RollDiceEvent(Ability source, UUID targetId, RollDieType rollDieType, int sides, int rollsAmount) {
super(EventType.ROLL_DICE, targetId, source, source.getControllerId(), rollsAmount, false);
this.sides = sides; this.sides = sides;
this.rollDieType = rollDieType; this.rollDieType = rollDieType;
} }

View file

@ -4,6 +4,8 @@ import mage.abilities.Ability;
import mage.constants.RollDieType; import mage.constants.RollDieType;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.UUID;
/** /**
* @author TheElk801 * @author TheElk801
*/ */
@ -16,8 +18,19 @@ public class RollDieEvent extends GameEvent {
private int rollsAmount = 1; // rolls X times and choose result from it private int rollsAmount = 1; // rolls X times and choose result from it
private int bigIdeaRollsAmount = 0; // rolls 2x and sum result private int bigIdeaRollsAmount = 0; // rolls 2x and sum result
public RollDieEvent(Ability source, RollDieType rollDieType, int sides) { /**
super(EventType.ROLL_DIE, source.getControllerId(), source, source.getControllerId()); * The target ID is used to keep track of the distinction between the player who controls the ability that
* started the dice roll and the player who does the rolling.
* <p>
* The only times this distinction matters is for Chaos Dragon and Ricochet.
*
* @param source
* @param targetId The player rolling the die
* @param rollDieType
* @param sides
*/
public RollDieEvent(Ability source, UUID targetId, RollDieType rollDieType, int sides) {
super(EventType.ROLL_DIE, targetId, source, source.getControllerId());
this.rollDieType = rollDieType; this.rollDieType = rollDieType;
this.sides = sides; this.sides = sides;
} }

View file

@ -3062,7 +3062,7 @@ public abstract class PlayerImpl implements Player, Serializable {
private List<Object> rollDiceInner(Outcome outcome, Ability source, Game game, RollDieType rollDieType, private List<Object> rollDiceInner(Outcome outcome, Ability source, Game game, RollDieType rollDieType,
int sidesAmount, int chaosSidesAmount, int planarSidesAmount, int sidesAmount, int chaosSidesAmount, int planarSidesAmount,
int rollsAmount, int ignoreLowestAmount) { int rollsAmount, int ignoreLowestAmount) {
RollDiceEvent rollDiceEvent = new RollDiceEvent(source, rollDieType, sidesAmount, rollsAmount); RollDiceEvent rollDiceEvent = new RollDiceEvent(source, this.getId(), rollDieType, sidesAmount, rollsAmount);
if (ignoreLowestAmount > 0) { if (ignoreLowestAmount > 0) {
rollDiceEvent.incIgnoreLowestAmount(ignoreLowestAmount); rollDiceEvent.incIgnoreLowestAmount(ignoreLowestAmount);
} }
@ -3079,7 +3079,7 @@ public abstract class PlayerImpl implements Player, Serializable {
List<RollDieResult> dieRolls = new ArrayList<>(); List<RollDieResult> dieRolls = new ArrayList<>();
for (int i = 0; i < rollDiceEvent.getAmount(); i++) { for (int i = 0; i < rollDiceEvent.getAmount(); i++) {
// ROLL SINGLE die // ROLL SINGLE die
RollDieEvent rollDieEvent = new RollDieEvent(source, rollDiceEvent.getRollDieType(), rollDiceEvent.getSides()); RollDieEvent rollDieEvent = new RollDieEvent(source, this.getId(), rollDiceEvent.getRollDieType(), rollDiceEvent.getSides());
game.replaceEvent(rollDieEvent); game.replaceEvent(rollDieEvent);
Object rollResult; Object rollResult;
@ -3186,7 +3186,7 @@ public abstract class PlayerImpl implements Player, Serializable {
for (RollDieResult result : dieRolls) { for (RollDieResult result : dieRolls) {
game.fireEvent(new DieRolledEvent(source, rollDiceEvent.getRollDieType(), rollDiceEvent.getSides(), result.naturalResult, result.modifier, result.planarResult)); game.fireEvent(new DieRolledEvent(source, rollDiceEvent.getRollDieType(), rollDiceEvent.getSides(), result.naturalResult, result.modifier, result.planarResult));
} }
game.fireEvent(new DiceRolledEvent(rollDiceEvent.getSides(), dieResults, source)); game.fireEvent(new DiceRolledEvent(rollDiceEvent.getSides(), dieResults, source, this.getId()));
String resultString = dieResults String resultString = dieResults
.stream() .stream()