From 4c2d2cf5377cef54aef56dd2c57f818a60a85898 Mon Sep 17 00:00:00 2001 From: Evan Kranzler Date: Thu, 19 Apr 2018 16:59:38 -0400 Subject: [PATCH] added TargetOpponentOrPlaneswalker and FilterOpponentOrPlaneswalker --- .../mage/cards/a/AngrathMinotaurPirate.java | 7 +- .../common/FilterOpponentOrPlaneswalker.java | 85 +++++++ .../common/TargetOpponentOrPlaneswalker.java | 221 ++++++++++++++++++ 3 files changed, 311 insertions(+), 2 deletions(-) create mode 100644 Mage/src/main/java/mage/filter/common/FilterOpponentOrPlaneswalker.java create mode 100644 Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java diff --git a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java index e685f257608..c916f562443 100644 --- a/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java +++ b/Mage.Sets/src/mage/cards/a/AngrathMinotaurPirate.java @@ -52,6 +52,7 @@ import mage.game.permanent.Permanent; import mage.players.Player; import mage.target.common.TargetCardInYourGraveyard; import mage.target.common.TargetOpponent; +import mage.target.common.TargetOpponentOrPlaneswalker; /** * @@ -69,9 +70,11 @@ public class AngrathMinotaurPirate extends CardImpl { // +2: Angrath, Minotaur Pirate deals 1 damage to target opponent and each creature that player controls. Effects effects1 = new Effects(); effects1.add(new DamageTargetEffect(1)); - effects1.add(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()).setText("and each creature that player controls")); + effects1.add(new DamageAllControlledTargetEffect(1, new FilterCreaturePermanent()) + .setText("and each creature that player or that planeswalker’s controller controls") + ); LoyaltyAbility ability1 = new LoyaltyAbility(effects1, +2); - ability1.addTarget(new TargetOpponent()); + ability1.addTarget(new TargetOpponentOrPlaneswalker()); this.addAbility(ability1); // -3: Return target Pirate card from your graveyard to the battlefield. diff --git a/Mage/src/main/java/mage/filter/common/FilterOpponentOrPlaneswalker.java b/Mage/src/main/java/mage/filter/common/FilterOpponentOrPlaneswalker.java new file mode 100644 index 00000000000..36d93524405 --- /dev/null +++ b/Mage/src/main/java/mage/filter/common/FilterOpponentOrPlaneswalker.java @@ -0,0 +1,85 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.filter.common; + +import java.util.UUID; +import mage.MageItem; +import mage.filter.FilterImpl; +import mage.filter.FilterInPlay; +import mage.filter.FilterOpponent; +import mage.filter.FilterPlayer; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; + +/** + * + * @author LevelX2 + */ +public class FilterOpponentOrPlaneswalker extends FilterImpl implements FilterInPlay { + + protected FilterPlaneswalkerPermanent planeswalkerFilter; + protected final FilterPlayer playerFilter; + + public FilterOpponentOrPlaneswalker() { + this("opponent or planeswalker"); + } + + public FilterOpponentOrPlaneswalker(String name) { + super(name); + planeswalkerFilter = new FilterPlaneswalkerPermanent(); + playerFilter = new FilterOpponent(); + } + + public FilterOpponentOrPlaneswalker(final FilterOpponentOrPlaneswalker filter) { + super(filter); + this.planeswalkerFilter = filter.planeswalkerFilter.copy(); + this.playerFilter = filter.playerFilter.copy(); + } + + @Override + public boolean checkObjectClass(Object object) { + return true; + } + + @Override + public boolean match(MageItem o, Game game) { + if (o instanceof Player) { + return playerFilter.match((Player) o, game); + } else if (o instanceof Permanent) { + return planeswalkerFilter.match((Permanent) o, game); + } + return false; + } + + @Override + public boolean match(MageItem o, UUID sourceId, UUID playerId, Game game) { + if (o instanceof Player) { + return playerFilter.match((Player) o, sourceId, playerId, game); + } else if (o instanceof Permanent) { + return planeswalkerFilter.match((Permanent) o, sourceId, playerId, game); + } + return false; + } + + public FilterPlaneswalkerPermanent getPlaneswalkerFilter() { + return this.planeswalkerFilter; + } + + public FilterPlayer getPlayerFilter() { + return this.playerFilter; + } + + public void setPlaneswalkerFilter(FilterPlaneswalkerPermanent planeswalkerFilter) { + this.planeswalkerFilter = planeswalkerFilter; + } + + @Override + public FilterOpponentOrPlaneswalker copy() { + return new FilterOpponentOrPlaneswalker(this); + } + +} diff --git a/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java new file mode 100644 index 00000000000..9dbb6b721fc --- /dev/null +++ b/Mage/src/main/java/mage/target/common/TargetOpponentOrPlaneswalker.java @@ -0,0 +1,221 @@ +/* + * To change this license header, choose License Headers in Project Properties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ +package mage.target.common; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import mage.MageObject; +import mage.abilities.Ability; +import mage.constants.Zone; +import mage.filter.Filter; +import mage.filter.common.FilterOpponentOrPlaneswalker; +import mage.game.Game; +import mage.game.permanent.Permanent; +import mage.players.Player; +import mage.target.TargetImpl; + +/** + * + * @author LevelX2 + */ +public class TargetOpponentOrPlaneswalker extends TargetImpl { + + protected FilterOpponentOrPlaneswalker filter; + + public TargetOpponentOrPlaneswalker() { + this(1, 1, new FilterOpponentOrPlaneswalker()); + } + + public TargetOpponentOrPlaneswalker(int numTargets) { + this(numTargets, numTargets, new FilterOpponentOrPlaneswalker()); + } + + public TargetOpponentOrPlaneswalker(FilterOpponentOrPlaneswalker filter) { + this(1, 1, filter); + } + + public TargetOpponentOrPlaneswalker(int minNumTargets, int maxNumTargets, FilterOpponentOrPlaneswalker filter) { + this.minNumberOfTargets = minNumTargets; + this.maxNumberOfTargets = maxNumTargets; + this.zone = Zone.ALL; + this.filter = filter; + this.targetName = filter.getMessage(); + } + + public TargetOpponentOrPlaneswalker(final TargetOpponentOrPlaneswalker target) { + super(target); + this.filter = target.filter.copy(); + } + + @Override + public Filter getFilter() { + return this.filter; + } + + @Override + public boolean canTarget(UUID id, Game game) { + Permanent permanent = game.getPermanent(id); + if (permanent != null) { + return filter.match(permanent, game); + } + Player player = game.getPlayer(id); + return player != null && filter.match(player, game); + } + + @Override + public boolean canTarget(UUID id, Ability source, Game game) { + return canTarget(source.getControllerId(), id, source, game); + } + + @Override + public boolean canTarget(UUID controllerId, UUID id, Ability source, Game game) { + Permanent permanent = game.getPermanent(id); + Player player = game.getPlayer(id); + + if (source != null) { + MageObject targetSource = game.getObject(source.getSourceId()); + if (permanent != null) { + return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(permanent, source.getSourceId(), source.getControllerId(), game); + } + if (player != null) { + return player.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(player, game); + } + } + + if (permanent != null) { + return filter.match(permanent, game); + } + return player != null && filter.match(player, game); + } + + /** + * Checks if there are enough {@link Permanent} or {@link Player} that can + * be chosen. Should only be used for Ability targets since this checks for + * protection, shroud etc. + * + * @param sourceId - the target event source + * @param sourceControllerId - controller of the target event source + * @param game + * @return - true if enough valid {@link Permanent} or {@link Player} exist + */ + @Override + public boolean canChoose(UUID sourceId, UUID sourceControllerId, Game game) { + int count = 0; + MageObject targetSource = game.getObject(sourceId); + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) { + if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + return false; + } + + /** + * Checks if there are enough {@link Permanent} or {@link Player} that can + * be selected. Should not be used for Ability targets since this does not + * check for protection, shroud etc. + * + * @param sourceControllerId - controller of the select event + * @param game + * @return - true if enough valid {@link Permanent} or {@link Player} exist + */ + @Override + public boolean canChoose(UUID sourceControllerId, Game game) { + int count = 0; + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null && filter.match(player, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) { + if (filter.match(permanent, null, sourceControllerId, game)) { + count++; + if (count >= this.minNumberOfTargets) { + return true; + } + } + } + return false; + } + + @Override + public Set possibleTargets(UUID sourceId, UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + MageObject targetSource = game.getObject(sourceId); + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null + && player.canBeTargetedBy(targetSource, sourceControllerId, game) + && filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) { + possibleTargets.add(playerId); + } + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) { + if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) + && filter.getPlaneswalkerFilter().match(permanent, sourceId, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + + @Override + public Set possibleTargets(UUID sourceControllerId, Game game) { + Set possibleTargets = new HashSet<>(); + for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { + Player player = game.getPlayer(playerId); + if (player != null && filter.getPlayerFilter().match(player, game)) { + possibleTargets.add(playerId); + } + } + for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) { + if (filter.getPlaneswalkerFilter().match(permanent, null, sourceControllerId, game)) { + possibleTargets.add(permanent.getId()); + } + } + return possibleTargets; + } + + @Override + public String getTargetedName(Game game) { + StringBuilder sb = new StringBuilder(); + for (UUID targetId : getTargets()) { + Permanent permanent = game.getPermanent(targetId); + if (permanent != null) { + sb.append(permanent.getLogName()).append(' '); + } else { + Player player = game.getPlayer(targetId); + if (player != null) { + sb.append(player.getLogName()).append(' '); + } + } + } + return sb.toString(); + } + + @Override + public TargetOpponentOrPlaneswalker copy() { + return new TargetOpponentOrPlaneswalker(this); + } + +}