implement [MH3] Volatile Stormdrake ; provide source Ability to canBeTargetedBy and HexproofBaseAbility::checkObject

This commit is contained in:
Susucre 2024-06-06 16:52:53 +02:00
parent 8ec4ffd9de
commit 2d625f0364
49 changed files with 399 additions and 171 deletions

View file

@ -1,7 +1,6 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
@ -14,8 +13,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author LevelX2 * @author LevelX2
*/ */
public final class BlazingHope extends CardImpl { public final class BlazingHope extends CardImpl {
@ -53,8 +53,8 @@ class BlazingHopeTarget extends TargetCreaturePermanent {
Permanent permanent = game.getPermanent(id); Permanent permanent = game.getPermanent(id);
if (permanent != null) { if (permanent != null) {
if (!isNotTarget()) { if (!isNotTarget()) {
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, source, game)
|| !permanent.canBeTargetedBy(game.getObject(source), controllerId, game)) { || !permanent.canBeTargetedBy(game.getObject(source), controllerId, source, game)) {
return false; return false;
} }
} }
@ -75,10 +75,10 @@ class BlazingHopeTarget extends TargetCreaturePermanent {
int count = 0; int count = 0;
Player controller = game.getPlayer(sourceControllerId); Player controller = game.getPlayer(sourceControllerId);
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId())) { if (!targets.containsKey(permanent.getId())) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (controller != null && permanent.getPower().getValue() >= controller.getLife()) { if (controller != null && permanent.getPower().getValue() >= controller.getLife()) {
count++; count++;
if (count >= remainingTargets) { if (count >= remainingTargets) {

View file

@ -1,7 +1,5 @@
package mage.cards.b; package mage.cards.b;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.OneShotEffect; import mage.abilities.effects.OneShotEffect;
@ -20,8 +18,9 @@ import mage.game.permanent.Permanent;
import mage.players.Player; import mage.players.Player;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.UUID;
/** /**
*
* @author Susucr * @author Susucr
*/ */
public final class BreakingOfTheFellowship extends CardImpl { public final class BreakingOfTheFellowship extends CardImpl {
@ -113,7 +112,7 @@ class BreakingOfTheFellowshipFirstTarget extends TargetCreaturePermanent {
int possibleTargets = 0; int possibleTargets = 0;
MageObject sourceObject = game.getObject(source.getId()); MageObject sourceObject = game.getObject(source.getId());
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllingPlayerId, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllingPlayerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, controllerId, game)) { if (permanent.canBeTargetedBy(sourceObject, controllerId, source, game)) {
possibleTargets++; possibleTargets++;
} }
} }
@ -130,7 +129,7 @@ class BreakingOfTheFellowshipFirstTarget extends TargetCreaturePermanent {
int possibleTargets = 0; int possibleTargets = 0;
MageObject sourceObject = game.getObject(source); MageObject sourceObject = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, controllingPlayerId, game)) { if (permanent.canBeTargetedBy(sourceObject, controllingPlayerId, source, game)) {
possibleTargets++; possibleTargets++;
} }
} }

View file

@ -1,11 +1,6 @@
package mage.cards.d; package mage.cards.d;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -13,11 +8,7 @@ import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
import mage.abilities.keyword.InspiredAbility; import mage.abilities.keyword.InspiredAbility;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.SubType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.TargetController;
import mage.filter.predicate.Predicates; import mage.filter.predicate.Predicates;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
@ -25,6 +16,11 @@ import mage.players.Player;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -91,7 +87,7 @@ class TargetControlledPermanentSharingOpponentPermanentCardType extends TargetCo
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
for (CardType type : permanent.getCardType(game)) { for (CardType type : permanent.getCardType(game)) {
if (cardTypes.contains(type)) { if (cardTypes.contains(type)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
@ -160,7 +156,7 @@ class DaringThiefSecondTarget extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (permanent.shareTypes(firstTarget, game)) { if (permanent.shareTypes(firstTarget, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -90,7 +90,7 @@ class GauntletsOfChaosFirstTarget extends TargetControlledPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
for (CardType type : permanent.getCardType(game)) { for (CardType type : permanent.getCardType(game)) {
if (cardTypes.contains(type)) { if (cardTypes.contains(type)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
@ -159,7 +159,7 @@ class GauntletsOfChaosSecondTarget extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (permanent.shareTypes(firstTarget, game)) { if (permanent.shareTypes(firstTarget, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -1,9 +1,6 @@
package mage.cards.g; package mage.cards.g;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -22,6 +19,10 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.watchers.common.PlayerDamagedBySourceWatcher; import mage.watchers.common.PlayerDamagedBySourceWatcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author BetaSteward_at_googlemail.com * @author BetaSteward_at_googlemail.com
*/ */
@ -99,7 +100,7 @@ class GiltspireAvengerTarget extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) {
count++; count++;
if (count >= remainingTargets) { if (count >= remainingTargets) {

View file

@ -81,7 +81,7 @@ class GlyphOfDelusionSecondTarget extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, source, game)) { for (Permanent creature : game.getBattlefield().getActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURE, sourceControllerId, source, game)) {
if (!targets.containsKey(creature.getId()) && creature.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(creature.getId()) && creature.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(firstTarget, game), game)) { if (watcher.creatureHasBlockedAttacker(new MageObjectReference(creature, game), new MageObjectReference(firstTarget, game), game)) {
possibleTargets.add(creature.getId()); possibleTargets.add(creature.getId());
} }

View file

@ -1,8 +1,5 @@
package mage.cards.k; package mage.cards.k;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -10,10 +7,10 @@ import mage.abilities.common.SimpleActivatedAbility;
import mage.abilities.costs.common.TapSourceCost; import mage.abilities.costs.common.TapSourceCost;
import mage.abilities.costs.mana.ManaCostsImpl; import mage.abilities.costs.mana.ManaCostsImpl;
import mage.abilities.effects.common.CreateTokenEffect; import mage.abilities.effects.common.CreateTokenEffect;
import mage.constants.SubType;
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.SubType;
import mage.filter.FilterOpponent; import mage.filter.FilterOpponent;
import mage.filter.StaticFilters; import mage.filter.StaticFilters;
import mage.game.Game; import mage.game.Game;
@ -21,15 +18,18 @@ import mage.game.permanent.token.BeastToken4;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author noahg * @author noahg
*/ */
public final class KeeperOfTheBeasts extends CardImpl { public final class KeeperOfTheBeasts extends CardImpl {
public KeeperOfTheBeasts(UUID ownerId, CardSetInfo setInfo) { public KeeperOfTheBeasts(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}"); super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{G}{G}");
this.subtype.add(SubType.HUMAN); this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1); this.power = new MageInt(1);
@ -90,7 +90,7 @@ class KeeperOfTheBeastsTarget extends TargetPlayer {
< game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game) < game.getBattlefield().countAll(StaticFilters.FILTER_PERMANENT_CREATURE, playerId, game)
&& !player.hasLeft() && !player.hasLeft()
&& filter.match(player, sourceControllerId, source, game) && filter.match(player, sourceControllerId, source, game)
&& player.canBeTargetedBy(targetSource, sourceControllerId, game)) { && player.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;

View file

@ -1,9 +1,6 @@
package mage.cards.k; package mage.cards.k;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -21,8 +18,11 @@ import mage.game.Game;
import mage.players.Player; import mage.players.Player;
import mage.target.TargetPlayer; import mage.target.TargetPlayer;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author stevemarkham81 * @author stevemarkham81
*/ */
public final class KeeperOfTheLight extends CardImpl { public final class KeeperOfTheLight extends CardImpl {
@ -95,7 +95,7 @@ class KeeperOfTheLightTarget extends TargetPlayer {
&& controller.getLife() < player.getLife() && controller.getLife() < player.getLife()
&& !player.hasLeft() && !player.hasLeft()
&& filter.match(player, sourceControllerId, source, game) && filter.match(player, sourceControllerId, source, game)
&& player.canBeTargetedBy(targetSource, sourceControllerId, game)) { && player.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;

View file

@ -109,7 +109,7 @@ class MutinyFirstTarget extends TargetCreaturePermanent {
int possibleTargets = 0; int possibleTargets = 0;
MageObject sourceObject = game.getObject(source.getId()); MageObject sourceObject = game.getObject(source.getId());
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllingPlayerId, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, controllingPlayerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, controllerId, game)) { if (permanent.canBeTargetedBy(sourceObject, controllerId, source, game)) {
possibleTargets++; possibleTargets++;
} }
} }
@ -126,7 +126,7 @@ class MutinyFirstTarget extends TargetCreaturePermanent {
int possibleTargets = 0; int possibleTargets = 0;
MageObject sourceObject = game.getObject(source); MageObject sourceObject = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(filter, playerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, controllingPlayerId, game)) { if (permanent.canBeTargetedBy(sourceObject, controllingPlayerId, source, game)) {
possibleTargets++; possibleTargets++;
} }
} }

View file

@ -62,7 +62,7 @@ class TargetCreatureWithLessPowerPermanent extends TargetPermanent {
return false; return false;
} }
for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getAllActivePermanents(StaticFilters.FILTER_PERMANENT_CREATURES, sourceControllerId, game)) {
if (permanent.getPower().getValue() > maxPower && permanent.canBeTargetedBy(sourceCard, sourceControllerId, game)) { if (permanent.getPower().getValue() > maxPower && permanent.canBeTargetedBy(sourceCard, sourceControllerId, source, game)) {
maxPower = permanent.getPower().getValue(); maxPower = permanent.getPower().getValue();
} }
} }
@ -70,7 +70,7 @@ class TargetCreatureWithLessPowerPermanent extends TargetPermanent {
FilterCreaturePermanent checkFilter = new FilterCreaturePermanent(); FilterCreaturePermanent checkFilter = new FilterCreaturePermanent();
checkFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, maxPower)); checkFilter.add(new PowerPredicate(ComparisonType.FEWER_THAN, maxPower));
for (Permanent permanent : game.getBattlefield().getActivePermanents(checkFilter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(checkFilter, sourceControllerId, source, game)) {
if (permanent.canBeTargetedBy(sourceCard, sourceControllerId, game)) { if (permanent.canBeTargetedBy(sourceCard, sourceControllerId, source, game)) {
return true; return true;
} }
} }

View file

@ -1,9 +1,6 @@
package mage.cards.p; package mage.cards.p;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.common.BeginningOfUpkeepTriggeredAbility; import mage.abilities.common.BeginningOfUpkeepTriggeredAbility;
@ -20,8 +17,11 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth * @author jeffwadsworth
*/ */
public final class PucasMischief extends CardImpl { public final class PucasMischief extends CardImpl {
@ -29,7 +29,7 @@ public final class PucasMischief extends CardImpl {
private static final String rule = "you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser mana value"; private static final String rule = "you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser mana value";
public PucasMischief(UUID ownerId, CardSetInfo setInfo) { public PucasMischief(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.ENCHANTMENT},"{3}{U}"); super(ownerId, setInfo, new CardType[]{CardType.ENCHANTMENT}, "{3}{U}");
// At the beginning of your upkeep, you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser converted mana cost. // At the beginning of your upkeep, you may exchange control of target nonland permanent you control and target nonland permanent an opponent controls with an equal or lesser converted mana cost.
Ability ability = new BeginningOfUpkeepTriggeredAbility(new ExchangeControlTargetEffect(Duration.EndOfGame, rule, false, true), TargetController.YOU, true); Ability ability = new BeginningOfUpkeepTriggeredAbility(new ExchangeControlTargetEffect(Duration.EndOfGame, rule, false, true), TargetController.YOU, true);
@ -66,9 +66,9 @@ class TargetControlledPermanentWithCMCGreaterOrLessThanOpponentPermanent extends
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) { public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = new HashSet<>(); Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }
@ -118,7 +118,7 @@ class PucasMischiefSecondTarget extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (firstTarget.getManaValue() >= permanent.getManaValue()) { if (firstTarget.getManaValue() >= permanent.getManaValue()) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -1,9 +1,6 @@
package mage.cards.r; package mage.cards.r;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
@ -16,6 +13,10 @@ import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.watchers.common.PlayerDamagedBySourceWatcher; import mage.watchers.common.PlayerDamagedBySourceWatcher;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
* @author LevelX2 * @author LevelX2
*/ */
@ -82,10 +83,10 @@ class ReciprocateTarget extends TargetPermanent {
} }
int count = 0; int count = 0;
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId); PlayerDamagedBySourceWatcher watcher = game.getState().getWatcher(PlayerDamagedBySourceWatcher.class, sourceControllerId);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game) if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) { && watcher != null && watcher.hasSourceDoneDamage(permanent.getId(), game)) {
count++; count++;
if (count >= remainingTargets) { if (count >= remainingTargets) {

View file

@ -43,7 +43,7 @@ public final class RoleReversal extends CardImpl {
class TargetPermanentsThatShareCardType extends TargetPermanent { class TargetPermanentsThatShareCardType extends TargetPermanent {
TargetPermanentsThatShareCardType() { TargetPermanentsThatShareCardType() {
super(2, 2, StaticFilters.FILTER_PERMANENT, false); super(2, 2, StaticFilters.FILTER_PERMANENT, false);
targetName = "permanents that share a permanent type"; targetName = "permanents that share a permanent type";
} }
@ -74,7 +74,7 @@ class TargetPermanentsThatShareCardType extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
for (CardType cardType : permanent.getCardType(game)) { for (CardType cardType : permanent.getCardType(game)) {
if (cardTypes.contains(cardType)) { if (cardTypes.contains(cardType)) {
return true; return true;

View file

@ -74,7 +74,7 @@ class TargetPermanentsThatShareCardType extends TargetPermanent {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
for (CardType cardType : permanent.getCardType(game)) { for (CardType cardType : permanent.getCardType(game)) {
if (cardTypes.contains(cardType)) { if (cardTypes.contains(cardType)) {
return true; return true;

View file

@ -1,9 +1,6 @@
package mage.cards.s; package mage.cards.s;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import mage.MageInt; import mage.MageInt;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
@ -11,19 +8,17 @@ import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect; import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
import mage.cards.CardImpl; import mage.cards.CardImpl;
import mage.cards.CardSetInfo; import mage.cards.CardSetInfo;
import mage.constants.CardType; import mage.constants.*;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.constants.TargetController;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.TargetPermanent; import mage.target.TargetPermanent;
import mage.target.common.TargetControlledPermanent; import mage.target.common.TargetControlledPermanent;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author jeffwadsworth & L_J * @author jeffwadsworth & L_J
*/ */
public final class Spawnbroker extends CardImpl { public final class Spawnbroker extends CardImpl {
@ -31,12 +26,12 @@ public final class Spawnbroker extends CardImpl {
private static final String rule = "you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls"; private static final String rule = "you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls";
public Spawnbroker(UUID ownerId, CardSetInfo setInfo) { public Spawnbroker(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(SubType.HUMAN); this.subtype.add(SubType.HUMAN);
this.subtype.add(SubType.WIZARD); this.subtype.add(SubType.WIZARD);
this.power = new MageInt(1); this.power = new MageInt(1);
this.toughness = new MageInt(1); this.toughness = new MageInt(1);
// When Spawnbroker enters the battlefield, you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls. // When Spawnbroker enters the battlefield, you may exchange control of target creature you control and target creature with power less than or equal to that creature's power an opponent controls.
Ability ability = new EntersBattlefieldTriggeredAbility(new ExchangeControlTargetEffect(Duration.Custom, rule, false, true), true); Ability ability = new EntersBattlefieldTriggeredAbility(new ExchangeControlTargetEffect(Duration.Custom, rule, false, true), true);
ability.addTarget(new TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent()); ability.addTarget(new TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent());
@ -72,9 +67,9 @@ class TargetControlledCreatureWithPowerGreaterOrLessThanOpponentPermanent extend
public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) { public Set<UUID> possibleTargets(UUID sourceControllerId, Ability source, Game game) {
Set<UUID> possibleTargets = new HashSet<>(); Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }
@ -122,9 +117,9 @@ class SpawnbrokerSecondTarget extends TargetPermanent {
Set<UUID> possibleTargets = new HashSet<>(); Set<UUID> possibleTargets = new HashSet<>();
if (firstTarget != null) { if (firstTarget != null) {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (firstTarget.getPower().getValue() >= permanent.getPower().getValue()) { if (firstTarget.getPower().getValue() >= permanent.getPower().getValue()) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -19,13 +19,12 @@ import mage.target.common.TargetCreaturePermanent;
import java.util.UUID; import java.util.UUID;
/** /**
*
* @author FenrisulfrX * @author FenrisulfrX
*/ */
public final class TemporaryInsanity extends CardImpl { public final class TemporaryInsanity extends CardImpl {
public TemporaryInsanity(UUID ownerId, CardSetInfo setInfo) { public TemporaryInsanity(UUID ownerId, CardSetInfo setInfo) {
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{R}"); super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{R}");
// Untap target creature with power less than the number of cards in your graveyard // Untap target creature with power less than the number of cards in your graveyard
this.getSpellAbility().addTarget(new TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard()); this.getSpellAbility().addTarget(new TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard());
@ -78,9 +77,9 @@ class TargetCreatureWithPowerLessThanNumberOfCardsInYourGraveyard extends Target
@Override @Override
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource != null) { if (targetSource != null) {
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (permanent.getPower().getValue() < game.getPlayer(sourceControllerId).getGraveyard().size()) { if (permanent.getPower().getValue() < game.getPlayer(sourceControllerId).getGraveyard().size()) {
return true; return true;
} }

View file

@ -115,7 +115,7 @@ class TheTricksterGodsHeistTarget extends TargetPermanent {
return false; return false;
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
continue; continue;
} }
for (CardType cardType : permanent.getCardType(game)) { for (CardType cardType : permanent.getCardType(game)) {

View file

@ -73,7 +73,7 @@ class ThranTomeEffect extends OneShotEffect {
// target an opponent, if able // target an opponent, if able
Player opponent; Player opponent;
Set<UUID> opponents = game.getOpponents(controller.getId()); Set<UUID> opponents = game.getOpponents(controller.getId());
opponents.removeIf(opp -> !game.getPlayer(opp).canBeTargetedBy(sourceObject, source.getControllerId(), game)); opponents.removeIf(opp -> !game.getPlayer(opp).canBeTargetedBy(sourceObject, source.getControllerId(), source, game));
if (opponents.isEmpty()) { if (opponents.isEmpty()) {
return false; return false;

View file

@ -1,9 +1,5 @@
package mage.cards.t; package mage.cards.t;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability; import mage.abilities.Ability;
import mage.abilities.effects.common.ExileTargetEffect; import mage.abilities.effects.common.ExileTargetEffect;
@ -14,8 +10,12 @@ import mage.game.Game;
import mage.game.permanent.Permanent; import mage.game.permanent.Permanent;
import mage.target.common.TargetCreaturePermanent; import mage.target.common.TargetCreaturePermanent;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;
/** /**
*
* @author L_J * @author L_J
*/ */
public final class Topple extends CardImpl { public final class Topple extends CardImpl {
@ -72,7 +72,7 @@ class ToppleTargetCreature extends TargetCreaturePermanent {
List<Permanent> activePermanents = game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game); List<Permanent> activePermanents = game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game);
Set<UUID> possibleTargets = new HashSet<>(); Set<UUID> possibleTargets = new HashSet<>();
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if(targetSource == null){ if (targetSource == null) {
return possibleTargets; return possibleTargets;
} }
for (Permanent permanent : activePermanents) { for (Permanent permanent : activePermanents) {
@ -81,7 +81,7 @@ class ToppleTargetCreature extends TargetCreaturePermanent {
} }
} }
for (Permanent permanent : activePermanents) { for (Permanent permanent : activePermanents) {
if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!targets.containsKey(permanent.getId()) && permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
if (permanent.getPower().getValue() == maxPower) { if (permanent.getPower().getValue() == maxPower) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -0,0 +1,147 @@
package mage.cards.v;
import mage.MageInt;
import mage.MageObject;
import mage.abilities.Ability;
import mage.abilities.common.EntersBattlefieldTriggeredAbility;
import mage.abilities.costs.common.PayEnergyCost;
import mage.abilities.effects.ContinuousEffect;
import mage.abilities.effects.OneShotEffect;
import mage.abilities.effects.common.DoIfCostPaid;
import mage.abilities.effects.common.SacrificeTargetEffect;
import mage.abilities.effects.common.continuous.ExchangeControlTargetEffect;
import mage.abilities.keyword.FlyingAbility;
import mage.abilities.keyword.HexproofBaseAbility;
import mage.cards.CardImpl;
import mage.cards.CardSetInfo;
import mage.constants.CardType;
import mage.constants.Duration;
import mage.constants.Outcome;
import mage.constants.SubType;
import mage.counters.CounterType;
import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.players.Player;
import mage.target.common.TargetOpponentsCreaturePermanent;
import java.io.ObjectStreamException;
import java.util.UUID;
/**
* @author Susucr
*/
public final class VolatileStormdrake extends CardImpl {
public VolatileStormdrake(UUID ownerId, CardSetInfo setInfo) {
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{1}{U}");
this.subtype.add(SubType.DRAKE);
this.power = new MageInt(3);
this.toughness = new MageInt(2);
// Flying
this.addAbility(FlyingAbility.getInstance());
// Hexproof from activated and triggered abilities
this.addAbility(VolatileStormdrakeHexproofAbility.getInstance());
// When Volatile Stormdrake enters the battlefield, exchange control of Volatile Stormdrake and target creature an opponent controls. If you do, you get {E}{E}{E}{E}, then sacrifice that creature unless you pay an amount of {E} equal to its mana value.
Ability ability = new EntersBattlefieldTriggeredAbility(new VolatileStormdrakeEffect());
ability.addTarget(new TargetOpponentsCreaturePermanent());
this.addAbility(ability);
}
private VolatileStormdrake(final VolatileStormdrake card) {
super(card);
}
@Override
public VolatileStormdrake copy() {
return new VolatileStormdrake(this);
}
}
class VolatileStormdrakeHexproofAbility extends HexproofBaseAbility {
private static final VolatileStormdrakeHexproofAbility instance;
static {
instance = new VolatileStormdrakeHexproofAbility();
}
private Object readResolve() throws ObjectStreamException {
return instance;
}
public static VolatileStormdrakeHexproofAbility getInstance() {
return instance;
}
private VolatileStormdrakeHexproofAbility() {
super();
}
@Override
public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.isTriggeredAbility() || source.isActivatedAbility();
}
@Override
public VolatileStormdrakeHexproofAbility copy() {
return instance;
}
@Override
public String getRule() {
return "hexproof from activated and triggered abilities";
}
@Override
public String getCardIconHint(Game game) {
return "hexproof from activated and triggered abilities";
}
}
class VolatileStormdrakeEffect extends OneShotEffect {
VolatileStormdrakeEffect() {
super(Outcome.GainControl);
this.staticText = "exchange control of {this} and up to one target creature an opponent controls. "
+ "If you do, you get {E}{E}{E}{E}, then sacrifice that creature unless you pay an amount of {E} equal to its mana value";
}
private VolatileStormdrakeEffect(final VolatileStormdrakeEffect effect) {
super(effect);
}
@Override
public VolatileStormdrakeEffect copy() {
return new VolatileStormdrakeEffect(this);
}
@Override
public boolean apply(Game game, Ability source) {
Player controller = game.getPlayer(source.getControllerId());
if (controller == null) {
return false;
}
Permanent sourceObject = game.getPermanent(source.getSourceId());
if (sourceObject == null) {
return false;
}
Permanent targetPermanent = game.getPermanent(getTargetPointer().getFirst(game, source));
if (targetPermanent == null) {
return false;
}
ContinuousEffect effect = new ExchangeControlTargetEffect(Duration.EndOfGame, "", true);
effect.setTargetPointer(this.getTargetPointer().copy());
game.addEffect(effect, source);
game.getState().processAction(game);
controller.addCounters(CounterType.ENERGY.createInstance(4), controller.getId(), source, game);
new DoIfCostPaid(
null, new SacrificeTargetEffect("", controller.getId()),
new PayEnergyCost(targetPermanent.getManaValue()), true
).apply(game, source);
return true;
}
}

View file

@ -307,6 +307,7 @@ public final class ModernHorizons3 extends ExpansionSet {
cards.add(new SetCardInfo("Vexing Bauble", 212, Rarity.UNCOMMON, mage.cards.v.VexingBauble.class)); cards.add(new SetCardInfo("Vexing Bauble", 212, Rarity.UNCOMMON, mage.cards.v.VexingBauble.class));
cards.add(new SetCardInfo("Victimize", 278, Rarity.UNCOMMON, mage.cards.v.Victimize.class)); cards.add(new SetCardInfo("Victimize", 278, Rarity.UNCOMMON, mage.cards.v.Victimize.class));
cards.add(new SetCardInfo("Voidpouncer", 143, Rarity.COMMON, mage.cards.v.Voidpouncer.class)); cards.add(new SetCardInfo("Voidpouncer", 143, Rarity.COMMON, mage.cards.v.Voidpouncer.class));
cards.add(new SetCardInfo("Volatile Stormdrake", 79, Rarity.RARE, mage.cards.v.VolatileStormdrake.class));
cards.add(new SetCardInfo("Voltstorm Angel", 46, Rarity.UNCOMMON, mage.cards.v.VoltstormAngel.class)); cards.add(new SetCardInfo("Voltstorm Angel", 46, Rarity.UNCOMMON, mage.cards.v.VoltstormAngel.class));
cards.add(new SetCardInfo("Warped Tusker", 16, Rarity.COMMON, mage.cards.w.WarpedTusker.class)); cards.add(new SetCardInfo("Warped Tusker", 16, Rarity.COMMON, mage.cards.w.WarpedTusker.class));
cards.add(new SetCardInfo("Warren Soultrader", 110, Rarity.RARE, mage.cards.w.WarrenSoultrader.class)); cards.add(new SetCardInfo("Warren Soultrader", 110, Rarity.RARE, mage.cards.w.WarrenSoultrader.class));

View file

@ -0,0 +1,75 @@
package org.mage.test.cards.single.mh3;
import mage.constants.PhaseStep;
import mage.constants.Zone;
import org.junit.Test;
import org.mage.test.serverside.base.CardTestPlayerBase;
/**
* @author Susucr
*/
public class VolatileStormdrakeTest extends CardTestPlayerBase {
/**
* {@link mage.cards.v.VolatileStormdrake Volatile Stormdrake} {1}{U}
* Creature Drake
* Flying, hexproof from activated and triggered abilities
* When Volatile Stormdrake enters the battlefield, exchange control of Volatile Stormdrake and target creature an opponent controls. If you do, you get {E}{E}{E}{E}, then sacrifice that creature unless you pay an amount of {E} equal to its mana value.
* 3/2
*/
private static final String drake = "Volatile Stormdrake";
@Test
public void test_Hexproof_From_Triggered() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, drake);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 4);
addCard(Zone.HAND, playerA, "Ravenous Chupacabra");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Ravenous Chupacabra");
// no trigger, as the drake has hexproof from triggered ability so there is no valid target
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertPermanentCount(playerB, drake, 1);
assertPermanentCount(playerA, "Ravenous Chupacabra", 1);
}
@Test
public void test_Hexproof_From_Activated() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, drake);
addCard(Zone.BATTLEFIELD, playerA, "Alluring Siren");
addCard(Zone.HAND, playerB, "Memnite");
checkPlayableAbility("can not activate Siren", 1, PhaseStep.PRECOMBAT_MAIN, playerA,
"{T}: Target creature an opponent controls attacks you this turn if able.", false);
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Memnite");
checkPlayableAbility("can not activate Siren", 3, PhaseStep.PRECOMBAT_MAIN, playerA,
"{T}: Target creature an opponent controls attacks you this turn if able.", true);
setStopAt(3, PhaseStep.BEGIN_COMBAT);
execute();
}
@Test
public void test_CanBeTargetted_BySpell() {
setStrictChooseMode(true);
addCard(Zone.BATTLEFIELD, playerB, drake);
addCard(Zone.BATTLEFIELD, playerA, "Swamp", 3);
addCard(Zone.HAND, playerA, "Murder");
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Murder", drake);
setStopAt(1, PhaseStep.BEGIN_COMBAT);
execute();
assertGraveyardCount(playerB, drake, 1);
}
}

View file

@ -3027,8 +3027,8 @@ public class TestPlayer implements Player {
} }
@Override @Override
public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { public boolean canBeTargetedBy(MageObject sourceObject, UUID sourceControllerId, Ability source, Game game) {
return computerPlayer.canBeTargetedBy(source, sourceControllerId, game); return computerPlayer.canBeTargetedBy(sourceObject, sourceControllerId, source, game);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,7 +33,7 @@ public class HexproofAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return true; return true;
} }

View file

@ -2,6 +2,7 @@ package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.ObjectColor; import mage.ObjectColor;
import mage.abilities.Ability;
import mage.abilities.MageSingleton; import mage.abilities.MageSingleton;
import mage.abilities.common.SimpleStaticAbility; import mage.abilities.common.SimpleStaticAbility;
import mage.abilities.icon.CardIcon; import mage.abilities.icon.CardIcon;
@ -9,10 +10,12 @@ import mage.abilities.icon.CardIconImpl;
import mage.abilities.icon.CardIconType; import mage.abilities.icon.CardIconType;
import mage.constants.Zone; import mage.constants.Zone;
import mage.game.Game; import mage.game.Game;
import mage.game.permanent.Permanent;
import mage.util.CardUtil; import mage.util.CardUtil;
import java.util.*; import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/** /**
* an abstract base class for hexproof abilities * an abstract base class for hexproof abilities
@ -21,11 +24,11 @@ import java.util.*;
*/ */
public abstract class HexproofBaseAbility extends SimpleStaticAbility implements MageSingleton { public abstract class HexproofBaseAbility extends SimpleStaticAbility implements MageSingleton {
HexproofBaseAbility() { protected HexproofBaseAbility() {
super(Zone.BATTLEFIELD, null); super(Zone.BATTLEFIELD, null);
} }
public abstract boolean checkObject(MageObject source, Game game); public abstract boolean checkObject(MageObject sourceObject, Ability source, Game game);
public static Set<HexproofBaseAbility> getFromColor(ObjectColor color) { public static Set<HexproofBaseAbility> getFromColor(ObjectColor color) {
Set<HexproofBaseAbility> abilities = new HashSet<>(); Set<HexproofBaseAbility> abilities = new HashSet<>();

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -31,8 +32,8 @@ public class HexproofFromArtifactsCreaturesAndEnchantments extends HexproofBaseA
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.isArtifact(game) || source.isCreature(game) || source.isEnchantment(game); return sourceObject.isArtifact(game) || sourceObject.isCreature(game) || sourceObject.isEnchantment(game);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromBlackAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor(game).isBlack(); return sourceObject.getColor(game).isBlack();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromBlueAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor(game).isBlue(); return sourceObject.getColor(game).isBlue();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -31,8 +32,8 @@ public class HexproofFromEachColorAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return !source.getColor(game).isColorless(); return !sourceObject.getColor(game).isColorless();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromGreenAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor(game).isGreen(); return sourceObject.getColor(game).isGreen();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromMonocoloredAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return !source.getColor(game).isMulticolored() && !source.getColor(game).isColorless(); return !sourceObject.getColor(game).isMulticolored() && !sourceObject.getColor(game).isColorless();
} }
@Override @Override

View file

@ -1,10 +1,11 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import java.io.ObjectStreamException;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException;
public class HexproofFromMulticoloredAbility extends HexproofBaseAbility { public class HexproofFromMulticoloredAbility extends HexproofBaseAbility {
private static final HexproofFromMulticoloredAbility instance; private static final HexproofFromMulticoloredAbility instance;
@ -31,8 +32,8 @@ public class HexproofFromMulticoloredAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor().isMulticolored(); return sourceObject.getColor().isMulticolored();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -31,8 +32,8 @@ public class HexproofFromPlaneswalkersAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.isPlaneswalker(game); return sourceObject.isPlaneswalker(game);
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromRedAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor(game).isRed(); return sourceObject.getColor(game).isRed();
} }
@Override @Override

View file

@ -1,6 +1,7 @@
package mage.abilities.keyword; package mage.abilities.keyword;
import mage.MageObject; import mage.MageObject;
import mage.abilities.Ability;
import mage.game.Game; import mage.game.Game;
import java.io.ObjectStreamException; import java.io.ObjectStreamException;
@ -32,8 +33,8 @@ public class HexproofFromWhiteAbility extends HexproofBaseAbility {
} }
@Override @Override
public boolean checkObject(MageObject source, Game game) { public boolean checkObject(MageObject sourceObject, Ability source, Game game) {
return source.getColor(game).isWhite(); return sourceObject.getColor(game).isWhite();
} }
@Override @Override

View file

@ -128,7 +128,7 @@ public interface Permanent extends Card, Controllable {
void unattach(Game game); void unattach(Game game);
boolean canBeTargetedBy(MageObject source, UUID controllerId, Game game); boolean canBeTargetedBy(MageObject sourceObject, UUID controllerId, Ability source, Game game);
boolean hasProtectionFrom(MageObject source, Game game); boolean hasProtectionFrom(MageObject source, Game game);

View file

@ -1302,8 +1302,8 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
} }
@Override @Override
public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { public boolean canBeTargetedBy(MageObject sourceObject, UUID sourceControllerId, Ability source, Game game) {
if (source != null) { if (sourceObject != null) {
if (abilities.containsKey(ShroudAbility.getInstance().getId())) { if (abilities.containsKey(ShroudAbility.getInstance().getId())) {
if (game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, null, sourceControllerId, game).isEmpty()) { if (game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, null, sourceControllerId, game).isEmpty()) {
return false; return false;
@ -1315,17 +1315,17 @@ public abstract class PermanentImpl extends CardImpl implements Permanent {
&& abilities.stream() && abilities.stream()
.filter(HexproofBaseAbility.class::isInstance) .filter(HexproofBaseAbility.class::isInstance)
.map(HexproofBaseAbility.class::cast) .map(HexproofBaseAbility.class::cast)
.anyMatch(ability -> ability.checkObject(source, game))) { .anyMatch(ability -> ability.checkObject(sourceObject, source, game))) {
return false; return false;
} }
if (hasProtectionFrom(source, game)) { if (hasProtectionFrom(sourceObject, game)) {
return false; return false;
} }
// example: Fiendslayer Paladin tried to target with Ultimate Price // example: Fiendslayer Paladin tried to target with Ultimate Price
return !game.getContinuousEffects().preventedByRuleModification( return !game.getContinuousEffects().preventedByRuleModification(
new TargetEvent(this, source.getId(), sourceControllerId), new TargetEvent(this, sourceObject.getId(), sourceControllerId),
null, null,
game, game,
true true

View file

@ -513,7 +513,7 @@ public interface Player extends MageItem, Copyable<Player> {
boolean triggerAbility(TriggeredAbility ability, Game game); boolean triggerAbility(TriggeredAbility ability, Game game);
boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game); boolean canBeTargetedBy(MageObject sourceObject, UUID sourceControllerId, Ability source, Game game);
boolean hasProtectionFrom(MageObject source, Game game); boolean hasProtectionFrom(MageObject source, Game game);

View file

@ -687,11 +687,11 @@ public abstract class PlayerImpl implements Player, Serializable {
} }
@Override @Override
public boolean canBeTargetedBy(MageObject source, UUID sourceControllerId, Game game) { public boolean canBeTargetedBy(MageObject sourceObject, UUID sourceControllerId, Ability source, Game game) {
if (this.hasLost() || this.hasLeft()) { if (this.hasLost() || this.hasLeft()) {
return false; return false;
} }
if (source != null) { if (sourceObject != null) {
if (abilities.containsKey(ShroudAbility.getInstance().getId()) if (abilities.containsKey(ShroudAbility.getInstance().getId())
&& game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, null, sourceControllerId, game).isEmpty()) { && game.getContinuousEffects().asThough(this.getId(), AsThoughEffectType.SHROUD, null, sourceControllerId, game).isEmpty()) {
return false; return false;
@ -703,17 +703,17 @@ public abstract class PlayerImpl implements Player, Serializable {
&& abilities.stream() && abilities.stream()
.filter(HexproofBaseAbility.class::isInstance) .filter(HexproofBaseAbility.class::isInstance)
.map(HexproofBaseAbility.class::cast) .map(HexproofBaseAbility.class::cast)
.anyMatch(ability -> ability.checkObject(source, game))) { .anyMatch(ability -> ability.checkObject(sourceObject, source, game))) {
return false; return false;
} }
if (hasProtectionFrom(source, game)) { if (hasProtectionFrom(sourceObject, game)) {
return false; return false;
} }
// example: Peace Talks // example: Peace Talks
return !game.getContinuousEffects().preventedByRuleModification( return !game.getContinuousEffects().preventedByRuleModification(
new TargetEvent(this, source.getId(), sourceControllerId), new TargetEvent(this, sourceObject.getId(), sourceControllerId),
null, null,
game, game,
true true

View file

@ -67,8 +67,8 @@ public class TargetPermanent extends TargetObject {
// first for protection from spells or abilities (e.g. protection from colored spells, r1753) // first for protection from spells or abilities (e.g. protection from colored spells, r1753)
// second for protection from sources (e.g. protection from artifacts + equip ability) // second for protection from sources (e.g. protection from artifacts + equip ability)
if (!isNotTarget()) { if (!isNotTarget()) {
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, source, game)
|| !permanent.canBeTargetedBy(game.getObject(source), controllerId, game)) { || !permanent.canBeTargetedBy(game.getObject(source), controllerId, source, game)) {
return false; return false;
} }
} }
@ -108,7 +108,7 @@ public class TargetPermanent extends TargetObject {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId())) { if (!targets.containsKey(permanent.getId())) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
count++; count++;
if (count >= remainingTargets) { if (count >= remainingTargets) {
return true; return true;
@ -155,7 +155,7 @@ public class TargetPermanent extends TargetObject {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter, sourceControllerId, source, game)) {
if (!targets.containsKey(permanent.getId())) { if (!targets.containsKey(permanent.getId())) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }

View file

@ -67,7 +67,7 @@ public class TargetPlayer extends TargetImpl {
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null && !player.hasLeft() && filter.match(player, sourceControllerId, source, game)) { if (player != null && !player.hasLeft() && filter.match(player, sourceControllerId, source, game)) {
if (player.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (player.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -109,7 +109,7 @@ public class TargetPlayer extends TargetImpl {
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null && !player.hasLeft() && filter.match(player, sourceControllerId, source, game)) { if (player != null && !player.hasLeft() && filter.match(player, sourceControllerId, source, game)) {
if (isNotTarget() || player.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (isNotTarget() || player.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
possibleTargets.add(playerId); possibleTargets.add(playerId);
} }
} }
@ -149,7 +149,7 @@ public class TargetPlayer extends TargetImpl {
Player player = game.getPlayer(id); Player player = game.getPlayer(id);
if (player != null) { if (player != null) {
if (source != null) { if (source != null) {
return (isNotTarget() || player.canBeTargetedBy(game.getObject(source), source.getControllerId(), game)) return (isNotTarget() || player.canBeTargetedBy(game.getObject(source), source.getControllerId(), source, game))
&& filter.match(player, source.getControllerId(), source, game); && filter.match(player, source.getControllerId(), source, game);
} else { } else {
return filter.match(player, game); return filter.match(player, game);

View file

@ -63,7 +63,7 @@ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard {
} }
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, source, game)) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
return true; return true;
} }
} }
@ -110,7 +110,7 @@ public class TargetCardInGraveyardBattlefieldOrStack extends TargetCard {
Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game); // in graveyard first Set<UUID> possibleTargets = super.possibleTargets(sourceControllerId, source, game); // in graveyard first
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, source, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filterPermanent, sourceControllerId, source, game)) {
if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }

View file

@ -71,10 +71,10 @@ public class TargetCreatureOrPlayer extends TargetImpl {
if (source != null) { if (source != null) {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (permanent != null) { if (permanent != null) {
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(permanent, source.getControllerId(), source, game); return permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game) && filter.match(permanent, source.getControllerId(), source, game);
} }
if (player != null) { if (player != null) {
return player.canBeTargetedBy(targetSource, source.getControllerId(), game) && filter.match(player, game); return player.canBeTargetedBy(targetSource, source.getControllerId(), source, game) && filter.match(player, game);
} }
} }
@ -100,7 +100,7 @@ public class TargetCreatureOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, game)) { if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(player, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -108,7 +108,7 @@ public class TargetCreatureOrPlayer extends TargetImpl {
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -157,13 +157,13 @@ public class TargetCreatureOrPlayer extends TargetImpl {
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null if (player != null
&& player.canBeTargetedBy(targetSource, sourceControllerId, game) && player.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& filter.getPlayerFilter().match(player, sourceControllerId, source, game)) { && filter.getPlayerFilter().match(player, sourceControllerId, source, game)) {
possibleTargets.add(playerId); possibleTargets.add(playerId);
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& filter.getCreatureFilter().match(permanent, sourceControllerId, source, game)) { && filter.getCreatureFilter().match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }

View file

@ -40,8 +40,8 @@ public class TargetOpponentsChoicePermanent extends TargetPermanent {
if (source != null) { if (source != null) {
boolean canSourceControllerTarget = true; boolean canSourceControllerTarget = true;
if (!isNotTarget()) { if (!isNotTarget()) {
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, game) if (!permanent.canBeTargetedBy(game.getObject(source.getId()), controllerId, source, game)
|| !permanent.canBeTargetedBy(game.getObject(source), controllerId, game)) { || !permanent.canBeTargetedBy(game.getObject(source), controllerId, source, game)) {
canSourceControllerTarget = false; canSourceControllerTarget = false;
} }
} }
@ -89,7 +89,7 @@ public class TargetOpponentsChoicePermanent extends TargetPermanent {
for (Permanent perm : game.getBattlefield().getActivePermanents(opp.getId(), game)) { for (Permanent perm : game.getBattlefield().getActivePermanents(opp.getId(), game)) {
if (!targets.containsKey(perm.getId()) if (!targets.containsKey(perm.getId())
&& filter.match(perm, opp.getId(), source, game) && filter.match(perm, opp.getId(), source, game)
&& perm.canBeTargetedBy(sourceObject, sourceControllerId, game)) { && perm.canBeTargetedBy(sourceObject, sourceControllerId, source, game)) {
counter++; counter++;
if (counter >= minNumberOfTargets) { if (counter >= minNumberOfTargets) {
return true; return true;

View file

@ -72,7 +72,7 @@ public class TargetPermanentAmount extends TargetAmount {
return filter.match(permanent, game); return filter.match(permanent, game);
} }
MageObject targetSource = source.getSourceObject(game); MageObject targetSource = source.getSourceObject(game);
return (notTarget || permanent.canBeTargetedBy(targetSource, source.getControllerId(), game)) return (notTarget || permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game))
&& filter.match(permanent, source.getControllerId(), source, game); && filter.match(permanent, source.getControllerId(), source, game);
} }
@ -106,7 +106,7 @@ public class TargetPermanentAmount extends TargetAmount {
.getActivePermanents(filter, sourceControllerId, source, game) .getActivePermanents(filter, sourceControllerId, source, game)
.stream() .stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(permanent -> notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) .filter(permanent -> notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game))
.map(Permanent::getId) .map(Permanent::getId)
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }

View file

@ -85,8 +85,8 @@ public class TargetPermanentOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
if (permanent != null) { if (permanent != null) {
if (!isNotTarget()) { if (!isNotTarget()) {
if (!permanent.canBeTargetedBy(game.getObject(source.getId()), source.getControllerId(), game) if (!permanent.canBeTargetedBy(game.getObject(source.getId()), source.getControllerId(), source, game)
|| !permanent.canBeTargetedBy(game.getObject(source), source.getControllerId(), game)) { || !permanent.canBeTargetedBy(game.getObject(source), source.getControllerId(), source, game)) {
return false; return false;
} }
} }
@ -94,7 +94,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
} }
if (player != null) { if (player != null) {
if (!isNotTarget()) { if (!isNotTarget()) {
if (!player.canBeTargetedBy(targetSource, source.getControllerId(), game) if (!player.canBeTargetedBy(targetSource, source.getControllerId(), source, game)
|| !filter.match(player, source.getControllerId(), source, game)) { || !filter.match(player, source.getControllerId(), source, game)) {
return false; return false;
} }
@ -126,7 +126,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(player, sourceControllerId, source, game)) { if (player != null && player.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(player, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -134,7 +134,7 @@ public class TargetPermanentOrPlayer extends TargetImpl {
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -183,12 +183,12 @@ public class TargetPermanentOrPlayer extends TargetImpl {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(player, sourceControllerId, source, game)) { if (player != null && (notTarget || player.canBeTargetedBy(targetSource, sourceControllerId, source, game)) && filter.match(player, sourceControllerId, source, game)) {
possibleTargets.add(playerId); possibleTargets.add(playerId);
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) && filter.match(permanent, sourceControllerId, source, game)) { if ((notTarget || permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) && filter.match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }

View file

@ -71,11 +71,11 @@ public abstract class TargetPermanentOrPlayerAmount extends TargetAmount {
if (source != null) { if (source != null) {
MageObject targetSource = source.getSourceObject(game); MageObject targetSource = source.getSourceObject(game);
if (permanent != null) { if (permanent != null) {
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) return permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game)
&& filter.match(permanent, source.getControllerId(), source, game); && filter.match(permanent, source.getControllerId(), source, game);
} }
if (player != null) { if (player != null) {
return player.canBeTargetedBy(targetSource, source.getControllerId(), game) return player.canBeTargetedBy(targetSource, source.getControllerId(), source, game)
&& filter.match(player, game); && filter.match(player, game);
} }
} }
@ -99,7 +99,7 @@ public abstract class TargetPermanentOrPlayerAmount extends TargetAmount {
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) { for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
Player player = game.getPlayer(playerId); Player player = game.getPlayer(playerId);
if (player == null if (player == null
|| !player.canBeTargetedBy(targetSource, sourceControllerId, game) || !player.canBeTargetedBy(targetSource, sourceControllerId, source, game)
|| !filter.match(player, game)) { || !filter.match(player, game)) {
continue; continue;
} }
@ -109,7 +109,7 @@ public abstract class TargetPermanentOrPlayerAmount extends TargetAmount {
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (!permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) { if (!permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game)) {
continue; continue;
} }
count++; count++;
@ -160,7 +160,7 @@ public abstract class TargetPermanentOrPlayerAmount extends TargetAmount {
.stream() .stream()
.map(game::getPlayer) .map(game::getPlayer)
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(player -> player.canBeTargetedBy(targetSource, sourceControllerId, game) .filter(player -> player.canBeTargetedBy(targetSource, sourceControllerId, source, game)
&& filter.match(player, game) && filter.match(player, game)
) )
.map(Player::getId) .map(Player::getId)
@ -170,7 +170,7 @@ public abstract class TargetPermanentOrPlayerAmount extends TargetAmount {
.getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game) .getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)
.stream() .stream()
.filter(Objects::nonNull) .filter(Objects::nonNull)
.filter(permanent -> permanent.canBeTargetedBy(targetSource, sourceControllerId, game)) .filter(permanent -> permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game))
.map(Permanent::getId) .map(Permanent::getId)
.forEach(possibleTargets::add); .forEach(possibleTargets::add);

View file

@ -57,7 +57,7 @@ public class TargetPermanentOrSuspendedCard extends TargetImpl {
public boolean canChoose(UUID sourceControllerId, Ability source, Game game) { public boolean canChoose(UUID sourceControllerId, Ability source, Game game) {
MageObject sourceObject = game.getObject(source); MageObject sourceObject = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(sourceObject, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
return true; return true;
} }
} }
@ -74,7 +74,7 @@ public class TargetPermanentOrSuspendedCard extends TargetImpl {
Set<UUID> possibleTargets = new HashSet<>(20); Set<UUID> possibleTargets = new HashSet<>(20);
MageObject sourceObject = game.getObject(source); MageObject sourceObject = game.getObject(source);
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(sourceObject, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(sourceObject, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }
@ -102,7 +102,7 @@ public class TargetPermanentOrSuspendedCard extends TargetImpl {
if (permanent != null) { if (permanent != null) {
if (source != null) { if (source != null) {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) return permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game)
&& filter.match(permanent, source.getControllerId(), source, game); && filter.match(permanent, source.getControllerId(), source, game);
} else { } else {
return filter.match(permanent, game); return filter.match(permanent, game);

View file

@ -89,7 +89,7 @@ public class TargetSpellOrPermanent extends TargetImpl {
if (permanent != null) { if (permanent != null) {
if (source != null) { if (source != null) {
MageObject targetSource = game.getObject(source); MageObject targetSource = game.getObject(source);
return permanent.canBeTargetedBy(targetSource, source.getControllerId(), game) return permanent.canBeTargetedBy(targetSource, source.getControllerId(), source, game)
&& filter.match(permanent, source.getControllerId(), source, game); && filter.match(permanent, source.getControllerId(), source, game);
} else { } else {
return filter.match(permanent, game); return filter.match(permanent, game);
@ -132,7 +132,7 @@ public class TargetSpellOrPermanent extends TargetImpl {
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
count++; count++;
if (count >= this.minNumberOfTargets) { if (count >= this.minNumberOfTargets) {
return true; return true;
@ -189,7 +189,7 @@ public class TargetSpellOrPermanent extends TargetImpl {
} }
} }
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) { for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceControllerId, source, game)) { if (permanent.canBeTargetedBy(targetSource, sourceControllerId, source, game) && filter.match(permanent, sourceControllerId, source, game)) {
possibleTargets.add(permanent.getId()); possibleTargets.add(permanent.getId());
} }
} }