diff --git a/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java b/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java index 5861cc4a01a..b406d81ff73 100644 --- a/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java +++ b/Mage.Sets/src/mage/sets/futuresight/VeilstoneAmulet.java @@ -28,12 +28,9 @@ package mage.sets.futuresight; import java.util.UUID; - import mage.cards.CardImpl; import mage.constants.Rarity; import mage.constants.CardType; - - import mage.abilities.common.SpellCastControllerTriggeredAbility; import mage.filter.FilterSpell; import mage.abilities.effects.ContinuousRuleModifiyingEffectImpl; @@ -55,10 +52,7 @@ public class VeilstoneAmulet extends CardImpl { this.expansionSetCode = "FUT"; // Whenever you cast a spell, creatures you control can't be the targets of spells or abilities your opponents control this turn. - this.addAbility(new SpellCastControllerTriggeredAbility(new VeilstoneAmuletEffect(), - new FilterSpell(), - false, - "Whenever you cast a spell, creatures you control can't be the targets of spells or abilities your opponents control this turn.")); + this.addAbility(new SpellCastControllerTriggeredAbility(new VeilstoneAmuletEffect(), new FilterSpell("a spell"), false)); } public VeilstoneAmulet(final VeilstoneAmulet card) { @@ -78,6 +72,7 @@ class VeilstoneAmuletEffect extends ContinuousRuleModifiyingEffectImpl { public VeilstoneAmuletEffect() { super(Duration.EndOfTurn, Outcome.Benefit); + staticText = "creatures you control can't be the targets of spells or abilities your opponents control this turn"; } public VeilstoneAmuletEffect(final VeilstoneAmuletEffect effect) { @@ -99,12 +94,9 @@ class VeilstoneAmuletEffect extends ContinuousRuleModifiyingEffectImpl { if (event.getType() == EventType.TARGET) { Permanent permanent = game.getPermanent(event.getTargetId()); if (permanent != null) { - UUID permanentController = permanent.getControllerId(); - UUID abilityController = ability.getControllerId(); - UUID sourceController = event.getPlayerId(); if (permanent.getCardType().contains(CardType.CREATURE) && - permanentController.equals(abilityController) && - game.getPlayer(abilityController).hasOpponent(sourceController, game)) { + permanent.getControllerId().equals(ability.getControllerId()) && + game.getPlayer(ability.getControllerId()).hasOpponent(event.getPlayerId(), game)) { return true; } } diff --git a/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java b/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java index 74b60c53590..b086a567d7f 100644 --- a/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java +++ b/Mage.Sets/src/mage/sets/guildpact/InkTreaderNephilim.java @@ -35,7 +35,6 @@ import mage.constants.CardType; import mage.constants.Rarity; import mage.MageInt; import mage.cards.CardImpl; - import mage.abilities.Ability; import mage.abilities.SpellAbility; import mage.abilities.TriggeredAbilityImpl; @@ -56,6 +55,7 @@ import java.util.List; import mage.target.Target; import mage.abilities.Modes; import mage.filter.predicate.mageobject.FromSetPredicate; +import mage.players.Player; import mage.target.TargetPermanent; import mage.util.SpellTargetAddress; @@ -68,6 +68,7 @@ public class InkTreaderNephilim extends CardImpl { super(ownerId, 117, "Ink-Treader Nephilim", Rarity.RARE, new CardType[]{CardType.CREATURE}, "{R}{G}{W}{U}"); this.expansionSetCode = "GPT"; this.subtype.add("Nephilim"); + this.power = new MageInt(3); this.toughness = new MageInt(3); @@ -113,7 +114,7 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { if (event.getType() == GameEvent.EventType.SPELL_CAST) { Spell spell = game.getStack().getSpell(event.getTargetId()); if (spell != null && - spell.getCardType().contains(CardType.INSTANT) || spell.getCardType().contains(CardType.SORCERY)){ + (spell.getCardType().contains(CardType.INSTANT) || spell.getCardType().contains(CardType.SORCERY))){ for (Effect effect : getEffects()) { effect.setValue("TriggeringSpell", spell); } @@ -129,10 +130,10 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { if (spell != null) { boolean allTargetsInkTreaderNephilim = true; boolean atLeastOneTargetsInkTreaderNephilim = false; - for (SpellAbility sa: spell.getSpellAbilities()){ - Modes modes = sa.getModes(); - for (UUID mode : modes.getSelectedModes()) { - for (Target targetInstance : modes.get(mode).getTargets()) { + for (SpellAbility spellAbility: spell.getSpellAbilities()){ + Modes modesSpell = spellAbility.getModes(); + for (UUID mode : modesSpell.getSelectedModes()) { + for (Target targetInstance : modesSpell.get(mode).getTargets()) { for (UUID target : targetInstance.getTargets()) { allTargetsInkTreaderNephilim &= target.equals(sourceId); atLeastOneTargetsInkTreaderNephilim |= target.equals(sourceId); @@ -149,7 +150,7 @@ class InkTreaderNephilimTriggeredAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "Whenever a player casts an instant or sorcery spell, if that spell targets only Ink-Treader Nephilim, copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures."; + return "Whenever a player casts an instant or sorcery spell, if that spell targets only {this}, copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures."; } } @@ -163,6 +164,7 @@ class InkTreaderNephilimEffect extends OneShotEffect { public InkTreaderNephilimEffect() { super(Outcome.Copy); + staticText = "copy the spell for each other creature that spell could target. Each copy targets a different one of those creatures"; } public InkTreaderNephilimEffect(final InkTreaderNephilimEffect effect) { @@ -171,13 +173,17 @@ class InkTreaderNephilimEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { + Player controller = game.getPlayer(source.getControllerId()); + if (controller == null) { + return false; + } Spell spell = (Spell) getValue("TriggeringSpell"); if (spell != null) { Map targetable = new HashMap<>(); - UUID controller = source.getControllerId(); - for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller, source.getSourceId(), game)) { + // gather all creatures that can be targeted from the spell to copy + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, controller.getId(), source.getSourceId(), game)) { Spell copy = spell.copySpell(); - copy.setControllerId(controller); + copy.setControllerId(controller.getId()); copy.setCopiedSpell(true); if (permanent.getId().equals(source.getSourceId())) { continue; // copy only for other creatures @@ -200,28 +206,29 @@ class InkTreaderNephilimEffect extends OneShotEffect { targetable.put(permanent.getId(), copy); } } + // controller while (targetable.size() > 0) { - FilterPermanent filter = new FilterPermanent("creature that spell could target ("+targetable.size()+" remaining)"); - filter.add(new FromSetPredicate(targetable.keySet())); - TargetPermanent target = new TargetPermanent(0, 1, filter, true); - if (target.possibleTargets(controller, game).size() > 1 - && target.canChoose(source.getSourceId(), controller, game)) { - game.getPlayer(controller).choose(Outcome.Neutral, target, source.getId(), game); + FilterPermanent filterCreatures = new FilterPermanent("creature that spell could target ("+ targetable.size() + " remaining)"); + filterCreatures.add(new FromSetPredicate(targetable.keySet())); + TargetPermanent target = new TargetPermanent(0, 1, filterCreatures, true); + if (target.possibleTargets(controller.getId(), game).size() > 1 + && target.canChoose(source.getSourceId(), controller.getId(), game)) { + controller.choose(Outcome.Neutral, target, source.getId(), game); } - Collection chosen = target.getTargets(); - if (chosen.size() == 0) { - chosen = targetable.keySet(); + Collection choosenIds = target.getTargets(); + if (choosenIds.isEmpty()) { + choosenIds = targetable.keySet(); } List toDelete = new ArrayList<>(); - for (UUID chosenId : chosen) { + for (UUID chosenId : choosenIds) { Spell chosenCopy = targetable.get(chosenId); if (chosenCopy != null) { game.getStack().push(chosenCopy); toDelete.add(chosenId); } } - for (UUID id : toDelete) { - targetable.remove(id); + for (UUID idToDelte : toDelete) { + targetable.remove(idToDelte); } } return true; diff --git a/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java b/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java index 475b4ec40c8..341e361df3f 100644 --- a/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java +++ b/Mage.Sets/src/mage/sets/ravnika/BreathOfFury.java @@ -28,18 +28,15 @@ package mage.sets.ravnika; import java.util.UUID; - import mage.cards.CardImpl; import mage.constants.Rarity; import mage.constants.CardType; - import mage.target.TargetPermanent; import mage.target.common.TargetControlledCreaturePermanent; import mage.abilities.effects.common.AttachEffect; import mage.constants.Outcome; import mage.abilities.Ability; import mage.abilities.keyword.EnchantAbility; - import mage.abilities.TriggeredAbilityImpl; import mage.constants.Zone; import mage.game.events.GameEvent; @@ -47,8 +44,6 @@ import mage.game.Game; import mage.game.events.DamagedPlayerEvent; import mage.abilities.effects.OneShotEffect; import mage.game.permanent.Permanent; -import mage.abilities.effects.Effect; -import mage.target.targetpointer.FixedTarget; import mage.players.Player; import mage.target.Target; import mage.filter.common.FilterControlledCreaturePermanent; @@ -105,12 +100,11 @@ class BreathOfFuryAbility extends TriggeredAbilityImpl { @Override public boolean checkTrigger(GameEvent event, Game game) { if (event instanceof DamagedPlayerEvent) { - DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; - Permanent p = game.getPermanent(event.getSourceId()); - if (damageEvent.isCombatDamage() && p != null && p.getAttachments().contains(this.getSourceId())) { - for (Effect effect : getEffects()) { - effect.setTargetPointer(new FixedTarget(p.getId())); - } + DamagedPlayerEvent damageEvent = (DamagedPlayerEvent)event; + Permanent enchantment = game.getPermanent(getSourceId()); + if (damageEvent.isCombatDamage() && + enchantment != null && + enchantment.getAttachedTo().equals(event.getSourceId())) { return true; } } @@ -119,7 +113,7 @@ class BreathOfFuryAbility extends TriggeredAbilityImpl { @Override public String getRule() { - return "When enchanted creature deals combat damage to a player, sacrifice it and attach Breath of Fury to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; + return "When enchanted creature deals combat damage to a player, " + super.getRule(); } } @@ -127,7 +121,7 @@ class BreathOfFuryEffect extends OneShotEffect { public BreathOfFuryEffect() { super(Outcome.Benefit); - staticText = "Sacrifice enchanted creature and attach Breath of Fury to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; + staticText = "sacrifice enchanted creature and attach {this} to a creature you control. If you do, untap all creatures you control and after this phase, there is an additional combat phase."; } public BreathOfFuryEffect(final BreathOfFuryEffect effect) { @@ -141,52 +135,39 @@ class BreathOfFuryEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source){ - Permanent enchantedCreature = game.getPermanent(targetPointer.getFirst(game, source)); Permanent enchantment = game.getPermanent(source.getSourceId()); + if (enchantment == null) { + return false; + } + Permanent enchantedCreature = game.getPermanent(enchantment.getAttachedTo()); Player controller = game.getPlayer(source.getControllerId()); - Target target = new TargetControlledCreaturePermanent(new FilterCanBeEnchantedControlledCreaturePermanent(enchantment)); + FilterControlledCreaturePermanent filter = new FilterControlledCreaturePermanent("creature you control that could be enchanted by " + enchantment.getName()); + filter.add(new CanBeEnchantedPredicate(enchantment)); + Target target = new TargetControlledCreaturePermanent(filter); target.setNotTarget(true); - if (enchantedCreature != null && - enchantedCreature.sacrifice(source.getSourceId(), game) && - enchantment != null && - controller != null && - target.canChoose(source.getSourceId(), source.getControllerId(), game)) { - controller.choose(outcome, target, source.getId(), game); - Permanent newCreature = game.getPermanent(target.getFirstTarget()); - if (newCreature != null && - newCreature.addAttachment(enchantment.getId(), game)) { - for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(), - controller.getId(), game)) { - permanent.untap(game); + if (enchantedCreature != null && controller != null) { + // sacrifice the enchanted creature (don't check return state because controller has sarificed independant if something replaced later); + // e.g. Commander replacement effect going to command zone + enchantedCreature.sacrifice(source.getSourceId(), game); + if (target.canChoose(source.getSourceId(), source.getControllerId(), game)) { + controller.choose(outcome, target, source.getSourceId(), game); + Permanent newCreature = game.getPermanent(target.getFirstTarget()); + if (newCreature != null && + newCreature.addAttachment(enchantment.getId(), game)) { + for (Permanent permanent : game.getBattlefield().getAllActivePermanents(new FilterControlledCreaturePermanent(), controller.getId(), game)) { + permanent.untap(game); + } + game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), TurnPhase.COMBAT, null, false)); + } - game.getState().getTurnMods().add(new TurnMod(source.getControllerId(), TurnPhase.COMBAT, null, false)); - return true; + } + return true; } return false; } } - - -class FilterCanBeEnchantedControlledCreaturePermanent extends FilterControlledCreaturePermanent { - - public FilterCanBeEnchantedControlledCreaturePermanent(final FilterCanBeEnchantedControlledCreaturePermanent filter) { - super(filter); - } - - public FilterCanBeEnchantedControlledCreaturePermanent(MageObject auraEnchantment) { - super("creature you control that could be enchanted by " + auraEnchantment.getName()); - this.add(new CanBeEnchantedPredicate(auraEnchantment)); - } - - @Override - public FilterCanBeEnchantedControlledCreaturePermanent copy() { - return new FilterCanBeEnchantedControlledCreaturePermanent(this); - } -} - - class CanBeEnchantedPredicate implements Predicate { private final MageObject auraEnchantment; diff --git a/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java b/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java index d3a61293479..0773e7f478d 100644 --- a/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java +++ b/Mage.Sets/src/mage/sets/ravnika/RallyTheRighteous.java @@ -29,7 +29,7 @@ package mage.sets.ravnika; import java.util.UUID; - +import mage.MageObjectReference; import mage.constants.CardType; import mage.constants.Rarity; import mage.constants.Outcome; @@ -77,7 +77,7 @@ class RallyTheRighteousUntapEffect extends OneShotEffect { public RallyTheRighteousUntapEffect() { super(Outcome.Untap); - staticText = "Radiance — Untap target creature and each other creature that shares a color with it."; + staticText = "Radiance — Untap target creature and each other creature that shares a color with it"; } public RallyTheRighteousUntapEffect(final RallyTheRighteousUntapEffect effect) { @@ -91,13 +91,13 @@ class RallyTheRighteousUntapEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); + Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { ObjectColor color = target.getColor(); target.untap(game); - for (Permanent p : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - if (p.getColor().shares(color) && !p.getId().equals(target.getId())) { - p.untap(game); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { + if (permanent.getColor().shares(color) && !permanent.getId().equals(target.getId())) { + permanent.untap(game); } } return true; @@ -111,7 +111,7 @@ class RallyTheRighteousBoostEffect extends ContinuousEffectImpl { public RallyTheRighteousBoostEffect() { super(Duration.EndOfTurn, Layer.PTChangingEffects_7, SubLayer.ModifyPT_7c, Outcome.BoostCreature); - staticText = " Those creatures get +2/+0 until end of turn."; + staticText = "Those creatures get +2/+0 until end of turn"; } public RallyTheRighteousBoostEffect(final RallyTheRighteousBoostEffect effect) { @@ -119,19 +119,30 @@ class RallyTheRighteousBoostEffect extends ContinuousEffectImpl { } @Override - public boolean apply(Game game, Ability source) { - Permanent target = game.getPermanent(targetPointer.getFirst(game, source)); + public void init(Ability source, Game game) { + super.init(source, game); + Permanent target = game.getPermanent(getTargetPointer().getFirst(game, source)); if (target != null) { + affectedObjectList.add(new MageObjectReference(target)); ObjectColor color = target.getColor(); target.addPower(2); - for (Permanent p : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), game)) { - if (p.getColor().shares(color) && !p.getId().equals(target.getId())) { - p.addPower(2); + for (Permanent permanent : game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), source.getControllerId(), source.getSourceId(), game)) { + if (!permanent.getId().equals(target.getId()) && permanent.getColor().shares(color)) { + affectedObjectList.add(new MageObjectReference(permanent)); } } - return true; + } + } + + @Override + public boolean apply(Game game, Ability source) { + for(MageObjectReference mageObjectReference :affectedObjectList) { + Permanent permanent = mageObjectReference.getPermanent(game); + if (permanent != null) { + permanent.addPower(2); + } } - return false; + return true; } @Override diff --git a/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java b/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java index f3cedb9033e..572f93919f0 100644 --- a/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java +++ b/Mage.Sets/src/mage/sets/shadowmoor/MercyKilling.java @@ -42,7 +42,6 @@ import mage.game.permanent.Permanent; import mage.constants.Outcome; import mage.game.permanent.token.Token; import mage.MageInt; -import mage.abilities.effects.Effect; /** * @author duncancmt @@ -54,11 +53,9 @@ public class MercyKilling extends CardImpl { this.expansionSetCode = "SHM"; // Target creature's controller sacrifices it, then puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power. - this.getSpellAbility().addTarget(new TargetCreaturePermanent()); - Effect sacEffect = new SacrificeTargetEffect(); - sacEffect.setText("Target creature's controller sacrifices it"); - this.getSpellAbility().addEffect(sacEffect); + this.getSpellAbility().addEffect(new SacrificeTargetEffect("Target creature's controller sacrifices it")); this.getSpellAbility().addEffect(new MercyKillingTokenEffect()); + this.getSpellAbility().addTarget(new TargetCreaturePermanent()); } public MercyKilling(final MercyKilling card) { @@ -75,7 +72,7 @@ class MercyKillingTokenEffect extends OneShotEffect { public MercyKillingTokenEffect() { super(Outcome.PutCreatureInPlay); - staticText = ", then puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power."; + staticText = ", then puts X 1/1 green and white Elf Warrior creature tokens onto the battlefield, where X is that creature's power"; } public MercyKillingTokenEffect(final MercyKillingTokenEffect effect) { @@ -89,13 +86,12 @@ class MercyKillingTokenEffect extends OneShotEffect { @Override public boolean apply(Game game, Ability source) { - Permanent permanent = game.getPermanentOrLKIBattlefield(targetPointer.getFirst(game, source)); + Permanent permanent = game.getPermanentOrLKIBattlefield(getTargetPointer().getFirst(game, source)); if (permanent != null) { int power = permanent.getPower().getValue(); - MercyKillingToken token = new MercyKillingToken(); - token.putOntoBattlefield(power, game, source.getSourceId(), permanent.getControllerId()); + return new MercyKillingToken().putOntoBattlefield(power, game, source.getSourceId(), permanent.getControllerId()); } - return true; + return false; } } diff --git a/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java b/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java index 0c0822e3d20..a106b232937 100644 --- a/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java +++ b/Mage/src/mage/filter/predicate/mageobject/FromSetPredicate.java @@ -29,22 +29,24 @@ package mage.filter.predicate.mageobject; import java.util.Set; import java.util.UUID; -import mage.MageObject; import mage.filter.predicate.ObjectPlayer; import mage.filter.predicate.ObjectPlayerPredicate; +import mage.game.Controllable; import mage.game.Game; /** * @author duncancmt */ -public class FromSetPredicate> implements ObjectPlayerPredicate { +public class FromSetPredicate implements ObjectPlayerPredicate> { + protected Set set; public FromSetPredicate(Set set) { this.set = set; } - public boolean apply(T input, Game game) { + @Override + public boolean apply(ObjectPlayer input, Game game) { return set.contains(input.getObject().getId()); } }