mirror of
https://github.com/correl/mage.git
synced 2024-12-26 03:00:11 +00:00
* 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:
parent
94f77675ec
commit
d0bf77cedf
25 changed files with 302 additions and 104 deletions
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -49,7 +49,7 @@ 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()));
|
||||||
|
|
|
@ -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
|
||||||
|
public boolean applies(GameEvent event, Ability source, Game game) {
|
||||||
|
if (event.getTargetId().equals(getTargetPointer().getFirst(game, source))) {
|
||||||
|
return new ManaWasSpentCondition(ColoredManaSymbol.G).apply(game, source);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
// targetPointer can't be used because target moved from graveyard to battlefield
|
return false;
|
||||||
Permanent permanent = game.getPermanent(source.getFirstTarget());
|
}
|
||||||
if (permanent != null) {
|
|
||||||
permanent.addCounters(CounterType.P1P1.createInstance(), source, game);
|
@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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public VigorMortisReplacementEffect copy() {
|
||||||
|
return new VigorMortisReplacementEffect(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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());
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue