From 5155f9024ee9da45a52e1a46dddaa96da9a41d1f Mon Sep 17 00:00:00 2001 From: Skyler Sell Date: Wed, 27 Jan 2016 20:08:06 -0800 Subject: [PATCH] Issue #1311: Cards with 'another target creature or player' AnotherTargetPredicate: Use MageItem instead of MageObject so it will now also work with Player objects. TargetCreatureOrPlayer: Add constructor specifying a filter object, modify methods to actually use the creature and player filters. Arc Trail and Cone of Flame: Use AnotherTargetPredicate to specify multiple different targets --- .../sets/knightsvsdragons/ConeOfFlame.java | 31 +++++++++++++++--- .../mage/sets/scarsofmirrodin/ArcTrail.java | 25 +++++++++++---- .../mageobject/AnotherTargetPredicate.java | 10 +++--- .../target/common/TargetCreatureOrPlayer.java | 32 +++++++++++-------- 4 files changed, 70 insertions(+), 28 deletions(-) diff --git a/Mage.Sets/src/mage/sets/knightsvsdragons/ConeOfFlame.java b/Mage.Sets/src/mage/sets/knightsvsdragons/ConeOfFlame.java index 297d39ca49..dead6e6d14 100644 --- a/Mage.Sets/src/mage/sets/knightsvsdragons/ConeOfFlame.java +++ b/Mage.Sets/src/mage/sets/knightsvsdragons/ConeOfFlame.java @@ -34,9 +34,12 @@ import mage.cards.CardImpl; import mage.constants.CardType; import mage.constants.Outcome; import mage.constants.Rarity; +import mage.filter.common.FilterCreatureOrPlayer; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; +import mage.target.Target; import mage.target.common.TargetCreatureOrPlayer; /** @@ -51,8 +54,28 @@ public class ConeOfFlame extends CardImpl { // Cone of Flame deals 1 damage to target creature or player, 2 damage to another target creature or player, and 3 damage to a third target creature or player. + FilterCreatureOrPlayer filter1 = new FilterCreatureOrPlayer("creature or player to deal 1 damage"); + TargetCreatureOrPlayer target1 = new TargetCreatureOrPlayer(1, 1, filter1); + target1.setTargetTag(1); + this.getSpellAbility().addTarget(target1); + + FilterCreatureOrPlayer filter2 = new FilterCreatureOrPlayer("another creature or player to deal 2 damage"); + AnotherTargetPredicate predicate2 = new AnotherTargetPredicate(2); + filter2.getCreatureFilter().add(predicate2); + filter2.getPlayerFilter().add(predicate2); + TargetCreatureOrPlayer target2 = new TargetCreatureOrPlayer(1, 1, filter2); + target2.setTargetTag(2); + this.getSpellAbility().addTarget(target2); + + FilterCreatureOrPlayer filter3 = new FilterCreatureOrPlayer("another creature or player to deal 3 damage"); + AnotherTargetPredicate predicate3 = new AnotherTargetPredicate(3); + filter3.getCreatureFilter().add(predicate3); + filter3.getPlayerFilter().add(predicate3); + TargetCreatureOrPlayer target3 = new TargetCreatureOrPlayer(1, 1, filter3); + target3.setTargetTag(3); + this.getSpellAbility().addTarget(target3); + this.getSpellAbility().addEffect(new ConeOfFlameEffect()); - this.getSpellAbility().addTarget(new TargetCreatureOrPlayer(3)); } public ConeOfFlame(final ConeOfFlame card) { @@ -85,12 +108,12 @@ class ConeOfFlameEffect extends OneShotEffect { public boolean apply(Game game, Ability source) { boolean applied = false; int damage = 1; - for (UUID targetId : targetPointer.getTargets(game, source)) { - Permanent permanent = game.getPermanent(targetId); + for (Target target : source.getTargets()) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); if (permanent != null) { applied |= (permanent.damage(damage, source.getSourceId(), game, false, true) > 0); } - Player player = game.getPlayer(targetId); + Player player = game.getPlayer(target.getFirstTarget()); if (player != null) { applied |= (player.damage(damage, source.getSourceId(), game, false, true) > 0); } diff --git a/Mage.Sets/src/mage/sets/scarsofmirrodin/ArcTrail.java b/Mage.Sets/src/mage/sets/scarsofmirrodin/ArcTrail.java index 46d94237c8..34972d34ee 100644 --- a/Mage.Sets/src/mage/sets/scarsofmirrodin/ArcTrail.java +++ b/Mage.Sets/src/mage/sets/scarsofmirrodin/ArcTrail.java @@ -37,6 +37,8 @@ import mage.abilities.Ability; import mage.abilities.effects.Effect; import mage.abilities.effects.OneShotEffect; import mage.cards.CardImpl; +import mage.filter.common.FilterCreatureOrPlayer; +import mage.filter.predicate.mageobject.AnotherTargetPredicate; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -53,9 +55,20 @@ public class ArcTrail extends CardImpl { super(ownerId, 81, "Arc Trail", Rarity.UNCOMMON, new CardType[] { CardType.SORCERY }, "{1}{R}"); this.expansionSetCode = "SOM"; - - Target target = new TargetCreatureOrPlayer(2); - this.getSpellAbility().addTarget(target); + // Arc Trail deals 2 damage to target creature or player and 1 damage to another target creature or player + FilterCreatureOrPlayer filter1 = new FilterCreatureOrPlayer("creature or player to deal 2 damage"); + TargetCreatureOrPlayer target1 = new TargetCreatureOrPlayer(1, 1, filter1); + target1.setTargetTag(1); + this.getSpellAbility().addTarget(target1); + + FilterCreatureOrPlayer filter2 = new FilterCreatureOrPlayer("another creature or player to deal 1 damage"); + AnotherTargetPredicate predicate = new AnotherTargetPredicate(2); + filter2.getCreatureFilter().add(predicate); + filter2.getPlayerFilter().add(predicate); + TargetCreatureOrPlayer target2 = new TargetCreatureOrPlayer(1, 1, filter2); + target2.setTargetTag(2); + this.getSpellAbility().addTarget(target2); + this.getSpellAbility().addEffect(ArcTrailEffect.getInstance()); } @@ -94,8 +107,8 @@ class ArcTrailEffect extends OneShotEffect { boolean twoDamageDone = false; int damage = 2; - for ( UUID target : targetPointer.getTargets(game, source) ) { - Permanent permanent = game.getPermanent(target); + for ( Target target : source.getTargets() ) { + Permanent permanent = game.getPermanent(target.getFirstTarget()); if ( twoDamageDone ) { damage = 1; @@ -104,7 +117,7 @@ class ArcTrailEffect extends OneShotEffect { if (permanent != null) { applied |= (permanent.damage( damage, source.getSourceId(), game, false, true ) > 0); } - Player player = game.getPlayer(target); + Player player = game.getPlayer(target.getFirstTarget()); if (player != null) { applied |= (player.damage( damage, source.getSourceId(), game, false, true ) > 0); } diff --git a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java index cd906f4a2a..bb40275367 100644 --- a/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java +++ b/Mage/src/main/java/mage/filter/predicate/mageobject/AnotherTargetPredicate.java @@ -27,7 +27,7 @@ */ package mage.filter.predicate.mageobject; -import mage.MageObject; +import mage.MageItem; import mage.filter.predicate.ObjectSourcePlayer; import mage.filter.predicate.ObjectSourcePlayerPredicate; import mage.game.Game; @@ -42,7 +42,7 @@ import mage.target.Target; * * @author LevelX2 */ -public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate> { +public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate> { private final int targetTag; @@ -51,14 +51,14 @@ public class AnotherTargetPredicate implements ObjectSourcePlayerPredicate input, Game game) { + public boolean apply(ObjectSourcePlayer input, Game game) { StackObject source = game.getStack().getStackObject(input.getSourceId()); if (source != null) { for (Target target : source.getStackAbility().getTargets()) { if (target.getTargetTag() > 0 // target is included in the target group to check && target.getTargetTag() != targetTag // it's not the target of this predicate - && target.getTargets().contains(input.getObject().getId())) { // if the uuid already is used for another target in the group it's no allowed here - return false; + && target.getTargets().contains(input.getObject().getId())) { // if the uuid already is used for another target in the group it's not allowed here + return false; } } } diff --git a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java index eef898e4dd..842c34c85e 100644 --- a/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java +++ b/Mage/src/main/java/mage/target/common/TargetCreatureOrPlayer.java @@ -33,7 +33,6 @@ import mage.MageObject; import mage.abilities.Ability; import mage.filter.Filter; import mage.filter.common.FilterCreatureOrPlayer; -import mage.filter.common.FilterCreaturePermanent; import mage.game.Game; import mage.game.permanent.Permanent; import mage.players.Player; @@ -52,18 +51,22 @@ public class TargetCreatureOrPlayer extends TargetImpl { protected FilterCreatureOrPlayer filter; public TargetCreatureOrPlayer() { - this(1, 1); + this(1, 1, new FilterCreatureOrPlayer()); } public TargetCreatureOrPlayer(int numTargets) { - this(numTargets, numTargets); + this(numTargets, numTargets, new FilterCreatureOrPlayer()); + } + + public TargetCreatureOrPlayer(int numTargets, int maxNumTargets) { + this(numTargets, maxNumTargets, new FilterCreatureOrPlayer()); } - public TargetCreatureOrPlayer(int minNumTargets, int maxNumTargets) { + public TargetCreatureOrPlayer(int minNumTargets, int maxNumTargets, FilterCreatureOrPlayer filter) { this.minNumberOfTargets = minNumTargets; this.maxNumberOfTargets = maxNumTargets; this.zone = Zone.ALL; - this.filter = new FilterCreatureOrPlayer(); + this.filter = filter; this.targetName = filter.getMessage(); } @@ -141,7 +144,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { } } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { @@ -172,7 +175,7 @@ public class TargetCreatureOrPlayer extends TargetImpl { } } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { if (filter.match(permanent, null, sourceControllerId, game)) { count++; if (count >= this.minNumberOfTargets) { @@ -189,12 +192,15 @@ public class TargetCreatureOrPlayer extends TargetImpl { MageObject targetSource = game.getObject(sourceId); for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); - if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) { + if (player != null + && player.canBeTargetedBy(targetSource, sourceControllerId, game) + && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) { possibleTargets.add(playerId); } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { - if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) + && filter.getCreatureFilter().match(permanent, sourceId, sourceControllerId, game)) { possibleTargets.add(permanent.getId()); } } @@ -206,12 +212,12 @@ public class TargetCreatureOrPlayer extends TargetImpl { Set possibleTargets = new HashSet<>(); for (UUID playerId: game.getPlayer(sourceControllerId).getInRange()) { Player player = game.getPlayer(playerId); - if (player != null && filter.match(player, game)) { + if (player != null && filter.getPlayerFilter().match(player, game)) { possibleTargets.add(playerId); } } - for (Permanent permanent: game.getBattlefield().getActivePermanents(new FilterCreaturePermanent(), sourceControllerId, game)) { - if (filter.match(permanent, null, sourceControllerId, game)) { + for (Permanent permanent: game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { + if (filter.getCreatureFilter().match(permanent, null, sourceControllerId, game)) { possibleTargets.add(permanent.getId()); } }