diff --git a/Mage.Sets/src/mage/sets/alarareborn/RetaliatorGriffin.java b/Mage.Sets/src/mage/sets/alarareborn/RetaliatorGriffin.java index 50d62a45535..09b150888d8 100644 --- a/Mage.Sets/src/mage/sets/alarareborn/RetaliatorGriffin.java +++ b/Mage.Sets/src/mage/sets/alarareborn/RetaliatorGriffin.java @@ -36,13 +36,14 @@ import mage.MageInt; import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.OneShotEffect; +import mage.abilities.effects.common.counter.AddCountersSourceEffect; import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; +import mage.players.Player; /** * @@ -55,9 +56,6 @@ public class RetaliatorGriffin extends CardImpl { this.expansionSetCode = "ARB"; this.subtype.add("Griffin"); - - - this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -79,7 +77,7 @@ public class RetaliatorGriffin extends CardImpl { class RetaliatorGriffinTriggeredAbility extends TriggeredAbilityImpl { public RetaliatorGriffinTriggeredAbility() { - super(Zone.BATTLEFIELD, new RetaliatorGriffinEffect(), false); + super(Zone.BATTLEFIELD, new RetaliatorGriffinEffect(), true); } public RetaliatorGriffinTriggeredAbility(final RetaliatorGriffinTriggeredAbility ability) { @@ -90,22 +88,19 @@ class RetaliatorGriffinTriggeredAbility extends TriggeredAbilityImpl { public RetaliatorGriffinTriggeredAbility copy() { return new RetaliatorGriffinTriggeredAbility(this); } - + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER); + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER)) { - UUID sourceControllerId = null; - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - sourceControllerId = permanent.getControllerId(); - } else { - StackObject sourceStackObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceStackObject != null) { - sourceControllerId = sourceStackObject.getControllerId(); - } - } - if (event.getTargetId().equals(controllerId) && game.getOpponents(controllerId).contains(sourceControllerId)) { - getEffects().get(0).setValue("RetaliatorGriffinAmount", event.getAmount()); + if (event.getTargetId().equals(getControllerId())) { + UUID sourceControllerId = game.getControllerId(event.getSourceId()); + if (sourceControllerId != null && + game.getOpponents(getControllerId()).contains(sourceControllerId)) { + getEffects().get(0).setValue("damageAmount", event.getAmount()); return true; } } @@ -135,10 +130,13 @@ class RetaliatorGriffinEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - Integer amount = (Integer) this.getValue("RetaliatorGriffinAmount"); - if (permanent != null && amount != null) { - permanent.addCounters(CounterType.P1P1.createInstance(amount), game); + Player controller = game.getPlayer(source.getControllerId()); + if (controller != null) { + Permanent permanent = game.getPermanent(source.getSourceId()); + Integer amount = (Integer) this.getValue("damageAmount"); + if (permanent != null && amount != null && amount > 0) { + new AddCountersSourceEffect(CounterType.P1P1.createInstance(amount), true).apply(game, source); + } return true; } return false; diff --git a/Mage.Sets/src/mage/sets/bornofthegods/SatyrFiredancer.java b/Mage.Sets/src/mage/sets/bornofthegods/SatyrFiredancer.java index 96671fc94a5..9f285c595fe 100644 --- a/Mage.Sets/src/mage/sets/bornofthegods/SatyrFiredancer.java +++ b/Mage.Sets/src/mage/sets/bornofthegods/SatyrFiredancer.java @@ -36,6 +36,7 @@ import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; +import mage.cards.Card; import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; @@ -63,7 +64,6 @@ public class SatyrFiredancer extends CardImpl { this.expansionSetCode = "BNG"; this.subtype.add("Satyr"); - this.color.setRed(true); this.power = new MageInt(1); this.toughness = new MageInt(1); @@ -95,7 +95,7 @@ public class SatyrFiredancer extends CardImpl { class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { - private List handledStackObjects = new ArrayList(); + private List handledStackObjects = new ArrayList<>(); public SatyrFiredancerTriggeredAbility() { super(Zone.BATTLEFIELD, new SatyrFiredancerDamageEffect(), false); @@ -115,22 +115,26 @@ class SatyrFiredancerTriggeredAbility extends TriggeredAbilityImpl { handledStackObjects.clear(); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGED_PLAYER; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.DAMAGED_PLAYER) { - StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); - if (stackObject != null && stackObject.getControllerId().equals(getControllerId())) { - MageObject object = game.getObject(stackObject.getSourceId()); - if (object.getCardType().contains(CardType.INSTANT) || object.getCardType().contains(CardType.SORCERY)) { - if (game.getOpponents(getControllerId()).contains(event.getTargetId())) { - if (!handledStackObjects.contains(stackObject.getId())) { - handledStackObjects.add(stackObject.getId()); - for (Effect effect: this.getEffects()) { - effect.setTargetPointer(new FixedTarget(event.getTargetId())); - effect.setValue("damage", event.getAmount()); - } - return true; + if (getControllerId().equals(game.getControllerId(event.getSourceId()))) { + MageObject damageSource = game.getObject(event.getSourceId()); + if (damageSource != null) { + if (game.getOpponents(getControllerId()).contains(event.getTargetId())) { + if (!(damageSource instanceof StackObject) || !handledStackObjects.contains(damageSource.getId())) { + if (damageSource instanceof StackObject) { + handledStackObjects.add(damageSource.getId()); } + for (Effect effect: this.getEffects()) { + effect.setTargetPointer(new FixedTarget(event.getTargetId())); // used by adjust targets + effect.setValue("damage", event.getAmount()); + } + return true; } } } diff --git a/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java b/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java index 9332a44fc13..4dc321dea1c 100644 --- a/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java +++ b/Mage.Sets/src/mage/sets/championsofkamigawa/NightDealings.java @@ -52,7 +52,6 @@ import mage.filter.predicate.mageobject.ConvertedManaCostPredicate; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; import mage.players.Player; import mage.target.common.TargetCardInLibrary; @@ -65,7 +64,7 @@ public class NightDealings extends CardImpl { public NightDealings (UUID ownerId) { super(ownerId, 132, "Night Dealings", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{B}{B}"); this.expansionSetCode = "CHK"; - this.color.setBlack(true); + // Whenever a source you control deals damage to another player, put that many theft counters on Night Dealings. this.addAbility((new NightDealingsTriggeredAbility())); @@ -100,30 +99,24 @@ public class NightDealings extends CardImpl { return new NightDealingsTriggeredAbility(this); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == GameEvent.EventType.DAMAGED_PLAYER; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == GameEvent.EventType.DAMAGED_PLAYER) { - // to another player - if (this.getControllerId() != event.getTargetId()) { - // a source you control - UUID sourceControllerId = null; - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - sourceControllerId = permanent.getControllerId(); - } else { - StackObject sourceStackObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceStackObject != null) { - sourceControllerId = sourceStackObject.getControllerId(); - } - } - if (sourceControllerId != null && sourceControllerId == this.getControllerId()) { - // save amount of damage to effect - this.getEffects().get(0).setValue("damageAmount", event.getAmount()); - return true; - } + // to another player + if (this.getControllerId() != event.getTargetId()) { + // a source you control + UUID sourceControllerId = game.getControllerId(event.getSourceId()); + if (sourceControllerId != null && sourceControllerId == this.getControllerId()) { + // save amount of damage to effect + this.getEffects().get(0).setValue("damageAmount", event.getAmount()); + return true; } } - return false; + return false; } @Override @@ -136,7 +129,7 @@ public class NightDealings extends CardImpl { public NightDealingsEffect() { super(Outcome.Damage); - this.staticText = "put that many theft counters on Night Dealings"; + this.staticText = "put that many theft counters on {this}"; } public NightDealingsEffect(final NightDealingsEffect effect) { @@ -219,4 +212,4 @@ public class NightDealings extends CardImpl { } } -} \ No newline at end of file +} diff --git a/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java b/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java index 3eb68074c88..f728094c195 100644 --- a/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java +++ b/Mage.Sets/src/mage/sets/dragonsmaze/BlazeCommando.java @@ -40,10 +40,12 @@ import mage.MageObject; import mage.abilities.TriggeredAbilityImpl; import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.keyword.HasteAbility; +import mage.cards.Card; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.events.GameEvent.EventType; +import mage.game.permanent.Permanent; import mage.game.permanent.token.Token; import mage.game.stack.StackObject; @@ -82,7 +84,7 @@ public class BlazeCommando extends CardImpl { } class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { - private List handledStackObjects = new ArrayList(); + private final List handledStackObjects = new ArrayList<>(); public BlazeCommandoTriggeredAbility() { super(Zone.BATTLEFIELD, new CreateTokenEffect(new BlazeCommandoSoldierToken(), 2), false); @@ -99,18 +101,30 @@ class BlazeCommandoTriggeredAbility extends TriggeredAbilityImpl { @Override public void reset(Game game) { + /** + * Blaze Commando's ability triggers each time an instant or sorcery spell you control + * deals damage (or, put another way, the number of times the word “deals” appears in + * its instructions), no matter how much damage is dealt or how many players or permanents + * are dealt damage. For example, if you cast Punish the Enemy and it “deals 3 damage to + * target player and 3 damage to target creature,” Blaze Commando's ability will trigger + * once and you'll get two Soldier tokens. + */ handledStackObjects.clear(); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType() == EventType.DAMAGED_CREATURE || event.getType() == EventType.DAMAGED_PLANESWALKER || event.getType() == EventType.DAMAGED_PLAYER; + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType() == EventType.DAMAGED_CREATURE || event.getType() == EventType.DAMAGED_PLANESWALKER || event.getType() == EventType.DAMAGED_PLAYER) { - StackObject stackObject = game.getStack().getStackObject(event.getSourceId()); - if (stackObject != null && stackObject.getControllerId().equals(getControllerId())) { - MageObject object = game.getObject(stackObject.getSourceId()); - if (object.getCardType().contains(CardType.INSTANT) || object.getCardType().contains(CardType.SORCERY)) { - if (!handledStackObjects.contains(stackObject.getId())) { - handledStackObjects.add(stackObject.getId()); + if (getControllerId().equals(game.getControllerId(event.getSourceId()))) { + MageObject damageSource = game.getObject(event.getSourceId()); + if (damageSource != null) { + if (damageSource.getCardType().contains(CardType.INSTANT) || damageSource.getCardType().contains(CardType.SORCERY)) { + if (!handledStackObjects.contains(damageSource.getId())) { + handledStackObjects.add(damageSource.getId()); return true; } } diff --git a/Mage.Sets/src/mage/sets/magic2010/GuardianSeraph.java b/Mage.Sets/src/mage/sets/magic2010/GuardianSeraph.java index 1b6be3bfed5..22203d49b14 100644 --- a/Mage.Sets/src/mage/sets/magic2010/GuardianSeraph.java +++ b/Mage.Sets/src/mage/sets/magic2010/GuardianSeraph.java @@ -40,8 +40,6 @@ import mage.abilities.keyword.FlyingAbility; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; /** * @@ -54,11 +52,11 @@ public class GuardianSeraph extends CardImpl { this.expansionSetCode = "M10"; this.subtype.add("Angel"); - this.color.setWhite(true); this.power = new MageInt(3); this.toughness = new MageInt(4); this.addAbility(FlyingAbility.getInstance()); + // If a source an opponent controls would deal damage to you, prevent 1 of that damage. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new GuardianSeraphEffect())); } @@ -76,47 +74,24 @@ public class GuardianSeraph extends CardImpl { class GuardianSeraphEffect extends PreventionEffectImpl { public GuardianSeraphEffect() { - super(Duration.WhileOnBattlefield); + super(Duration.WhileOnBattlefield, 1, false, false); this.staticText = "If a source an opponent controls would deal damage to you, prevent 1 of that damage"; } - public GuardianSeraphEffect(GuardianSeraphEffect effect) { + public GuardianSeraphEffect(final GuardianSeraphEffect effect) { super(effect); } @Override - public boolean replaceEvent(GameEvent event, Ability source, Game game) { - GameEvent preventEvent = new GameEvent(GameEvent.EventType.PREVENT_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), 1, false); - if (!game.replaceEvent(preventEvent)) { - int damage = event.getAmount(); - if (damage > 0) { - event.setAmount(damage - 1); - game.informPlayers("1 damage has been prevented."); - } - game.fireEvent(GameEvent.getEvent(GameEvent.EventType.PREVENTED_DAMAGE, source.getFirstTarget(), source.getSourceId(), source.getControllerId(), 1)); - } - return false; + public boolean checksEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER); } - - @Override - public boolean apply(Game game, Ability source) { - return true; - } - + @Override public boolean applies(GameEvent event, Ability source, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGE_PLAYER)) { - UUID sourceControllerId = null; - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - sourceControllerId = permanent.getControllerId(); - } else { - StackObject sourceStackObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceStackObject != null) { - sourceControllerId = sourceStackObject.getControllerId(); - } - } - if (event.getTargetId().equals(source.getControllerId()) && game.getOpponents(source.getControllerId()).contains(sourceControllerId)) { + if (event.getTargetId().equals(source.getControllerId())) { + UUID sourceControllerId = game.getControllerId(event.getSourceId()); + if (sourceControllerId != null && game.getOpponents(source.getControllerId()).contains(sourceControllerId)) { return super.applies(event, source, game); } } diff --git a/Mage.Sets/src/mage/sets/mirrodin/FarsightMask.java b/Mage.Sets/src/mage/sets/mirrodin/FarsightMask.java index b7133350056..7aa5166950c 100644 --- a/Mage.Sets/src/mage/sets/mirrodin/FarsightMask.java +++ b/Mage.Sets/src/mage/sets/mirrodin/FarsightMask.java @@ -29,20 +29,14 @@ package mage.sets.mirrodin; import java.util.UUID; import mage.constants.CardType; -import mage.constants.Outcome; import mage.constants.Rarity; import mage.constants.Zone; -import mage.abilities.Ability; import mage.abilities.TriggeredAbilityImpl; -import mage.abilities.condition.Condition; -import mage.abilities.decorator.ConditionalOneShotEffect; import mage.abilities.effects.common.DrawCardSourceControllerEffect; import mage.cards.CardImpl; import mage.game.Game; import mage.game.events.GameEvent; import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; -import mage.players.Player; /** * @@ -71,7 +65,7 @@ public class FarsightMask extends CardImpl { class FarsightMaskTriggeredAbility extends TriggeredAbilityImpl { public FarsightMaskTriggeredAbility() { - super(Zone.BATTLEFIELD, new ConditionalOneShotEffect(new DrawCardSourceControllerEffect(1), new FarsightMaskCondition(), ""), false); + super(Zone.BATTLEFIELD, new DrawCardSourceControllerEffect(1), true); } public FarsightMaskTriggeredAbility(final FarsightMaskTriggeredAbility ability) { @@ -83,20 +77,22 @@ class FarsightMaskTriggeredAbility extends TriggeredAbilityImpl { return new FarsightMaskTriggeredAbility(this); } + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER); + } + + @Override + public boolean checkInterveningIfClause(Game game) { + Permanent permanent = game.getPermanent(getSourceId()); + return permanent != null && !permanent.isTapped(); + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER)) { - UUID sourceControllerId = null; - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - sourceControllerId = permanent.getControllerId(); - } else { - StackObject sourceStackObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceStackObject != null) { - sourceControllerId = sourceStackObject.getControllerId(); - } - } - if (event.getTargetId().equals(controllerId) && game.getOpponents(controllerId).contains(sourceControllerId)) { + if (event.getTargetId().equals(controllerId)) { + UUID sourceControllerId = game.getControllerId(event.getSourceId()); + if (sourceControllerId != null && game.getOpponents(getControllerId()).contains(sourceControllerId)) { return true; } } @@ -105,20 +101,6 @@ class FarsightMaskTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a source an opponent controls deals damage to you, if Farsight Mask is untapped, you may draw a card."; + return "Whenever a source an opponent controls deals damage to you, if {this} is untapped, you may draw a card."; } } - -class FarsightMaskCondition implements Condition { - - @Override - public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanent(source.getSourceId()); - Player player = game.getPlayer(source.getControllerId()); - if (permanent != null && !permanent.isTapped() - && player != null && player.chooseUse(Outcome.DrawCard, "Do you wish to draw a card?", game)) { - return true; - } - return false; - } -} \ No newline at end of file diff --git a/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java b/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java index b1f71a9606f..90781a35f0e 100644 --- a/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java +++ b/Mage.Sets/src/mage/sets/modernmasters/PyromancersSwath.java @@ -54,8 +54,6 @@ public class PyromancersSwath extends CardImpl { super(ownerId, 125, "Pyromancer's Swath", Rarity.RARE, new CardType[]{CardType.ENCHANTMENT}, "{2}{R}"); this.expansionSetCode = "MMA"; - this.color.setRed(true); - // If an instant or sorcery source you control would deal damage to a creature or player, it deals that much damage plus 2 to that creature or player instead. this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD, new PyromancersSwathReplacementEffect())); @@ -98,14 +96,10 @@ class PyromancersSwathReplacementEffect extends ReplacementEffectImpl { } @Override - public boolean applies(GameEvent event, Ability source, Game game) { - MageObject object = game.getObject(event.getSourceId()); - if (object != null && object instanceof Spell) { - if (((Spell) object).getControllerId().equals(source.getControllerId()) - && (object.getCardType().contains(CardType.INSTANT) - || object.getCardType().contains(CardType.SORCERY))){ - return true; - } + public boolean applies(GameEvent event, Ability source, Game game) { + if (source.getControllerId().equals(game.getControllerId(event.getSourceId()))) { + MageObject object = game.getObject(event.getSourceId()); + return object != null && (object.getCardType().contains(CardType.INSTANT) || object.getCardType().contains(CardType.SORCERY)); } return false; } diff --git a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MichikoKondaTruthSeeker.java b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MichikoKondaTruthSeeker.java index 15c81b4d37c..40aad8c5e95 100644 --- a/Mage.Sets/src/mage/sets/saviorsofkamigawa/MichikoKondaTruthSeeker.java +++ b/Mage.Sets/src/mage/sets/saviorsofkamigawa/MichikoKondaTruthSeeker.java @@ -38,8 +38,6 @@ import mage.cards.CardImpl; import mage.filter.FilterPermanent; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; import mage.target.targetpointer.FixedTarget; /** @@ -55,7 +53,6 @@ public class MichikoKondaTruthSeeker extends CardImpl { this.subtype.add("Human"); this.subtype.add("Advisor"); - this.color.setWhite(true); this.power = new MageInt(2); this.toughness = new MageInt(2); @@ -87,21 +84,18 @@ class MichikoKondaTruthSeekerAbility extends TriggeredAbilityImpl { public MichikoKondaTruthSeekerAbility copy() { return new MichikoKondaTruthSeekerAbility(this); } - + + @Override + public boolean checkEventType(GameEvent event, Game game) { + return event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER); + } + @Override public boolean checkTrigger(GameEvent event, Game game) { - if (event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER)) { - UUID sourceControllerId = null; - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null) { - sourceControllerId = permanent.getControllerId(); - } else { - StackObject sourceStackObject = game.getStack().getStackObject(event.getSourceId()); - if (sourceStackObject != null) { - sourceControllerId = sourceStackObject.getControllerId(); - } - } - if (event.getTargetId().equals(controllerId) && game.getOpponents(controllerId).contains(sourceControllerId)) { + if (event.getTargetId().equals(getControllerId())) { + UUID sourceControllerId = game.getControllerId(event.getSourceId()); + if (sourceControllerId != null && + game.getOpponents(getControllerId()).contains(sourceControllerId)) { getEffects().get(0).setTargetPointer(new FixedTarget(sourceControllerId)); return true; } diff --git a/Mage.Sets/src/mage/sets/zendikar/QuestForPureFlame.java b/Mage.Sets/src/mage/sets/zendikar/QuestForPureFlame.java index 95a4f09d1e5..1045a048dcb 100644 --- a/Mage.Sets/src/mage/sets/zendikar/QuestForPureFlame.java +++ b/Mage.Sets/src/mage/sets/zendikar/QuestForPureFlame.java @@ -44,9 +44,6 @@ import mage.constants.Zone; import mage.counters.CounterType; import mage.game.Game; import mage.game.events.GameEvent; -import mage.game.permanent.Permanent; -import mage.game.stack.StackObject; -import mage.players.Player; /** * @@ -95,27 +92,15 @@ class QuestForPureFlameTriggeredAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event.getType().equals(GameEvent.EventType.DAMAGED_PLAYER) - && game.getOpponents(controllerId).contains(event.getTargetId())) { - Permanent permanent = game.getPermanent(event.getSourceId()); - Player player = game.getPlayer(event.getSourceId()); - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (permanent != null && permanent.getControllerId().equals(controllerId)) { - return true; - } - if (player != null && player.getId().equals(controllerId)) { - return true; - } - if (spell != null && spell.getControllerId().equals(controllerId)) { - return true; - } - return false; + && game.getOpponents(getControllerId()).contains(event.getTargetId())) { + return getControllerId().equals(game.getControllerId(event.getSourceId())); } return false; } @Override public String getRule() { - return "Whenever a source you control deals damage to an opponent, you may put a quest counter on Quest for Pure Flame."; + return "Whenever a source you control deals damage to an opponent, you may put a quest counter on {this}."; } } @@ -143,24 +128,7 @@ class QuestForPureFlameEffect extends ReplacementEffectImpl { @Override public boolean applies(GameEvent event, Ability source, Game game) { - Permanent permanent = game.getPermanent(event.getSourceId()); - if (permanent != null && permanent.getControllerId().equals(source.getControllerId())) { - return true; - } - Player player = game.getPlayer(event.getSourceId()); - if (player != null && player.getId().equals(source.getControllerId())) { - return true; - } - StackObject spell = game.getStack().getStackObject(event.getSourceId()); - if (spell != null && spell.getControllerId().equals(source.getControllerId())) { - return true; - } - return false; - } - - @Override - public boolean apply(Game game, Ability source) { - return true; + return source.getControllerId().equals(game.getControllerId(event.getSourceId())); } @Override diff --git a/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/DeflectingPalmTest.java b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/DeflectingPalmTest.java new file mode 100644 index 00000000000..7a18095eb14 --- /dev/null +++ b/Mage.Tests/src/test/java/org/mage/test/cards/abilities/oneshot/damage/DeflectingPalmTest.java @@ -0,0 +1,80 @@ +/* + * 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.abilities.oneshot.damage; + +import mage.constants.PhaseStep; +import mage.constants.Zone; +import org.junit.Test; +import org.mage.test.serverside.base.CardTestPlayerBase; + +/** + * + * @author LevelX2 + */ +public class DeflectingPalmTest extends CardTestPlayerBase { + + /** + * Test that prevented damage will be created with the correct source and + * will trigger the ability of Satyr Firedance + * https://github.com/magefree/mage/issues/804 + */ + + @Test + public void testDamageInPlayer() { + addCard(Zone.BATTLEFIELD, playerA, "Mountain"); + addCard(Zone.BATTLEFIELD, playerA, "Plains"); + // The next time a source of your choice would deal damage to you this turn, prevent that damage. + // If damage is prevented this way, Deflecting Palm deals that much damage to that source's controller. + addCard(Zone.HAND, playerA, "Deflecting Palm"); + // Whenever an instant or sorcery spell you control deals damage to an opponent, Satyr Firedancer deals + // that much damage to target creature that player controls. + addCard(Zone.BATTLEFIELD, playerA, "Satyr Firedancer"); + + addCard(Zone.BATTLEFIELD, playerB, "Silvercoat Lion"); + addCard(Zone.BATTLEFIELD, playerB, "Mountain"); + addCard(Zone.HAND, playerB, "Lightning Bolt"); + + + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerB ,"Lightning Bolt", playerA); + castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA ,"Deflecting Palm", null, "Lightning Bolt"); + setChoice(playerA, "Lightning Bolt"); + addTarget(playerA, "Silvercoat Lion"); // target for Satyr Firedancer + + setStopAt(1, PhaseStep.BEGIN_COMBAT); + execute(); + + assertGraveyardCount(playerA, "Deflecting Palm", 1); + assertGraveyardCount(playerB, "Lightning Bolt", 1); + + + assertGraveyardCount(playerB, "Silvercoat Lion", 1); + + assertLife(playerA, 20); + assertLife(playerB, 17); + } +} \ No newline at end of file diff --git a/Mage/src/mage/abilities/effects/ContinuousEffects.java b/Mage/src/mage/abilities/effects/ContinuousEffects.java index c7426d4181a..7b2f8722caf 100644 --- a/Mage/src/mage/abilities/effects/ContinuousEffects.java +++ b/Mage/src/mage/abilities/effects/ContinuousEffects.java @@ -1099,6 +1099,37 @@ public class ContinuousEffects implements Serializable { public boolean existRequirementEffects() { return !requirementEffects.isEmpty(); } + + public UUID getControllerOfSourceId(UUID sourceId) { + UUID controllerFound = null; + for (PreventionEffect effect: preventionEffects) { + HashSet abilities = preventionEffects.getAbility(effect.getId()); + for (Ability ability : abilities) { + if (ability.getSourceId().equals(sourceId)) { + if (controllerFound == null || controllerFound == ability.getControllerId()) { + controllerFound = ability.getControllerId(); + } else { + // not unique controller - No solution yet + return null; + } + } + } + } + for (ReplacementEffect effect: replacementEffects) { + HashSet abilities = replacementEffects.getAbility(effect.getId()); + for (Ability ability : abilities) { + if (ability.getSourceId().equals(sourceId)) { + if (controllerFound == null || controllerFound == ability.getControllerId()) { + controllerFound = ability.getControllerId(); + } else { + // not unique controller - No solution yet + return null; + } + } + } + } + return controllerFound; + } } class ContinuousEffectSorter implements Comparator { diff --git a/Mage/src/mage/game/Game.java b/Mage/src/mage/game/Game.java index 0d59775657a..817c65571c4 100644 --- a/Mage/src/mage/game/Game.java +++ b/Mage/src/mage/game/Game.java @@ -293,4 +293,5 @@ public interface Game extends MageItem, Serializable { int getPriorityTime(); void setPriorityTime(int priorityTime); UUID getStartingPlayerId(); + } diff --git a/Mage/src/mage/game/GameImpl.java b/Mage/src/mage/game/GameImpl.java index 3e7d9a252fe..1c3275e7e2d 100644 --- a/Mage/src/mage/game/GameImpl.java +++ b/Mage/src/mage/game/GameImpl.java @@ -382,9 +382,23 @@ public abstract class GameImpl implements Game, Serializable { } MageObject object = getObject(objectId); if (object != null) { - if (object instanceof Permanent) { + if (object instanceof StackObject) { + return ((StackObject)object).getControllerId(); + } else if (object instanceof Permanent) { return ((Permanent)object).getControllerId(); + } else if (object instanceof CommandObject) { + return ((CommandObject)object).getControllerId(); + } + UUID controllerId = getContinuousEffects().getControllerOfSourceId(objectId); + if (controllerId != null) { + return controllerId; } + // TODO: When is a player the damage source itself? If not possible remove this + Player player = getPlayer(objectId); + if (player != null){ + return player.getId(); + } + // No object with controller found so return owner if possible if (object instanceof Card) { return ((Card)object).getOwnerId(); } @@ -2500,4 +2514,6 @@ public abstract class GameImpl implements Game, Serializable { } } + + } diff --git a/Mage/src/mage/game/events/GameEvent.java b/Mage/src/mage/game/events/GameEvent.java index 06838a6e656..662d13af589 100644 --- a/Mage/src/mage/game/events/GameEvent.java +++ b/Mage/src/mage/game/events/GameEvent.java @@ -93,7 +93,17 @@ public class GameEvent { DISCARDED_CARD, CYCLE_CARD, CYCLED_CARD, CLASH, CLASHED, - DAMAGE_PLAYER, DAMAGED_PLAYER, + DAMAGE_PLAYER, + + /* DAMAGED_PLAYER + targetId the id of the damged player + sourceId sourceId of the ability which caused the damage + playerId the id of the damged player + amount amount of damage + flag true = comabat damage - other damage = false + */ + DAMAGED_PLAYER, + DAMAGE_CAUSES_LIFE_LOSS, PLAYER_LIFE_CHANGE, GAIN_LIFE, GAINED_LIFE,