* Fixed a problem with replacement effects that add counters were applied more than once to the same EnteresTheBattlefield event (fixes #2872).

This commit is contained in:
LevelX2 2017-04-01 17:43:17 +02:00
parent 94f77675ec
commit d0bf77cedf
25 changed files with 302 additions and 104 deletions

View file

@ -27,6 +27,8 @@
*/ */
package mage.cards.a; package mage.cards.a;
import java.util.ArrayList;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.AsEntersBattlefieldAbility; import mage.abilities.common.AsEntersBattlefieldAbility;
@ -45,8 +47,6 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import java.util.UUID;
/** /**
* *
* @author jeffwadsworth * @author jeffwadsworth
@ -54,7 +54,7 @@ import java.util.UUID;
public class ArsenalThresher extends CardImpl { public class ArsenalThresher extends CardImpl {
public ArsenalThresher(UUID ownerId, CardSetInfo setInfo) { public ArsenalThresher(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ARTIFACT,CardType.CREATURE},"{2}{W/B}{U}"); super(ownerId, setInfo, new CardType[]{CardType.ARTIFACT, CardType.CREATURE}, "{2}{W/B}{U}");
this.subtype.add("Construct"); this.subtype.add("Construct");
this.power = new MageInt(2); this.power = new MageInt(2);
@ -109,7 +109,8 @@ class ArsenalThresherEffect extends OneShotEffect {
} }
if (arsenalThresher != null) { if (arsenalThresher != null) {
controller.revealCards(arsenalThresher.getIdName(), cards, game); controller.revealCards(arsenalThresher.getIdName(), cards, game);
arsenalThresher.addCounters(CounterType.P1P1.createInstance(cards.size()), source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
arsenalThresher.addCounters(CounterType.P1P1.createInstance(cards.size()), source, game, appliedEffects);
} }
} }
} }

View file

@ -27,6 +27,7 @@
*/ */
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -47,8 +48,6 @@ import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent; import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
* *
* @author emerald000 * @author emerald000
@ -62,7 +61,7 @@ public class BramblewoodParagon extends CardImpl {
} }
public BramblewoodParagon(UUID ownerId, CardSetInfo setInfo) { public BramblewoodParagon(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{G}");
this.subtype.add("Elf"); this.subtype.add("Elf");
this.subtype.add("Warrior"); this.subtype.add("Warrior");
this.power = new MageInt(2); this.power = new MageInt(2);
@ -120,7 +119,7 @@ class BramblewoodParagonReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) { if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source, game); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
return false; return false;
} }

View file

@ -27,6 +27,9 @@
*/ */
package mage.cards.c; package mage.cards.c;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -45,10 +48,6 @@ import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
/** /**
* *
* @author jeffwadsworth * @author jeffwadsworth
@ -57,7 +56,7 @@ import java.util.UUID;
public class ChorusOfTheConclave extends CardImpl { public class ChorusOfTheConclave extends CardImpl {
public ChorusOfTheConclave(UUID ownerId, CardSetInfo setInfo) { public ChorusOfTheConclave(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{G}{G}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{G}{G}{W}{W}");
addSuperType(SuperType.LEGENDARY); addSuperType(SuperType.LEGENDARY);
this.subtype.add("Dryad"); this.subtype.add("Dryad");
@ -198,7 +197,7 @@ class ChorusOfTheConclaveReplacementEffect2 extends ReplacementEffectImpl {
String key = event.getSourceId().toString() + (game.getState().getZoneChangeCounter(event.getSourceId()) - 1); String key = event.getSourceId().toString() + (game.getState().getZoneChangeCounter(event.getSourceId()) - 1);
int xValue = spellX.get(key); int xValue = spellX.get(key);
if (xValue > 0) { if (xValue > 0) {
creature.addCounters(CounterType.P1P1.createInstance(xValue), source, game); creature.addCounters(CounterType.P1P1.createInstance(xValue), source, game, event.getAppliedEffects());
game.informPlayers(sourceObject.getLogName() + ": " + creature.getLogName() + " enters the battlefield with " + xValue + " +1/+1 counter" + (xValue > 1 ? "s" : "") + " on it"); game.informPlayers(sourceObject.getLogName() + ": " + creature.getLogName() + " enters the battlefield with " + xValue + " +1/+1 counter" + (xValue > 1 ? "s" : "") + " on it");
} }
spellX.remove(key); spellX.remove(key);

View file

@ -27,6 +27,7 @@
*/ */
package mage.cards.d; package mage.cards.d;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
@ -45,15 +46,13 @@ import mage.game.events.GameEvent;
import mage.game.events.GameEvent.EventType; import mage.game.events.GameEvent.EventType;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import java.util.UUID;
/** /**
* @author nantuko * @author nantuko
*/ */
public class DearlyDeparted extends CardImpl { public class DearlyDeparted extends CardImpl {
public DearlyDeparted(UUID ownerId, CardSetInfo setInfo) { public DearlyDeparted(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{4}{W}{W}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{4}{W}{W}");
this.subtype.add("Spirit"); this.subtype.add("Spirit");
this.power = new MageInt(5); this.power = new MageInt(5);
@ -104,7 +103,7 @@ class DearlyDepartedEntersBattlefieldEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent target = ((EntersTheBattlefieldEvent) event).getTarget();
if (target != null) { if (target != null) {
target.addCounters(CounterType.P1P1.createInstance(), source, game); target.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
return false; return false;
} }

View file

@ -58,7 +58,7 @@ import mage.target.common.TargetCreaturePermanent;
public class LongRoadHome extends CardImpl { public class LongRoadHome extends CardImpl {
public LongRoadHome(UUID ownerId, CardSetInfo setInfo) { public LongRoadHome(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
// Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it. // Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it.
this.getSpellAbility().addEffect(new LongRoadHomeEffect()); this.getSpellAbility().addEffect(new LongRoadHomeEffect());
@ -163,7 +163,7 @@ class LongRoadHomeEntersBattlefieldEffect extends ReplacementEffectImpl {
public LongRoadHomeEntersBattlefieldEffect(MageObjectReference objectToReturn) { public LongRoadHomeEntersBattlefieldEffect(MageObjectReference objectToReturn) {
super(Duration.Custom, Outcome.BoostCreature); super(Duration.Custom, Outcome.BoostCreature);
this.objectToReturn = objectToReturn; this.objectToReturn = objectToReturn;
staticText = "that card returns to the battlefield with a +1/+1 counter on it"; staticText = "that card to the battlefield under its owner's control with a +1/+1 counter on it";
} }
public LongRoadHomeEntersBattlefieldEffect(LongRoadHomeEntersBattlefieldEffect effect) { public LongRoadHomeEntersBattlefieldEffect(LongRoadHomeEntersBattlefieldEffect effect) {
@ -188,7 +188,7 @@ class LongRoadHomeEntersBattlefieldEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null) { if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(), source, game); permanent.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
discard(); // use only once discard(); // use only once
} }
return false; return false;

View file

@ -30,17 +30,19 @@ package mage.cards.n;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.common.SpellMasteryCondition; import mage.abilities.condition.common.SpellMasteryCondition;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.Effect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInGraveyard; import mage.target.common.TargetCardInGraveyard;
@ -51,16 +53,15 @@ import mage.target.common.TargetCardInGraveyard;
public class NecromanticSummons extends CardImpl { public class NecromanticSummons extends CardImpl {
public NecromanticSummons(UUID ownerId, CardSetInfo setInfo) { public NecromanticSummons(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{4}{B}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{4}{B}");
this.getSpellAbility().addEffect(new NecromanticSummoningReplacementEffect());// has to be added before the moving effect
// Put target creature card from a graveyard onto the battlefield under your control. // Put target creature card from a graveyard onto the battlefield under your control.
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard"))); this.getSpellAbility().addTarget(new TargetCardInGraveyard(new FilterCreatureCard("creature card from a graveyard")));
// <i>Spell mastery</i> - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it. // <i>Spell mastery</i> - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it.
Effect effect = new ConditionalOneShotEffect(new NecromanticSummoningEffect(), this.getSpellAbility().addEffect(new InfoEffect("\"<br><i>Spell mastery</i> - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it\""));
SpellMasteryCondition.instance, "<br><i>Spell mastery</i> - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it");
this.getSpellAbility().addEffect(effect);
} }
public NecromanticSummons(final NecromanticSummons card) { public NecromanticSummons(final NecromanticSummons card) {
@ -73,29 +74,46 @@ public class NecromanticSummons extends CardImpl {
} }
} }
class NecromanticSummoningEffect extends OneShotEffect { class NecromanticSummoningReplacementEffect extends ReplacementEffectImpl {
public NecromanticSummoningEffect() { NecromanticSummoningReplacementEffect() {
super(Outcome.BoostCreature); super(Duration.EndOfStep, Outcome.BoostCreature);
this.staticText = "<br><i>Spell mastery</i> - If there are two or more instant and/or sorcery cards in your graveyard, that creature enters the battlefield with two additional +1/+1 counters on it";
} }
public NecromanticSummoningEffect(final NecromanticSummoningEffect effect) { NecromanticSummoningReplacementEffect(NecromanticSummoningReplacementEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public NecromanticSummoningEffect copy() { public boolean checksEventType(GameEvent event, Game game) {
return new NecromanticSummoningEffect(this); return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
}
@Override
public boolean applies(GameEvent event, Ability source, Game game) {
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
return SpellMasteryCondition.instance.apply(game, source);
}
return false;
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean apply(Game game, Ability source) {
Permanent permanent = game.getPermanent(source.getFirstTarget()); return false;
if (permanent != null) { }
permanent.addCounters(CounterType.P1P1.createInstance(2), source, game);
return true; @Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(2), source, game, event.getAppliedEffects());
discard();
} }
return false; return false;
} }
@Override
public NecromanticSummoningReplacementEffect copy() {
return new NecromanticSummoningReplacementEffect(this);
}
} }

View file

@ -58,7 +58,7 @@ import mage.target.targetpointer.FixedTarget;
public class OonasBlackguard extends CardImpl { public class OonasBlackguard extends CardImpl {
public OonasBlackguard(UUID ownerId, CardSetInfo setInfo) { public OonasBlackguard(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{1}{B}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{B}");
this.subtype.add("Faerie"); this.subtype.add("Faerie");
this.subtype.add("Rogue"); this.subtype.add("Rogue");
this.power = new MageInt(1); this.power = new MageInt(1);
@ -121,7 +121,7 @@ class OonasBlackguardReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) { if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source, game); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
return false; return false;
} }

View file

@ -57,7 +57,7 @@ import mage.target.common.TargetCreaturePermanent;
public class OtherworldlyJourney extends CardImpl { public class OtherworldlyJourney extends CardImpl {
public OtherworldlyJourney(UUID ownerId, CardSetInfo setInfo) { public OtherworldlyJourney(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{W}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{W}");
this.subtype.add("Arcane"); this.subtype.add("Arcane");
// Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it. // Exile target creature. At the beginning of the next end step, return that card to the battlefield under its owner's control with a +1/+1 counter on it.
@ -184,7 +184,7 @@ class OtherworldlyJourneyEntersBattlefieldEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent permanent = ((EntersTheBattlefieldEvent) event).getTarget();
if (permanent != null) { if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(), source, game); permanent.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
discard(); // use only once discard(); // use only once
} }
return false; return false;

View file

@ -56,7 +56,7 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class SageOfFables extends CardImpl { public class SageOfFables extends CardImpl {
public SageOfFables(UUID ownerId, CardSetInfo setInfo) { public SageOfFables(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{2}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{2}{U}");
this.subtype.add("Merfolk"); this.subtype.add("Merfolk");
this.subtype.add("Wizard"); this.subtype.add("Wizard");
this.power = new MageInt(2); this.power = new MageInt(2);
@ -115,7 +115,7 @@ class SageOfFablesReplacementEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) { if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source, game); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
return false; return false;
} }

View file

@ -64,7 +64,7 @@ import mage.watchers.Watcher;
public class SavageSummoning extends CardImpl { public class SavageSummoning extends CardImpl {
public SavageSummoning(UUID ownerId, CardSetInfo setInfo) { public SavageSummoning(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{G}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{G}");
// Savage Summoning can't be countered. // Savage Summoning can't be countered.
Ability ability = new CantBeCounteredAbility(); Ability ability = new CantBeCounteredAbility();
@ -315,7 +315,7 @@ class SavageSummoningEntersBattlefieldEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) { if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source, game); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
discard(); discard();
return false; return false;

View file

@ -49,8 +49,8 @@ import mage.players.Player;
public class ThoughtReflection extends CardImpl { public class ThoughtReflection extends CardImpl {
public ThoughtReflection(UUID ownerId, CardSetInfo setInfo) { public ThoughtReflection(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{4}{U}{U}{U}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{4}{U}{U}{U}");
// If you would draw a card, draw two cards instead. // If you would draw a card, draw two cards instead.
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThoughtReflectionReplacementEffect())); this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new ThoughtReflectionReplacementEffect()));
@ -90,13 +90,13 @@ class ThoughtReflectionReplacementEffect extends ReplacementEffectImpl {
@Override @Override
public boolean checksEventType(GameEvent event, Game game) { public boolean checksEventType(GameEvent event, Game game) {
return event.getType() == GameEvent.EventType.DRAW_CARD; return event.getType() == GameEvent.EventType.DRAW_CARD;
} }
@Override @Override
public boolean applies(GameEvent event, Ability source, Game game) { public boolean applies(GameEvent event, Ability source, Game game) {
return event.getPlayerId().equals(source.getControllerId()); return event.getPlayerId().equals(source.getControllerId());
} }
@Override @Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Player you = game.getPlayer(event.getPlayerId()); Player you = game.getPlayer(event.getPlayerId());
@ -104,5 +104,5 @@ class ThoughtReflectionReplacementEffect extends ReplacementEffectImpl {
you.drawCards(2, game, event.getAppliedEffects()); you.drawCards(2, game, event.getAppliedEffects());
} }
return true; return true;
} }
} }

View file

@ -30,17 +30,20 @@ package mage.cards.v;
import java.util.UUID; import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.condition.common.ManaWasSpentCondition; import mage.abilities.condition.common.ManaWasSpentCondition;
import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.ReplacementEffectImpl;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.common.InfoEffect;
import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect; import mage.abilities.effects.common.ReturnFromGraveyardToBattlefieldTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.CardType;
import mage.constants.ColoredManaSymbol; import mage.constants.ColoredManaSymbol;
import mage.constants.Duration;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.counters.CounterType; import mage.counters.CounterType;
import mage.filter.common.FilterCreatureCard; import mage.filter.common.FilterCreatureCard;
import mage.game.Game; import mage.game.Game;
import mage.game.events.EntersTheBattlefieldEvent;
import mage.game.events.GameEvent;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetCardInYourGraveyard;
@ -51,12 +54,14 @@ import mage.target.common.TargetCardInYourGraveyard;
public class VigorMortis extends CardImpl { public class VigorMortis extends CardImpl {
public VigorMortis(UUID ownerId, CardSetInfo setInfo) { public VigorMortis(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.SORCERY},"{2}{B}{B}"); super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{2}{B}{B}");
// Return target creature card from your graveyard to the battlefield. If {G} was spent to cast Vigor Mortis, that creature enters the battlefield with an additional +1/+1 counter on it. // Return target creature card from your graveyard to the battlefield. If {G} was spent to cast Vigor Mortis, that creature enters the battlefield with an additional +1/+1 counter on it.
this.getSpellAbility().addEffect(new VigorMortisReplacementEffect()); // has to be added before the moving effect
this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect()); this.getSpellAbility().addEffect(new ReturnFromGraveyardToBattlefieldTargetEffect());
this.getSpellAbility().addEffect(new InfoEffect("If {G} was spent to cast {this}, that creature enters the battlefield with an additional +1/+1 counter on it"));
this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard())); this.getSpellAbility().addTarget(new TargetCardInYourGraveyard(new FilterCreatureCard()));
this.getSpellAbility().addEffect(new ConditionalOneShotEffect(new VigorMortisAddCounterEffect(), new ManaWasSpentCondition(ColoredManaSymbol.G)));
} }
public VigorMortis(final VigorMortis card) { public VigorMortis(final VigorMortis card) {
@ -69,29 +74,46 @@ public class VigorMortis extends CardImpl {
} }
} }
class VigorMortisAddCounterEffect extends OneShotEffect { class VigorMortisReplacementEffect extends ReplacementEffectImpl {
VigorMortisAddCounterEffect() { VigorMortisReplacementEffect() {
super(Outcome.BoostCreature); super(Duration.EndOfStep, Outcome.BoostCreature);
this.staticText = "that creature enters the battlefield with an additional +1/+1 counter on it";
} }
VigorMortisAddCounterEffect(final VigorMortisAddCounterEffect effect) { VigorMortisReplacementEffect(VigorMortisReplacementEffect effect) {
super(effect); super(effect);
} }
@Override @Override
public VigorMortisAddCounterEffect copy() { public boolean checksEventType(GameEvent event, Game game) {
return new VigorMortisAddCounterEffect(this); return event.getType() == GameEvent.EventType.ENTERS_THE_BATTLEFIELD;
} }
@Override @Override
public boolean apply(Game game, Ability source) { public boolean applies(GameEvent event, Ability source, Game game) {
// targetPointer can't be used because target moved from graveyard to battlefield if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
Permanent permanent = game.getPermanent(source.getFirstTarget()); return new ManaWasSpentCondition(ColoredManaSymbol.G).apply(game, source);
if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(), source, game);
} }
return false; return false;
} }
@Override
public boolean apply(Game game, Ability source) {
return false;
}
@Override
public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent creature = ((EntersTheBattlefieldEvent) event).getTarget();
if (creature != null) {
creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
discard();
}
return false;
}
@Override
public VigorMortisReplacementEffect copy() {
return new VigorMortisReplacementEffect(this);
}
} }

View file

@ -55,7 +55,7 @@ import mage.target.common.TargetControlledCreaturePermanent;
public class ZameckGuildmage extends CardImpl { public class ZameckGuildmage extends CardImpl {
public ZameckGuildmage(UUID ownerId, CardSetInfo setInfo) { public ZameckGuildmage(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.CREATURE},"{G}{U}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{U}");
this.subtype.add("Elf"); this.subtype.add("Elf");
this.subtype.add("Wizard"); this.subtype.add("Wizard");
@ -112,7 +112,7 @@ class ZameckGuildmageEntersBattlefieldEffect extends ReplacementEffectImpl {
public boolean replaceEvent(GameEvent event, Ability source, Game game) { public boolean replaceEvent(GameEvent event, Ability source, Game game) {
Permanent target = ((EntersTheBattlefieldEvent) event).getTarget(); Permanent target = ((EntersTheBattlefieldEvent) event).getTarget();
if (target != null) { if (target != null) {
target.addCounters(CounterType.P1P1.createInstance(), source, game); target.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
return false; return false;
} }

View file

@ -52,7 +52,7 @@ public class DrawEffectsTest extends CardTestPlayerBase {
setStopAt(2, PhaseStep.PRECOMBAT_MAIN); setStopAt(2, PhaseStep.PRECOMBAT_MAIN);
execute(); execute();
Assert.assertEquals("Player B has to have 4 cards in hand", 8, playerB.getHand().size()); Assert.assertEquals("Player B has to have 8 cards in hand", 8, playerB.getHand().size());
} }

View file

@ -0,0 +1,142 @@
/*
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are
* permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
* of conditions and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those of the
* authors and should not be interpreted as representing official policies, either expressed
* or implied, of BetaSteward_at_googlemail.com.
*/
package org.mage.test.cards.replacement.entersBattlefield;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import mage.counters.CounterType;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
*
* @author LevelX2
*/
public class HardenedScaleTest extends CardTestPlayerBase {
/*
Reported bug: Hangarback interaciton with Hardened Scales and Metallic Mimic on board is incorrect.
*/
@Test
public void hangarBackHardenedScalesMetallicMimicTest() {
/*
Hangarback Walker {X}{X}
Artifact Creature Construct 0/0
Hangarback Walker enters the battlefield with X +1/+1 counters on it.
When Hangarback Walker dies, create a 1/1 colorless Thopter artifact creature token with flying for each +1/+1 counter on Hangarback Walker.
{1}, {T}: Put a +1/+1 counter on Hangarback Walker.
*/
String hWalker = "Hangarback Walker";
/*
Hardened Scales {G}
Enchantment
If one or more +1/+1 counters would be placed on a creature you control, that many plus one +1/+1 counters are placed on it instead.
*/
String hScales = "Hardened Scales";
/*
Metallic Mimic {2}
Artifact Creature Shapeshifter 2/1
As Metallic Mimic enters the battlefield, choose a creature type.
Metallic Mimic is the chosen type in addition to its other types.
Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it.
*/
String mMimic = "Metallic Mimic";
addCard(Zone.BATTLEFIELD, playerA, hScales);
addCard(Zone.HAND, playerA, mMimic);
addCard(Zone.HAND, playerA, hWalker);
addCard(Zone.BATTLEFIELD, playerA, "Wastes", 4);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, mMimic);
setChoice(playerA, "Construct");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, hWalker);
setChoice(playerA, "X=1");
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, mMimic, 1);
assertPermanentCount(playerA, hWalker, 1);
assertCounterCount(playerA, hWalker, CounterType.P1P1, 3);
assertPowerToughness(playerA, hWalker, 3, 3);
}
@Test
public void testWithVigorMortis() {
/*
Vigor Mortis {2}{B}{B}
Sorcery
Return target creature card from your graveyard to the battlefield. If {G} was spent to cast Vigor Mortis,
that creature enters the battlefield with an additional +1/+1 counter on it.
*/
String vMortis = "Vigor Mortis";
/*
Hardened Scales {G}
Enchantment
If one or more +1/+1 counters would be placed on a creature you control, that many plus one +1/+1 counters are placed on it instead.
*/
String hScales = "Hardened Scales";
/*
Metallic Mimic {2}
Artifact Creature Shapeshifter 2/1
As Metallic Mimic enters the battlefield, choose a creature type.
Metallic Mimic is the chosen type in addition to its other types.
Each other creature you control of the chosen type enters the battlefield with an additional +1/+1 counter on it.
*/
String mMimic = "Metallic Mimic";
addCard(Zone.GRAVEYARD, playerA, "Silvercoat Lion");
addCard(Zone.BATTLEFIELD, playerA, hScales);
addCard(Zone.HAND, playerA, mMimic);
addCard(Zone.HAND, playerA, vMortis);
addCard(Zone.BATTLEFIELD, playerA, "Forest", 2);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 2);
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, mMimic);
setChoice(playerA, "Cat");
castSpell(3, PhaseStep.PRECOMBAT_MAIN, playerA, vMortis, "Silvercoat Lion");
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerA, mMimic, 1);
assertPermanentCount(playerA, "Silvercoat Lion", 1);
assertCounterCount(playerA, "Silvercoat Lion", CounterType.P1P1, 3);
assertPowerToughness(playerA, "Silvercoat Lion", 5, 5); // Hardened Scales is only once applied to EntersTheBattlefield event
assertGraveyardCount(playerA, vMortis, 1);
}
}

View file

@ -27,6 +27,9 @@
*/ */
package mage.abilities.effects; package mage.abilities.effects;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
import mage.MageObject; import mage.MageObject;
import mage.abilities.*; import mage.abilities.*;
import mage.abilities.keyword.SpliceOntoArcaneAbility; import mage.abilities.keyword.SpliceOntoArcaneAbility;
@ -49,10 +52,6 @@ import mage.players.Player;
import mage.target.common.TargetCardInHand; import mage.target.common.TargetCardInHand;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import java.io.Serializable;
import java.util.*;
import java.util.Map.Entry;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -691,8 +690,7 @@ public class ContinuousEffects implements Serializable {
spliceAbilities.remove(selectedAbility); spliceAbilities.remove(selectedAbility);
} }
} }
} } while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
while (!spliceAbilities.isEmpty() && controller.chooseUse(Outcome.Benefit, "Splice another card?", abilityToModify, game));
controller.revealCards("Spliced cards", cardsToReveal, game); controller.revealCards("Spliced cards", cardsToReveal, game);
} }
} }
@ -702,10 +700,10 @@ public class ContinuousEffects implements Serializable {
* Checks if an event won't happen because of an rule modifying effect * Checks if an event won't happen because of an rule modifying effect
* *
* @param event * @param event
* @param targetAbility ability the event is attached to. can be null. * @param targetAbility ability the event is attached to. can be null.
* @param game * @param game
* @param checkPlayableMode true if the event does not really happen but * @param checkPlayableMode true if the event does not really happen but
* it's checked if the event would be replaced * it's checked if the event would be replaced
* @return * @return
*/ */
public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) { public boolean preventedByRuleModification(GameEvent event, Ability targetAbility, Game game, boolean checkPlayableMode) {
@ -752,7 +750,7 @@ public class ContinuousEffects implements Serializable {
do { do {
HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game); HashMap<ReplacementEffect, HashSet<Ability>> rEffects = getApplicableReplacementEffects(event, game);
// Remove all consumed effects (ability dependant) // Remove all consumed effects (ability dependant)
for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext(); ) { for (Iterator<ReplacementEffect> it1 = rEffects.keySet().iterator(); it1.hasNext();) {
ReplacementEffect entry = it1.next(); ReplacementEffect entry = it1.next();
if (consumed.containsKey(entry.getId())) { if (consumed.containsKey(entry.getId())) {
HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId()); HashSet<UUID> consumedAbilitiesIds = consumed.get(entry.getId());
@ -933,7 +931,7 @@ public class ContinuousEffects implements Serializable {
if (!waitingEffects.isEmpty()) { if (!waitingEffects.isEmpty()) {
// check if waiting effects can be applied now // check if waiting effects can be applied now
for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext(); ) { for (Iterator<Map.Entry<ContinuousEffect, Set<UUID>>> iterator = waitingEffects.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next(); Map.Entry<ContinuousEffect, Set<UUID>> entry = iterator.next();
if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself if (appliedEffects.containsAll(entry.getValue())) { // all dependent to effects are applied now so apply the effect itself
appliedAbilities = appliedEffectAbilities.get(entry.getKey()); appliedAbilities = appliedEffectAbilities.get(entry.getKey());

View file

@ -148,6 +148,7 @@ public class EntersBattlefieldEffect extends ReplacementEffectImpl {
if (spell != null) { if (spell != null) {
effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility()); effect.setValue(SOURCE_CAST_SPELL_ABILITY, spell.getSpellAbility());
} }
effect.setValue("appliedEffects", event.getAppliedEffects());
effect.apply(game, source); effect.apply(game, source);
} }
// } // }

View file

@ -27,6 +27,8 @@
*/ */
package mage.abilities.effects.common; package mage.abilities.effects.common;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.SpellAbility; import mage.abilities.SpellAbility;
import mage.abilities.effects.EntersBattlefieldEffect; import mage.abilities.effects.EntersBattlefieldEffect;
@ -75,7 +77,8 @@ public class EntersBattlefieldWithXCountersEffect extends OneShotEffect {
if (amount > 0) { if (amount > 0) {
Counter counterToAdd = counter.copy(); Counter counterToAdd = counter.copy();
counterToAdd.add(amount - counter.getCount()); counterToAdd.add(amount - counter.getCount());
permanent.addCounters(counterToAdd, source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
permanent.addCounters(counterToAdd, source, game, appliedEffects);
} }
} }
} }

View file

@ -27,6 +27,8 @@
*/ */
package mage.abilities.effects.common.counter; package mage.abilities.effects.common.counter;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.StaticValue; import mage.abilities.dynamicvalue.common.StaticValue;
@ -103,7 +105,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
countersToAdd--; countersToAdd--;
} }
newCounter.add(countersToAdd); newCounter.add(countersToAdd);
card.addCounters(newCounter, source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
card.addCounters(newCounter, source, game, appliedEffects);
if (informPlayers && !game.isSimulation()) { if (informPlayers && !game.isSimulation()) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
if (player != null) { if (player != null) {
@ -128,7 +131,8 @@ public class AddCountersSourceEffect extends OneShotEffect {
} }
newCounter.add(countersToAdd); newCounter.add(countersToAdd);
int before = permanent.getCounters(game).getCount(newCounter.getName()); int before = permanent.getCounters(game).getCount(newCounter.getName());
permanent.addCounters(newCounter, source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects");
permanent.addCounters(newCounter, source, game, appliedEffects); // if used from a replacement effect, the basic event determines if an effect was already applied to an event
if (informPlayers && !game.isSimulation()) { if (informPlayers && !game.isSimulation()) {
int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before; int amountAdded = permanent.getCounters(game).getCount(newCounter.getName()) - before;
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
@ -150,12 +154,10 @@ public class AddCountersSourceEffect extends OneShotEffect {
sb.append("put "); sb.append("put ");
if (counter.getCount() > 1) { if (counter.getCount() > 1) {
sb.append(CardUtil.numberToText(counter.getCount())).append(' '); sb.append(CardUtil.numberToText(counter.getCount())).append(' ');
} else if (amount.toString().equals("X") && amount.getMessage().isEmpty()) {
sb.append("X ");
} else { } else {
if (amount.toString().equals("X") && amount.getMessage().isEmpty()) { sb.append("a ");
sb.append("X ");
} else {
sb.append("a ");
}
} }
sb.append(counter.getName().toLowerCase()).append(" counter on {this}"); sb.append(counter.getName().toLowerCase()).append(" counter on {this}");
if (!amount.getMessage().isEmpty()) { if (!amount.getMessage().isEmpty()) {

View file

@ -1,5 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -71,7 +73,8 @@ class BloodthirstEffect extends OneShotEffect {
if (watcher != null && watcher.conditionMet()) { if (watcher != null && watcher.conditionMet()) {
Permanent permanent = game.getPermanentEntering(source.getSourceId()); Permanent permanent = game.getPermanentEntering(source.getSourceId());
if (permanent != null) { if (permanent != null) {
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
permanent.addCounters(CounterType.P1P1.createInstance(amount), source, game, appliedEffects);
} }
} }
return true; return true;

View file

@ -1,5 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.StaticAbility; import mage.abilities.StaticAbility;
import mage.abilities.common.DiesTriggeredAbility; import mage.abilities.common.DiesTriggeredAbility;
@ -159,7 +161,8 @@ class ModularDistributeCounterEffect extends OneShotEffect {
if (sourcePermanent != null && targetArtifact != null && player != null) { if (sourcePermanent != null && targetArtifact != null && player != null) {
int numberOfCounters = sourcePermanent.getCounters(game).getCount(CounterType.P1P1); int numberOfCounters = sourcePermanent.getCounters(game).getCount(CounterType.P1P1);
if (numberOfCounters > 0) { if (numberOfCounters > 0) {
targetArtifact.addCounters(CounterType.P1P1.createInstance(numberOfCounters), source, game); ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
targetArtifact.addCounters(CounterType.P1P1.createInstance(numberOfCounters), source, game, appliedEffects);
} }
return true; return true;
} }

View file

@ -27,13 +27,14 @@
*/ */
package mage.abilities.keyword; package mage.abilities.keyword;
import java.util.ArrayList;
import java.util.UUID;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldAbility; import mage.abilities.common.EntersBattlefieldAbility;
import mage.abilities.dynamicvalue.DynamicValue; import mage.abilities.dynamicvalue.DynamicValue;
import mage.abilities.dynamicvalue.common.SunburstCount; import mage.abilities.dynamicvalue.common.SunburstCount;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
import mage.cards.Card; import mage.cards.Card;
import mage.constants.CardType;
import mage.constants.Outcome; import mage.constants.Outcome;
import mage.counters.Counter; import mage.counters.Counter;
import mage.counters.CounterType; import mage.counters.CounterType;
@ -97,8 +98,8 @@ class SunburstEffect extends OneShotEffect {
counter = CounterType.CHARGE.createInstance(amount.calculate(game, source, this)); counter = CounterType.CHARGE.createInstance(amount.calculate(game, source, this));
} }
if (counter != null) { if (counter != null) {
ArrayList<UUID> appliedEffects = (ArrayList<UUID>) this.getValue("appliedEffects"); // the basic event is the EntersBattlefieldEvent, so use already applied replacement effects from that event
permanent.addCounters(counter, source, game); permanent.addCounters(counter, source, game, appliedEffects);
if (!game.isSimulation()) { if (!game.isSimulation()) {
Player player = game.getPlayer(source.getControllerId()); Player player = game.getPlayer(source.getControllerId());
if (player != null) { if (player != null) {

View file

@ -105,7 +105,7 @@ class UnleashReplacementEffect extends ReplacementEffectImpl {
if (!game.isSimulation()) { if (!game.isSimulation()) {
game.informPlayers(controller.getLogName() + " unleashes " + creature.getName()); game.informPlayers(controller.getLogName() + " unleashes " + creature.getName());
} }
creature.addCounters(CounterType.P1P1.createInstance(), source, game); creature.addCounters(CounterType.P1P1.createInstance(), source, game, event.getAppliedEffects());
} }
} }
return false; return false;

View file

@ -76,7 +76,7 @@ public class MageDrawAction extends MageAction {
*/ */
protected int drawCard(Game game) { protected int drawCard(Game game) {
GameEvent event = GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, player.getId(), player.getId()); GameEvent event = GameEvent.getEvent(GameEvent.EventType.DRAW_CARD, player.getId(), player.getId());
event.setAppliedEffects(appliedEffects); event.addAppliedEffects(appliedEffects);
if (!game.replaceEvent(event)) { if (!game.replaceEvent(event)) {
Card card = player.getLibrary().removeFromTop(game); Card card = player.getLibrary().removeFromTop(game);
if (card != null) { if (card != null) {

View file

@ -451,12 +451,19 @@ public class GameEvent implements Serializable {
return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType); return type == EventType.CUSTOM_EVENT && this.customEventType.equals(customEventType);
} }
public void setAppliedEffects(ArrayList<UUID> appliedEffects) { public void addAppliedEffects(ArrayList<UUID> appliedEffects) {
if (this.appliedEffects == null) {
this.appliedEffects = new ArrayList<>();
}
if (appliedEffects != null) { if (appliedEffects != null) {
this.appliedEffects.addAll(appliedEffects); this.appliedEffects.addAll(appliedEffects);
} }
} }
public void setAppliedEffects(ArrayList<UUID> appliedEffects) {
if (appliedEffects != null) {
if (this.appliedEffects.isEmpty()) {
this.appliedEffects = appliedEffects; // Use object refecence to handle that an replacement effect can only be once applied to an event
} else {
this.appliedEffects.addAll(appliedEffects);
}
}
}
} }