mirror of
https://github.com/correl/mage.git
synced 2024-11-14 19:19:32 +00:00
* Deals damage divided as you choose - fixed that some cards can't choose planeswalkers (example: Arc Lightning, see #7276);
Refactor: simplified FilterCreaturePlayerOrPlaneswalker to use single permanent filter;
This commit is contained in:
parent
347a3b1e1a
commit
255c292104
18 changed files with 162 additions and 222 deletions
|
@ -1,16 +1,10 @@
|
|||
package mage.player.ai;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import mage.ApprovingObject;
|
||||
import mage.ConditionalMana;
|
||||
import mage.MageObject;
|
||||
import mage.Mana;
|
||||
import mage.abilities.*;
|
||||
import mage.abilities.costs.AlternativeSourceCosts;
|
||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
||||
import mage.abilities.costs.VariableCost;
|
||||
import mage.abilities.costs.mana.*;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
@ -42,7 +36,6 @@ import mage.game.combat.CombatGroup;
|
|||
import mage.game.draft.Draft;
|
||||
import mage.game.draft.RateCard;
|
||||
import mage.game.events.GameEvent;
|
||||
import mage.game.events.GameEvent.EventType;
|
||||
import mage.game.match.Match;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.game.stack.Spell;
|
||||
|
@ -63,6 +56,11 @@ import mage.util.TournamentUtil;
|
|||
import mage.util.TreeNode;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
/**
|
||||
* suitable for two player games and some multiplayer games
|
||||
*
|
||||
|
@ -270,9 +268,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
List<Permanent> targets;
|
||||
TargetAnyTarget origTarget = (TargetAnyTarget) target.getOriginalTarget();
|
||||
if (outcome.isGood()) {
|
||||
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
|
||||
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
} else {
|
||||
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
|
||||
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
}
|
||||
for (Permanent permanent : targets) {
|
||||
List<UUID> alreadyTargetted = target.getTargets();
|
||||
|
@ -651,9 +649,9 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
List<Permanent> targets;
|
||||
TargetAnyTarget origTarget = ((TargetAnyTarget) target.getOriginalTarget());
|
||||
if (outcome.isGood()) {
|
||||
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
|
||||
targets = threats(abilityControllerId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
} else {
|
||||
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), game, target.getTargets());
|
||||
targets = threats(randomOpponentId, sourceId, ((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), game, target.getTargets());
|
||||
}
|
||||
|
||||
if (targets.isEmpty()) {
|
||||
|
@ -667,7 +665,7 @@ public class ComputerPlayer extends PlayerImpl implements Player {
|
|||
}
|
||||
|
||||
if (targets.isEmpty() && required) {
|
||||
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getCreatureFilter(), playerId, game);
|
||||
targets = game.getBattlefield().getActivePermanents(((FilterCreaturePlayerOrPlaneswalker) origTarget.getFilter()).getPermanentFilter(), playerId, game);
|
||||
}
|
||||
for (Permanent permanent : targets) {
|
||||
List<UUID> alreadyTargeted = target.getTargets();
|
||||
|
|
|
@ -33,9 +33,8 @@ public final class ArcTrail extends CardImpl {
|
|||
this.getSpellAbility().addTarget(target1);
|
||||
|
||||
FilterCreaturePlayerOrPlaneswalker filter2 = new FilterCreaturePlayerOrPlaneswalker("another creature, player or planeswalker to deal 1 damage");
|
||||
AnotherTargetPredicate predicate = new AnotherTargetPredicate(2);
|
||||
filter2.getCreatureFilter().add(predicate);
|
||||
filter2.getPlayerFilter().add(predicate);
|
||||
filter2.getPermanentFilter().add(new AnotherTargetPredicate(2));
|
||||
filter2.getPlayerFilter().add(new AnotherTargetPredicate(2));
|
||||
TargetAnyTarget target2 = new TargetAnyTarget(1, 1, filter2);
|
||||
target2.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target2);
|
||||
|
|
|
@ -32,14 +32,12 @@ public final class BondOfPassion extends CardImpl {
|
|||
|
||||
private static final FilterPermanent filter
|
||||
= new FilterCreaturePermanent();
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filter2
|
||||
private static final FilterCreaturePlayerOrPlaneswalker otherFilter
|
||||
= new FilterCreaturePlayerOrPlaneswalker("any other target");
|
||||
|
||||
static {
|
||||
filter.add(new AnotherTargetPredicate(1));
|
||||
filter2.getCreatureFilter().add(new AnotherTargetPredicate(2));
|
||||
filter2.getPlaneswalkerFilter().add(new AnotherTargetPredicate(2));
|
||||
filter2.getPlayerFilter().add(new AnotherTargetPredicate(2));
|
||||
otherFilter.getPlayerFilter().add(new AnotherTargetPredicate(2));
|
||||
otherFilter.getPlayerFilter().add(new AnotherTargetPredicate(2));
|
||||
}
|
||||
|
||||
public BondOfPassion(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -50,7 +48,7 @@ public final class BondOfPassion extends CardImpl {
|
|||
Target target = new TargetPermanent(filter);
|
||||
target.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
target = new TargetAnyTarget(filter2);
|
||||
target = new TargetAnyTarget(otherFilter);
|
||||
target.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.c;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -18,12 +16,12 @@ import mage.constants.Duration;
|
|||
import mage.constants.SubType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreaturePermanent;
|
||||
import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author anonymous
|
||||
*/
|
||||
public final class CauterySliver extends CardImpl {
|
||||
|
@ -43,10 +41,12 @@ public final class CauterySliver extends CardImpl {
|
|||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new GainAbilityAllEffect(ability1, Duration.WhileOnBattlefield, filter,
|
||||
"All Slivers have \"{1}, Sacrifice this permanent: This permanent deals 1 damage to any target.\"")));
|
||||
|
||||
// All Slivers have "{1}, Sacrifice this permanent: Prevent the next 1 damage that would be dealt to target Sliver creature or player this turn."
|
||||
// All Slivers have "{1}, Sacrifice this permanent: Prevent the next 1 damage that would be dealt to target player, planeswalker, or Sliver creature this turn."
|
||||
Ability ability2 = new SimpleActivatedAbility(Zone.BATTLEFIELD, new PreventDamageToTargetEffect(Duration.EndOfTurn, 1), new ManaCostsImpl("1"));
|
||||
ability2.addCost(new SacrificeSourceCost());
|
||||
ability2.addTarget(new TargetSliverCreatureOrPlayer());
|
||||
ability2.addTarget(new TargetAnyTarget(new FilterCreatureOrPlayerByType(SubType.SLIVER, "Sliver creature or player")));
|
||||
this.addAbility(new SimpleStaticAbility(Zone.BATTLEFIELD,
|
||||
new GainAbilityAllEffect(ability2, Duration.WhileOnBattlefield, filter,
|
||||
"All Slivers have \"{1}, Sacrifice this permanent: Prevent the next 1 damage that would be dealt to target Sliver creature or player this turn.\"")));
|
||||
|
@ -62,18 +62,10 @@ public final class CauterySliver extends CardImpl {
|
|||
}
|
||||
}
|
||||
|
||||
class TargetSliverCreatureOrPlayer extends TargetAnyTarget {
|
||||
|
||||
public TargetSliverCreatureOrPlayer() {
|
||||
super();
|
||||
filter = new FilterCreatureOrPlayerByType("Sliver", "Sliver creature or player");
|
||||
}
|
||||
}
|
||||
|
||||
class FilterCreatureOrPlayerByType extends FilterCreaturePlayerOrPlaneswalker {
|
||||
|
||||
public FilterCreatureOrPlayerByType(String type, String name) {
|
||||
public FilterCreatureOrPlayerByType(SubType subType, String name) {
|
||||
super(name);
|
||||
creatureFilter = new FilterCreaturePermanent(type);
|
||||
this.getPermanentFilter().add(subType.getPredicate());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,24 +24,23 @@ public final class ConeOfFlame extends CardImpl {
|
|||
public ConeOfFlame(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.SORCERY}, "{3}{R}{R}");
|
||||
|
||||
// Cone of Flame deals 1 damage to any target, 2 damage to another any target, and 3 damage to a third any target.
|
||||
FilterCreaturePlayerOrPlaneswalker filter1 = new FilterCreaturePlayerOrPlaneswalker("creature, player or planeswalker to deal 1 damage");
|
||||
// Cone of Flame deals 1 damage to any target, 2 damage to another target, and 3 damage to a third target.
|
||||
// 1
|
||||
FilterCreaturePlayerOrPlaneswalker filter1 = new FilterCreaturePlayerOrPlaneswalker("any target to deal 1 damage");
|
||||
TargetAnyTarget target1 = new TargetAnyTarget(1, 1, filter1);
|
||||
target1.setTargetTag(1);
|
||||
this.getSpellAbility().addTarget(target1);
|
||||
|
||||
FilterCreaturePlayerOrPlaneswalker filter2 = new FilterCreaturePlayerOrPlaneswalker("another creature, player or planeswalker to deal 2 damage");
|
||||
AnotherTargetPredicate predicate2 = new AnotherTargetPredicate(2);
|
||||
filter2.getCreatureFilter().add(predicate2);
|
||||
filter2.getPlayerFilter().add(predicate2);
|
||||
// 2
|
||||
FilterCreaturePlayerOrPlaneswalker filter2 = new FilterCreaturePlayerOrPlaneswalker("another target to deal 2 damage");
|
||||
filter2.getPermanentFilter().add(new AnotherTargetPredicate(2));
|
||||
filter2.getPlayerFilter().add(new AnotherTargetPredicate(2));
|
||||
TargetAnyTarget target2 = new TargetAnyTarget(1, 1, filter2);
|
||||
target2.setTargetTag(2);
|
||||
this.getSpellAbility().addTarget(target2);
|
||||
|
||||
FilterCreaturePlayerOrPlaneswalker filter3 = new FilterCreaturePlayerOrPlaneswalker("another creature, player or planeswalker to deal 3 damage");
|
||||
AnotherTargetPredicate predicate3 = new AnotherTargetPredicate(3);
|
||||
filter3.getCreatureFilter().add(predicate3);
|
||||
filter3.getPlayerFilter().add(predicate3);
|
||||
// 3
|
||||
FilterCreaturePlayerOrPlaneswalker filter3 = new FilterCreaturePlayerOrPlaneswalker("third target to deal 3 damage");
|
||||
filter3.getPermanentFilter().add(new AnotherTargetPredicate(3));
|
||||
filter3.getPlayerFilter().add(new AnotherTargetPredicate(3));
|
||||
TargetAnyTarget target3 = new TargetAnyTarget(1, 1, filter3);
|
||||
target3.setTargetTag(3);
|
||||
this.getSpellAbility().addTarget(target3);
|
||||
|
|
|
@ -43,9 +43,8 @@ public final class DrakusethMawOfFlames extends CardImpl {
|
|||
target.setTargetTag(1);
|
||||
ability.addTarget(target);
|
||||
FilterCreaturePlayerOrPlaneswalker filter = new FilterCreaturePlayerOrPlaneswalker("any target");
|
||||
filter.getCreatureFilter().add(new AnotherTargetPredicate(2, true));
|
||||
filter.getPlayerFilter().add(new AnotherTargetPredicate(2, true));
|
||||
filter.getPlaneswalkerFilter().add(new AnotherTargetPredicate(2, true));
|
||||
filter.getPermanentFilter().add(new AnotherTargetPredicate(2, true));
|
||||
target = new TargetAnyTarget(0, 2, filter).withChooseHint("to deal 3 damage");
|
||||
target.setTargetTag(2);
|
||||
ability.addTarget(target);
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.e;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.PreventAllDamageToAllEffect;
|
||||
import mage.cards.CardImpl;
|
||||
import mage.cards.CardSetInfo;
|
||||
|
@ -10,26 +8,26 @@ import mage.constants.Duration;
|
|||
import mage.constants.TargetController;
|
||||
import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jeffwadsworth
|
||||
*/
|
||||
public final class Endure extends CardImpl {
|
||||
|
||||
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filter = new FilterCreaturePlayerOrPlaneswalker("you and permanents you control");
|
||||
|
||||
static {
|
||||
filter.getCreatureFilter().add(TargetController.YOU.getControllerPredicate());
|
||||
filter.getPermanentFilter().add(TargetController.YOU.getControllerPredicate());
|
||||
filter.getPlayerFilter().add(TargetController.YOU.getPlayerPredicate());
|
||||
}
|
||||
|
||||
public Endure(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{3}{W}{W}");
|
||||
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{3}{W}{W}");
|
||||
|
||||
// Prevent all damage that would be dealt to you and permanents you control this turn.
|
||||
this.getSpellAbility().addEffect(new PreventAllDamageToAllEffect(Duration.EndOfTurn, filter));
|
||||
|
||||
|
||||
}
|
||||
|
||||
public Endure(final Endure card) {
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.i;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageInt;
|
||||
import mage.abilities.Ability;
|
||||
import mage.abilities.common.SimpleActivatedAbility;
|
||||
|
@ -16,17 +14,15 @@ import mage.constants.Zone;
|
|||
import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
|
||||
import mage.target.common.TargetAnyTarget;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Styxo
|
||||
*/
|
||||
public final class ImperialGunner extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filter = new FilterCreaturePlayerOrPlaneswalker("target player, planeswalker or Starship creature");
|
||||
|
||||
static {
|
||||
filter.getCreatureFilter().add(SubType.STARSHIP.getPredicate());
|
||||
}
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filter = new FilterCreaturePlayerOrPlaneswalker(
|
||||
"target player, planeswalker or Starship creature", SubType.STARSHIP);
|
||||
|
||||
public ImperialGunner(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId, setInfo, new CardType[]{CardType.CREATURE}, "{R}");
|
||||
|
@ -35,7 +31,7 @@ public final class ImperialGunner extends CardImpl {
|
|||
this.power = new MageInt(1);
|
||||
this.toughness = new MageInt(2);
|
||||
|
||||
// {1},{T}:Imperial Gunner deals 1 damage to target player or Starship creature.
|
||||
// {1},{T}: Imperial Gunner deals 1 damage to target player or Starship creature.
|
||||
Ability ability = new SimpleActivatedAbility(Zone.BATTLEFIELD, new DamageTargetEffect(1), new ManaCostsImpl("{1}"));
|
||||
ability.addTarget(new TargetAnyTarget(filter));
|
||||
ability.addCost(new TapSourceCost());
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.n;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.MageItem;
|
||||
import mage.MageObject;
|
||||
import mage.abilities.effects.Effect;
|
||||
|
@ -17,18 +15,18 @@ import mage.players.Player;
|
|||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.watchers.common.DamageDoneWatcher;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Quercitron
|
||||
*/
|
||||
public final class NeedleDrop extends CardImpl {
|
||||
|
||||
private static final FilterCreaturePlayerOrPlaneswalker FILTER = new FilterCreaturePlayerOrPlaneswalker();
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filer = new FilterCreaturePlayerOrPlaneswalker();
|
||||
|
||||
static {
|
||||
FILTER.getCreatureFilter().add(new DamagedThisTurnPredicate());
|
||||
FILTER.getPlaneswalkerFilter().add(new DamagedThisTurnPredicate());
|
||||
FILTER.getPlayerFilter().add(new DamagedThisTurnPredicate());
|
||||
filer.getPlayerFilter().add(new DamagedThisTurnPredicate());
|
||||
filer.getPermanentFilter().add(new DamagedThisTurnPredicate());
|
||||
}
|
||||
|
||||
public NeedleDrop(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -38,7 +36,7 @@ public final class NeedleDrop extends CardImpl {
|
|||
Effect effect = new DamageTargetEffect(1);
|
||||
effect.setText("{this} deals 1 damage to any target that was dealt damage this turn");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget(1, 1, FILTER));
|
||||
this.getSpellAbility().addTarget(new TargetAnyTarget(1, 1, filer));
|
||||
|
||||
// Draw a card.
|
||||
this.getSpellAbility().addEffect(new DrawCardSourceControllerEffect(1));
|
||||
|
|
|
@ -7,6 +7,7 @@ import mage.abilities.effects.ContinuousEffect;
|
|||
import mage.abilities.effects.OneShotEffect;
|
||||
import mage.abilities.effects.common.DamageTargetEffect;
|
||||
import mage.abilities.effects.common.ExileAllEffect;
|
||||
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
|
||||
import mage.cards.*;
|
||||
import mage.constants.*;
|
||||
import mage.filter.FilterCard;
|
||||
|
@ -20,27 +21,25 @@ import mage.target.Target;
|
|||
import mage.target.common.TargetAnyTarget;
|
||||
import mage.target.common.TargetCardInHand;
|
||||
import mage.target.common.TargetOpponent;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.common.asthought.PlayFromNotOwnHandZoneTargetEffect;
|
||||
import mage.target.targetpointer.FixedTarget;
|
||||
|
||||
/**
|
||||
* @author Will
|
||||
*/
|
||||
public final class NicolBolasGodPharaoh extends CardImpl {
|
||||
|
||||
private static final FilterPermanent filter = new FilterNonlandPermanent();
|
||||
private static final FilterCreaturePlayerOrPlaneswalker filter2
|
||||
private static final FilterCreaturePlayerOrPlaneswalker damageFilter
|
||||
= new FilterCreaturePlayerOrPlaneswalker("opponent, creature an opponent controls, or planeswalker an opponent controls.");
|
||||
private static final FilterPermanent exileFilter = new FilterNonlandPermanent();
|
||||
|
||||
static {
|
||||
filter.add(TargetController.OPPONENT.getControllerPredicate());
|
||||
filter2.getPlayerFilter().add(TargetController.OPPONENT.getPlayerPredicate());
|
||||
filter2.getCreatureFilter().add(TargetController.OPPONENT.getControllerPredicate());
|
||||
filter2.getPlaneswalkerFilter().add(TargetController.OPPONENT.getControllerPredicate());
|
||||
damageFilter.getPlayerFilter().add(TargetController.OPPONENT.getPlayerPredicate());
|
||||
damageFilter.getPermanentFilter().add(TargetController.OPPONENT.getControllerPredicate());
|
||||
exileFilter.add(TargetController.OPPONENT.getControllerPredicate());
|
||||
}
|
||||
|
||||
public NicolBolasGodPharaoh(UUID ownerId, CardSetInfo setInfo) {
|
||||
|
@ -58,13 +57,13 @@ public final class NicolBolasGodPharaoh extends CardImpl {
|
|||
// +1: Each opponent exiles two cards from their hand.
|
||||
this.addAbility(new LoyaltyAbility(new NicolBolasGodPharaohPlusOneEffect(), 1));
|
||||
|
||||
// -4: Nicol Bolas, God-Pharaoh deals 7 damage to any target.
|
||||
// -4: Nicol Bolas, God-Pharaoh deals 7 damage to target opponent, creature an opponent controls, or planeswalker an opponent controls.
|
||||
ability = new LoyaltyAbility(new DamageTargetEffect(7), -4);
|
||||
ability.addTarget(new TargetAnyTarget(filter2));
|
||||
ability.addTarget(new TargetAnyTarget(damageFilter));
|
||||
this.addAbility(ability);
|
||||
|
||||
// -12: Exile each nonland permanent your opponents control.
|
||||
this.addAbility(new LoyaltyAbility(new ExileAllEffect(filter)
|
||||
this.addAbility(new LoyaltyAbility(new ExileAllEffect(exileFilter)
|
||||
.setText("exile each nonland permanent your opponents control"), -12));
|
||||
}
|
||||
|
||||
|
@ -168,7 +167,7 @@ class NicolBolasGodPharaohPlusTwoEffect extends OneShotEffect {
|
|||
if (card.isLand()) {
|
||||
continue;
|
||||
}
|
||||
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.EndOfTurn, true);
|
||||
ContinuousEffect effect = new PlayFromNotOwnHandZoneTargetEffect(Zone.EXILED, TargetController.YOU, Duration.EndOfTurn, true);
|
||||
effect.setTargetPointer(new FixedTarget(card, game));
|
||||
game.addEffect(effect, source);
|
||||
break;
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
|
||||
package mage.cards.t;
|
||||
|
||||
import java.util.UUID;
|
||||
import mage.abilities.effects.Effect;
|
||||
import mage.abilities.effects.common.DamageMultiEffect;
|
||||
import mage.cards.CardImpl;
|
||||
|
@ -9,21 +7,21 @@ import mage.cards.CardSetInfo;
|
|||
import mage.constants.CardType;
|
||||
import mage.target.common.TargetAnyTargetAmount;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author LevelX2
|
||||
*/
|
||||
public final class TwinBolt extends CardImpl {
|
||||
|
||||
public TwinBolt(UUID ownerId, CardSetInfo setInfo) {
|
||||
super(ownerId,setInfo,new CardType[]{CardType.INSTANT},"{1}{R}");
|
||||
super(ownerId, setInfo, new CardType[]{CardType.INSTANT}, "{1}{R}");
|
||||
|
||||
// Twin Bolt deals 2 damage divided as you choose among one or two target creatures and/or players.
|
||||
Effect effect = new DamageMultiEffect(2);
|
||||
effect.setText("{this} deals 2 damage divided as you choose among one or two target creatures and/or players");
|
||||
this.getSpellAbility().addEffect(effect);
|
||||
this.getSpellAbility().addTarget(new TargetAnyTargetAmount(2));
|
||||
|
||||
}
|
||||
|
||||
public TwinBolt(final TwinBolt card) {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
package org.mage.test.cards.single.m11;
|
||||
|
||||
import mage.constants.PhaseStep;
|
||||
import mage.constants.Zone;
|
||||
import mage.counters.CounterType;
|
||||
import org.junit.Test;
|
||||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* @author JayDi85
|
||||
*/
|
||||
public class InfernoTitanTest extends CardTestPlayerBase {
|
||||
|
||||
@Test
|
||||
public void test_MustAbleToTargetPlaneswalkers() {
|
||||
// bug: https://github.com/magefree/mage/issues/7276
|
||||
|
||||
// Whenever Inferno Titan enters the battlefield or attacks, it deals 3 damage divided as you choose among one, two, or three targets.
|
||||
addCard(Zone.HAND, playerA, "Inferno Titan"); // {4}{R}{R}
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Mountain", 6);
|
||||
//
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Chandra, Acolyte of Flame", 1); // 4
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); // 2/2
|
||||
|
||||
// cast and devide damage (2x to creature and 1x to planeswalker)
|
||||
castSpell(1, PhaseStep.PRECOMBAT_MAIN, playerA, "Inferno Titan");
|
||||
addTargetAmount(playerA, "Grizzly Bears", 2);
|
||||
addTargetAmount(playerA, "Chandra, Acolyte of Flame", 1);
|
||||
|
||||
setStrictChooseMode(true);
|
||||
setStopAt(1, PhaseStep.END_TURN);
|
||||
execute();
|
||||
assertAllCommandsUsed();
|
||||
|
||||
assertPermanentCount(playerA, "Inferno Titan", 1);
|
||||
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||
assertCounterCount(playerA, "Chandra, Acolyte of Flame", CounterType.LOYALTY, 4 - 1);
|
||||
}
|
||||
}
|
|
@ -8,61 +8,61 @@ import org.junit.Test;
|
|||
import org.mage.test.serverside.base.CardTestPlayerBase;
|
||||
|
||||
/**
|
||||
* 4RR
|
||||
* Creature - Angel
|
||||
* Flying
|
||||
*
|
||||
* Whenever a source an opponent controls deals damage to you or a permanent you control,
|
||||
* you may have Flameblade Angel deal 1 damage to that source's controller.
|
||||
*
|
||||
* 4RR
|
||||
* Creature - Angel
|
||||
* Flying
|
||||
* <p>
|
||||
* Whenever a source an opponent controls deals damage to you or a permanent you control,
|
||||
* you may have Flameblade Angel deal 1 damage to that source's controller.
|
||||
*
|
||||
* @author escplan9 (Derek Monturo - dmontur1 at gmail dot com)
|
||||
*/
|
||||
public class FlamebladeAngelTest extends CardTestPlayerBase {
|
||||
|
||||
|
||||
/**
|
||||
* Reported bug: Not triggering when damage is dealt to the creatures I control.
|
||||
*/
|
||||
@Test
|
||||
public void testDamageToCreature() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Flameblade Angel");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Wall of Roots"); // 0/5
|
||||
addCard(Zone.HAND, playerB, "Shock"); // instant deals 2 dmg to creature/player
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain");
|
||||
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock");
|
||||
addTarget(playerB, "Wall of Roots");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
Permanent roots = getPermanent("Wall of Roots", playerA);
|
||||
Assert.assertEquals("Wall of Roots should have 2 damage dealt to it", 2, roots.getDamage());
|
||||
assertGraveyardCount(playerB, "Shock", 1);
|
||||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 19); // Angel should deal 1 damage to Shock's controller
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reported bug: Not triggering when damage is dealt to the creatures I control.
|
||||
*/
|
||||
@Test
|
||||
public void testDamageToMultipleCreatures() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Flameblade Angel");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Wall of Roots"); // 0/5
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); // 2/2
|
||||
addCard(Zone.HAND, playerB, "Shock", 2); // instant deals 2 dmg to creature/player
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Mountain", 2);
|
||||
|
||||
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock");
|
||||
addTarget(playerB, "Wall of Roots");
|
||||
castSpell(2, PhaseStep.PRECOMBAT_MAIN, playerB, "Shock");
|
||||
addTarget(playerB, "Grizzly Bears");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.BEGIN_COMBAT);
|
||||
execute();
|
||||
|
||||
|
||||
Permanent roots = getPermanent("Wall of Roots", playerA);
|
||||
Assert.assertEquals("Wall of Roots should have 2 damage dealt to it", 2, roots.getDamage());
|
||||
assertGraveyardCount(playerB, "Shock", 2);
|
||||
|
@ -70,27 +70,27 @@ public class FlamebladeAngelTest extends CardTestPlayerBase {
|
|||
assertLife(playerA, 20);
|
||||
assertLife(playerB, 18); // Angel should deal 1 damage twice to Shock's controller
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reported bug: Not triggering when damage is dealt to the creatures I control.
|
||||
*/
|
||||
@Test
|
||||
public void testCombatDamageToCreatures() {
|
||||
|
||||
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Flameblade Angel");
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Wall of Roots"); // 0/5
|
||||
addCard(Zone.BATTLEFIELD, playerA, "Grizzly Bears"); // 2/2
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Elite Vanguard"); // 2/1
|
||||
addCard(Zone.BATTLEFIELD, playerB, "Hill Giant"); // 3/3
|
||||
|
||||
|
||||
attack(2, playerB, "Elite Vanguard");
|
||||
attack(2, playerB, "Hill Giant");
|
||||
block(2, playerA, "Wall of Roots", "Hill Giant");
|
||||
block(2, playerA, "Grizzly Bears", "Elite Vanguard");
|
||||
|
||||
|
||||
setStopAt(2, PhaseStep.POSTCOMBAT_MAIN);
|
||||
execute();
|
||||
|
||||
|
||||
Permanent roots = getPermanent("Wall of Roots", playerA);
|
||||
Assert.assertEquals("Wall of Roots should have 3 damage dealt to it", 3, roots.getDamage());
|
||||
assertGraveyardCount(playerA, "Grizzly Bears", 1);
|
||||
|
|
|
@ -2281,9 +2281,6 @@ public class TestPlayer implements Player {
|
|||
if (filter instanceof FilterCreatureOrPlayer) {
|
||||
filter = ((FilterCreatureOrPlayer) filter).getCreatureFilter();
|
||||
}
|
||||
if (filter instanceof FilterCreaturePlayerOrPlaneswalker) {
|
||||
filter = ((FilterCreaturePlayerOrPlaneswalker) filter).getCreatureFilter();
|
||||
}
|
||||
if (filter instanceof FilterPermanentOrPlayer) {
|
||||
filter = ((FilterPermanentOrPlayer) filter).getPermanentFilter();
|
||||
}
|
||||
|
|
|
@ -1,72 +1,48 @@
|
|||
package mage.filter.common;
|
||||
|
||||
import mage.MageItem;
|
||||
import mage.game.Game;
|
||||
import mage.game.permanent.Permanent;
|
||||
import mage.players.Player;
|
||||
import mage.MageObject;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.SubType;
|
||||
import mage.filter.predicate.Predicate;
|
||||
import mage.filter.predicate.Predicates;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* If you add predicate to permanentFilter then it will be applied to planeswalker too
|
||||
*
|
||||
* @author JRHerlehy Created on 4/8/18.
|
||||
*/
|
||||
public class FilterCreaturePlayerOrPlaneswalker extends FilterPermanentOrPlayer {
|
||||
|
||||
protected FilterCreaturePermanent creatureFilter;
|
||||
protected FilterPlaneswalkerPermanent planeswalkerFilter;
|
||||
|
||||
public FilterCreaturePlayerOrPlaneswalker() {
|
||||
this("any target");
|
||||
}
|
||||
|
||||
public FilterCreaturePlayerOrPlaneswalker(String name) {
|
||||
this(name, (SubType) null);
|
||||
}
|
||||
|
||||
public FilterCreaturePlayerOrPlaneswalker(String name, SubType... andCreatureTypes) {
|
||||
super(name);
|
||||
creatureFilter = new FilterCreaturePermanent();
|
||||
planeswalkerFilter = new FilterPlaneswalkerPermanent();
|
||||
List<Predicate<MageObject>> allCreaturePredicates = Arrays.stream(andCreatureTypes)
|
||||
.filter(Objects::nonNull)
|
||||
.map(SubType::getPredicate)
|
||||
.collect(Collectors.toList());
|
||||
allCreaturePredicates.add(0, CardType.CREATURE.getPredicate());
|
||||
Predicate<MageObject> planeswalkerPredicate = CardType.PLANESWALKER.getPredicate();
|
||||
|
||||
this.permanentFilter.add(Predicates.or(
|
||||
Predicates.and(allCreaturePredicates),
|
||||
planeswalkerPredicate
|
||||
));
|
||||
}
|
||||
|
||||
public FilterCreaturePlayerOrPlaneswalker(final FilterCreaturePlayerOrPlaneswalker filter) {
|
||||
super(filter);
|
||||
this.creatureFilter = filter.creatureFilter.copy();
|
||||
this.planeswalkerFilter = filter.planeswalkerFilter.copy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(MageItem o, Game game) {
|
||||
if (super.match(o, game)) {
|
||||
if (o instanceof Player) {
|
||||
return playerFilter.match((Player) o, game);
|
||||
} else if (o instanceof Permanent) {
|
||||
return creatureFilter.match((Permanent) o, game)
|
||||
|| planeswalkerFilter.match((Permanent) o, game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean match(MageItem o, UUID sourceId, UUID playerId, Game game) {
|
||||
if (super.match(o, game)) { // process predicates
|
||||
if (o instanceof Player) {
|
||||
return playerFilter.match((Player) o, sourceId, playerId, game);
|
||||
} else if (o instanceof Permanent) {
|
||||
return creatureFilter.match((Permanent) o, sourceId, playerId, game)
|
||||
|| planeswalkerFilter.match((Permanent) o, sourceId, playerId, game);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public FilterCreaturePermanent getCreatureFilter() {
|
||||
return this.creatureFilter;
|
||||
}
|
||||
|
||||
public FilterPlaneswalkerPermanent getPlaneswalkerFilter() {
|
||||
return this.planeswalkerFilter;
|
||||
}
|
||||
|
||||
public void setCreatureFilter(FilterCreaturePermanent creatureFilter) {
|
||||
this.creatureFilter = creatureFilter;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -116,7 +116,7 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
}
|
||||
}
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(permanent, sourceId, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
|
@ -125,15 +125,6 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
}
|
||||
}
|
||||
|
||||
for (Permanent planeswalker : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) {
|
||||
if (planeswalker.canBeTargetedBy(targetSource, sourceControllerId, game) && filter.match(planeswalker, sourceId, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -160,7 +151,7 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
}
|
||||
}
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (filter.match(permanent, null, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
|
@ -169,15 +160,6 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
}
|
||||
}
|
||||
|
||||
for (Permanent planeswalker : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) {
|
||||
if (filter.match(planeswalker, null, sourceControllerId, game)) {
|
||||
count++;
|
||||
if (count >= this.minNumberOfTargets) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -190,25 +172,18 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
Player player = game.getPlayer(playerId);
|
||||
if (player != null
|
||||
&& player.canBeTargetedBy(targetSource, sourceControllerId, game)
|
||||
&& filter.getPlayerFilter().match(player, sourceId, sourceControllerId, game)) {
|
||||
&& filter.match(player, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (permanent.canBeTargetedBy(targetSource, sourceControllerId, game)
|
||||
&& filter.getCreatureFilter().match(permanent, sourceId, sourceControllerId, game)) {
|
||||
&& filter.match(permanent, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
}
|
||||
}
|
||||
|
||||
for (Permanent planeswalker : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) {
|
||||
if (planeswalker.canBeTargetedBy(targetSource, sourceControllerId, game)
|
||||
&& filter.getPlaneswalkerFilter().match(planeswalker, sourceId, sourceControllerId, game)) {
|
||||
possibleTargets.add(planeswalker.getId());
|
||||
}
|
||||
}
|
||||
|
||||
return possibleTargets;
|
||||
}
|
||||
|
||||
|
@ -218,23 +193,17 @@ public class TargetAnyTarget extends TargetImpl {
|
|||
|
||||
for (UUID playerId : game.getState().getPlayersInRange(sourceControllerId, game)) {
|
||||
Player player = game.getPlayer(playerId);
|
||||
if (player != null && filter.getPlayerFilter().match(player, game)) {
|
||||
if (player != null && filter.match(player, game)) {
|
||||
possibleTargets.add(playerId);
|
||||
}
|
||||
}
|
||||
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getCreatureFilter(), sourceControllerId, game)) {
|
||||
if (filter.getCreatureFilter().match(permanent, null, sourceControllerId, game)) {
|
||||
for (Permanent permanent : game.getBattlefield().getActivePermanents(filter.getPermanentFilter(), sourceControllerId, game)) {
|
||||
if (filter.getPermanentFilter().match(permanent, null, sourceControllerId, game)) {
|
||||
possibleTargets.add(permanent.getId());
|
||||
}
|
||||
}
|
||||
|
||||
for (Permanent planeswalker : game.getBattlefield().getActivePermanents(filter.getPlaneswalkerFilter(), sourceControllerId, game)) {
|
||||
if (filter.getPlaneswalkerFilter().match(planeswalker, null, sourceControllerId, game)) {
|
||||
possibleTargets.add(planeswalker.getId());
|
||||
}
|
||||
}
|
||||
|
||||
return possibleTargets;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,23 +2,17 @@ package mage.target.common;
|
|||
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.abilities.dynamicvalue.common.StaticValue;
|
||||
import mage.constants.CardType;
|
||||
import mage.constants.Zone;
|
||||
import mage.filter.common.FilterCreaturePlayerOrPlaneswalker;
|
||||
import mage.filter.common.FilterPermanentOrPlayer;
|
||||
|
||||
/**
|
||||
* @author BetaSteward_at_googlemail.com
|
||||
*/
|
||||
public class TargetAnyTargetAmount extends TargetPermanentOrPlayerAmount {
|
||||
|
||||
private static final FilterPermanentOrPlayer defaultFilter
|
||||
private static final FilterCreaturePlayerOrPlaneswalker defaultFilter
|
||||
= new FilterCreaturePlayerOrPlaneswalker("targets");
|
||||
|
||||
static {
|
||||
defaultFilter.getPermanentFilter().add(CardType.CREATURE.getPredicate());
|
||||
}
|
||||
|
||||
public TargetAnyTargetAmount(int amount) {
|
||||
this(amount, 0);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
package mage.target.common;
|
||||
|
||||
import mage.abilities.dynamicvalue.DynamicValue;
|
||||
import mage.filter.FilterPermanent;
|
||||
import mage.filter.common.FilterCreatureOrPlaneswalkerPermanent;
|
||||
|
||||
|
@ -16,18 +15,10 @@ public class TargetCreatureOrPlaneswalkerAmount extends TargetPermanentAmount {
|
|||
super(amount, defaultFilter);
|
||||
}
|
||||
|
||||
public TargetCreatureOrPlaneswalkerAmount(DynamicValue amount) {
|
||||
super(amount, defaultFilter);
|
||||
}
|
||||
|
||||
public TargetCreatureOrPlaneswalkerAmount(int amount, FilterPermanent filter) {
|
||||
super(amount, filter);
|
||||
}
|
||||
|
||||
public TargetCreatureOrPlaneswalkerAmount(DynamicValue amount, FilterPermanent filter) {
|
||||
super(amount, filter);
|
||||
}
|
||||
|
||||
private TargetCreatureOrPlaneswalkerAmount(final TargetCreatureOrPlaneswalkerAmount target) {
|
||||
super(target);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue