mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Fix attacking self with Kaalia trigger
This commit is contained in:
@@ -770,6 +770,7 @@ public class AiController {
|
|||||||
// one is warded and can't be paid for.
|
// one is warded and can't be paid for.
|
||||||
if (sa.usesTargeting()) {
|
if (sa.usesTargeting()) {
|
||||||
for (Card tgt : sa.getTargets().getTargetCards()) {
|
for (Card tgt : sa.getTargets().getTargetCards()) {
|
||||||
|
// TODO some older cards don't use the keyword, so check for trigger instead
|
||||||
if (tgt.hasKeyword(Keyword.WARD) && tgt.isInPlay() && tgt.getController().isOpponentOf(sa.getHostCard().getController())) {
|
if (tgt.hasKeyword(Keyword.WARD) && tgt.isInPlay() && tgt.getController().isOpponentOf(sa.getHostCard().getController())) {
|
||||||
int amount = 0;
|
int amount = 0;
|
||||||
Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt);
|
Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt);
|
||||||
|
|||||||
@@ -2497,4 +2497,27 @@ public class ComputerUtilCombat {
|
|||||||
}
|
}
|
||||||
return poison;
|
return poison;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static GameEntity addAttackerToCombat(SpellAbility sa, Card attacker, FCollection<GameEntity> defenders) {
|
||||||
|
Combat combat = sa.getHostCard().getGame().getCombat();
|
||||||
|
if (combat != null) {
|
||||||
|
// 1. If the card that spawned the attacker was sent at a planeswalker, attack the same. Consider improving.
|
||||||
|
GameEntity def = combat.getDefenderByAttacker(sa.getHostCard());
|
||||||
|
if (def != null && def instanceof Card) {
|
||||||
|
if (((Card)def).isPlaneswalker()) {
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably.
|
||||||
|
for (GameEntity p : defenders) {
|
||||||
|
if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
if (p instanceof Card && !ComputerUtilCard.canBeBlockedProfitably(((Card)p).getController(), attacker)) {
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Iterables.getFirst(defenders, null);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -452,21 +452,15 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Attach to player ai preferences.
|
* Attach to player ai preferences.
|
||||||
*
|
|
||||||
* @param sa
|
* @param sa
|
||||||
* the sa
|
* the sa
|
||||||
* @param mandatory
|
* @param mandatory
|
||||||
* the mandatory
|
* the mandatory
|
||||||
|
* @param newParam TODO
|
||||||
|
*
|
||||||
* @return the player
|
* @return the player
|
||||||
*/
|
*/
|
||||||
public static Player attachToPlayerAIPreferences(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
|
public static Player attachToPlayerAIPreferences(final Player aiPlayer, final SpellAbility sa, final boolean mandatory, List<Player> targetable) {
|
||||||
List<Player> targetable = new ArrayList<>();
|
|
||||||
for (final Player player : aiPlayer.getGame().getPlayers()) {
|
|
||||||
if (sa.canTarget(player)) {
|
|
||||||
targetable.add(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ("Curse".equals(sa.getParam("AILogic"))) {
|
if ("Curse".equals(sa.getParam("AILogic"))) {
|
||||||
if (!mandatory) {
|
if (!mandatory) {
|
||||||
targetable.removeAll(aiPlayer.getAllies());
|
targetable.removeAll(aiPlayer.getAllies());
|
||||||
@@ -1020,7 +1014,13 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
private static boolean attachPreference(final SpellAbility sa, final TargetRestrictions tgt, final boolean mandatory) {
|
private static boolean attachPreference(final SpellAbility sa, final TargetRestrictions tgt, final boolean mandatory) {
|
||||||
GameObject o;
|
GameObject o;
|
||||||
if (tgt.canTgtPlayer()) {
|
if (tgt.canTgtPlayer()) {
|
||||||
o = attachToPlayerAIPreferences(sa.getActivatingPlayer(), sa, mandatory);
|
List<Player> targetable = new ArrayList<>();
|
||||||
|
for (final Player player : sa.getHostCard().getGame().getPlayers()) {
|
||||||
|
if (sa.canTarget(player)) {
|
||||||
|
targetable.add(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o = attachToPlayerAIPreferences(sa.getActivatingPlayer(), sa, mandatory, targetable);
|
||||||
} else {
|
} else {
|
||||||
o = attachToCardAIPreferences(sa.getActivatingPlayer(), sa, mandatory);
|
o = attachToCardAIPreferences(sa.getActivatingPlayer(), sa, mandatory);
|
||||||
}
|
}
|
||||||
@@ -1459,10 +1459,12 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
public static Card attachGeneralAI(final Player ai, final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
public static Card attachGeneralAI(final Player ai, final SpellAbility sa, final List<Card> list, final boolean mandatory,
|
||||||
final Card attachSource, final String logic) {
|
final Card attachSource, final String logic) {
|
||||||
Player prefPlayer = AiAttackController.choosePreferredDefenderPlayer(ai);
|
Player prefPlayer;
|
||||||
if ("Pump".equals(logic) || "Animate".equals(logic) || "Curiosity".equals(logic) || "MoveTgtAura".equals(logic)
|
if ("Pump".equals(logic) || "Animate".equals(logic) || "Curiosity".equals(logic) || "MoveTgtAura".equals(logic)
|
||||||
|| "MoveAllAuras".equals(logic)) {
|
|| "MoveAllAuras".equals(logic)) {
|
||||||
prefPlayer = ai;
|
prefPlayer = ai;
|
||||||
|
} else {
|
||||||
|
prefPlayer = AiAttackController.choosePreferredDefenderPlayer(ai);
|
||||||
}
|
}
|
||||||
// Some ChangeType cards are beneficial, and PrefPlayer should be
|
// Some ChangeType cards are beneficial, and PrefPlayer should be
|
||||||
// changed to represent that
|
// changed to represent that
|
||||||
@@ -1765,6 +1767,6 @@ public class AttachAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||||
return attachToPlayerAIPreferences(ai, sa, true);
|
return attachToPlayerAIPreferences(ai, sa, true, (List<Player>)options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import forge.ai.SpellAbilityAi;
|
|||||||
import forge.ai.SpellApiToAi;
|
import forge.ai.SpellApiToAi;
|
||||||
import forge.card.MagicColor;
|
import forge.card.MagicColor;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.GameObject;
|
import forge.game.GameObject;
|
||||||
import forge.game.GlobalRuleChange;
|
import forge.game.GlobalRuleChange;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
@@ -50,6 +51,7 @@ import forge.game.spellability.TargetRestrictions;
|
|||||||
import forge.game.staticability.StaticAbilityMustTarget;
|
import forge.game.staticability.StaticAbilityMustTarget;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.collect.FCollection;
|
||||||
|
|
||||||
public class ChangeZoneAi extends SpellAbilityAi {
|
public class ChangeZoneAi extends SpellAbilityAi {
|
||||||
/*
|
/*
|
||||||
@@ -423,7 +425,6 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
}
|
}
|
||||||
return canBouncePermanent(ai, sa, list) != null;
|
return canBouncePermanent(ai, sa, list) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ComputerUtil.playImmediately(ai, sa)) {
|
if (ComputerUtil.playImmediately(ai, sa)) {
|
||||||
@@ -1784,8 +1785,20 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||||
// Called when attaching Aura to player
|
// Called when attaching Aura to player or adding creature to combat
|
||||||
return AttachAi.attachToPlayerAIPreferences(ai, sa, true);
|
if (params.containsKey("Attacker")) {
|
||||||
|
return (Player) ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
|
return AttachAi.attachToPlayerAIPreferences(ai, sa, true, (List<Player>)options);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
||||||
|
if (params.containsKey("Attacker")) {
|
||||||
|
return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
|
// should not be reached
|
||||||
|
return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean doSacAndReturnFromGraveLogic(final Player ai, final SpellAbility sa) {
|
private boolean doSacAndReturnFromGraveLogic(final Player ai, final SpellAbility sa) {
|
||||||
|
|||||||
@@ -12,10 +12,12 @@ import forge.ai.AiPlayDecision;
|
|||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilAbility;
|
import forge.ai.ComputerUtilAbility;
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.SpecialCardAi;
|
import forge.ai.SpecialCardAi;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityKey;
|
import forge.game.ability.AbilityKey;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
@@ -32,6 +34,7 @@ import forge.game.player.PlayerActionConfirmMode;
|
|||||||
import forge.game.player.PlayerCollection;
|
import forge.game.player.PlayerCollection;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.collect.FCollection;
|
||||||
|
|
||||||
public class CopyPermanentAi extends SpellAbilityAi {
|
public class CopyPermanentAi extends SpellAbilityAi {
|
||||||
@Override
|
@Override
|
||||||
@@ -244,9 +247,21 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||||
|
if (params.containsKey("Attacker")) {
|
||||||
|
return (Player) ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
final List<Card> cards = new PlayerCollection(options).getCreaturesInPlay();
|
final List<Card> cards = new PlayerCollection(options).getCreaturesInPlay();
|
||||||
Card chosen = ComputerUtilCard.getBestCreatureAI(cards);
|
Card chosen = ComputerUtilCard.getBestCreatureAI(cards);
|
||||||
return chosen != null ? chosen.getController() : Iterables.getFirst(options, null);
|
return chosen != null ? chosen.getController() : Iterables.getFirst(options, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
||||||
|
if (params.containsKey("Attacker")) {
|
||||||
|
return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
|
// should not be reached
|
||||||
|
return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ import forge.ai.AiAttackController;
|
|||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilAbility;
|
import forge.ai.ComputerUtilAbility;
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.SpecialCardAi;
|
import forge.ai.SpecialCardAi;
|
||||||
import forge.ai.SpellAbilityAi;
|
import forge.ai.SpellAbilityAi;
|
||||||
import forge.game.Game;
|
import forge.game.Game;
|
||||||
|
import forge.game.GameEntity;
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.card.CardCollection;
|
import forge.game.card.CardCollection;
|
||||||
@@ -25,6 +27,7 @@ import forge.game.player.PlayerPredicates;
|
|||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.TextUtil;
|
import forge.util.TextUtil;
|
||||||
|
import forge.util.collect.FCollection;
|
||||||
|
|
||||||
|
|
||||||
public class DigAi extends SpellAbilityAi {
|
public class DigAi extends SpellAbilityAi {
|
||||||
@@ -180,10 +183,22 @@ public class DigAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||||
|
if (params.containsKey("Attacker")) {
|
||||||
|
return (Player) ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
// an opponent choose a card from
|
// an opponent choose a card from
|
||||||
return Iterables.getFirst(options, null);
|
return Iterables.getFirst(options, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
||||||
|
if (params.containsKey("Attacker")) {
|
||||||
|
return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
|
}
|
||||||
|
// should not be reached
|
||||||
|
return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params);
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
* @see forge.card.ability.SpellAbilityAi#confirmAction(forge.card.spellability.SpellAbility, forge.game.player.PlayerActionConfirmMode, java.lang.String)
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import forge.ai.AiController;
|
|||||||
import forge.ai.AiProps;
|
import forge.ai.AiProps;
|
||||||
import forge.ai.ComputerUtil;
|
import forge.ai.ComputerUtil;
|
||||||
import forge.ai.ComputerUtilCard;
|
import forge.ai.ComputerUtilCard;
|
||||||
|
import forge.ai.ComputerUtilCombat;
|
||||||
import forge.ai.ComputerUtilCost;
|
import forge.ai.ComputerUtilCost;
|
||||||
import forge.ai.ComputerUtilMana;
|
import forge.ai.ComputerUtilMana;
|
||||||
import forge.ai.PlayerControllerAi;
|
import forge.ai.PlayerControllerAi;
|
||||||
@@ -37,6 +38,7 @@ import forge.game.spellability.SpellAbility;
|
|||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.MyRandom;
|
import forge.util.MyRandom;
|
||||||
|
import forge.util.collect.FCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -312,15 +314,8 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||||
Combat combat = ai.getGame().getCombat();
|
if (params.containsKey("Attacker")) {
|
||||||
// TokenAttacking
|
return (Player) ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
if (combat != null && sa.hasParam("TokenAttacking")) {
|
|
||||||
Card attacker = spawnToken(ai, sa);
|
|
||||||
for (Player p : options) {
|
|
||||||
if (!ComputerUtilCard.canBeBlockedProfitably(p, attacker)) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Iterables.getFirst(options, null);
|
return Iterables.getFirst(options, null);
|
||||||
}
|
}
|
||||||
@@ -330,28 +325,11 @@ public class TokenAi extends SpellAbilityAi {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
||||||
Combat combat = ai.getGame().getCombat();
|
if (params.containsKey("Attacker")) {
|
||||||
// TokenAttacking
|
return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||||
if (combat != null && sa.hasParam("TokenAttacking")) {
|
|
||||||
// 1. If the card that spawned the token was sent at a planeswalker, attack the same planeswalker with the token. Consider improving.
|
|
||||||
GameEntity def = combat.getDefenderByAttacker(sa.getHostCard());
|
|
||||||
if (def != null && def instanceof Card) {
|
|
||||||
if (((Card)def).isPlaneswalker()) {
|
|
||||||
return def;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 2. Otherwise, go through the list of options one by one, choose the first one that can't be blocked profitably.
|
|
||||||
Card attacker = spawnToken(ai, sa);
|
|
||||||
for (GameEntity p : options) {
|
|
||||||
if (p instanceof Player && !ComputerUtilCard.canBeBlockedProfitably((Player)p, attacker)) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
if (p instanceof Card && !ComputerUtilCard.canBeBlockedProfitably(((Card)p).getController(), attacker)) {
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return Iterables.getFirst(options, null);
|
// should not be reached
|
||||||
|
return super.chooseSinglePlayerOrPlaneswalker(ai, sa, options, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -412,7 +412,7 @@ public class GameAction {
|
|||||||
CardCollection cards = new CardCollection(c.getMergedCards());
|
CardCollection cards = new CardCollection(c.getMergedCards());
|
||||||
// replace top card with copied card for correct name for human to choose.
|
// replace top card with copied card for correct name for human to choose.
|
||||||
cards.set(cards.indexOf(c), copied);
|
cards.set(cards.indexOf(c), copied);
|
||||||
// 721.3b
|
// 723.3b
|
||||||
if (cause != null && zoneTo.getZoneType() == ZoneType.Exile) {
|
if (cause != null && zoneTo.getZoneType() == ZoneType.Exile) {
|
||||||
cards = (CardCollection) cause.getHostCard().getController().getController().orderMoveToZoneList(cards, zoneTo.getZoneType(), cause);
|
cards = (CardCollection) cause.getHostCard().getController().getController().orderMoveToZoneList(cards, zoneTo.getZoneType(), cause);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -575,14 +575,14 @@ public abstract class SpellAbilityEffect {
|
|||||||
FCollection<GameEntity> defs = null;
|
FCollection<GameEntity> defs = null;
|
||||||
// important to update defenders here, maybe some PW got removed
|
// important to update defenders here, maybe some PW got removed
|
||||||
combat.initConstraints();
|
combat.initConstraints();
|
||||||
if ("True".equalsIgnoreCase(attacking)) {
|
if (sa.hasParam("ChoosePlayerOrPlaneswalker")) {
|
||||||
defs = (FCollection<GameEntity>) combat.getDefenders();
|
|
||||||
} else if (sa.hasParam("ChoosePlayerOrPlaneswalker")) {
|
|
||||||
PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(host, attacking, sa);
|
PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(host, attacking, sa);
|
||||||
defs = new FCollection<>();
|
defs = new FCollection<>();
|
||||||
for (Player p : defendingPlayers) {
|
for (Player p : defendingPlayers) {
|
||||||
defs.addAll(game.getCombat().getDefendersControlledBy(p));
|
defs.addAll(game.getCombat().getDefendersControlledBy(p));
|
||||||
}
|
}
|
||||||
|
} else if ("True".equalsIgnoreCase(attacking)) {
|
||||||
|
defs = (FCollection<GameEntity>) combat.getDefenders();
|
||||||
} else {
|
} else {
|
||||||
defs = AbilityUtils.getDefinedEntities(host, attacking, sa);
|
defs = AbilityUtils.getDefinedEntities(host, attacking, sa);
|
||||||
}
|
}
|
||||||
@@ -593,8 +593,7 @@ public abstract class SpellAbilityEffect {
|
|||||||
Player chooser;
|
Player chooser;
|
||||||
if (sa.hasParam("Chooser")) {
|
if (sa.hasParam("Chooser")) {
|
||||||
chooser = Iterables.getFirst(AbilityUtils.getDefinedPlayers(host, sa.getParam("Chooser"), sa), null);
|
chooser = Iterables.getFirst(AbilityUtils.getDefinedPlayers(host, sa.getParam("Chooser"), sa), null);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
chooser = controller;
|
chooser = controller;
|
||||||
}
|
}
|
||||||
defender = chooser.getController().chooseSingleEntityForEffect(defs, sa,
|
defender = chooser.getController().chooseSingleEntityForEffect(defs, sa,
|
||||||
|
|||||||
@@ -164,7 +164,6 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
|||||||
game.getAction().reveal(revealed, p, false);
|
game.getAction().reveal(revealed, p, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (foundDest != null) {
|
if (foundDest != null) {
|
||||||
// Allow ordering of found cards
|
// Allow ordering of found cards
|
||||||
if ((foundDest.isKnown()) && found.size() >= 2 && !foundDest.equals(ZoneType.Exile)) {
|
if ((foundDest.isKnown()) && found.size() >= 2 && !foundDest.equals(ZoneType.Exile)) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ public class DrawEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
int actualNum = numCards;
|
int actualNum = numCards;
|
||||||
if (upto) {
|
if (upto) {
|
||||||
actualNum = p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyCardDoYouWantDraw"),0, numCards);
|
actualNum = p.getController().chooseNumber(sa, Localizer.getInstance().getMessage("lblHowManyCardDoYouWantDraw"), 0, numCards);
|
||||||
}
|
}
|
||||||
|
|
||||||
final CardCollectionView drawn = p.drawCards(actualNum, sa);
|
final CardCollectionView drawn = p.drawCards(actualNum, sa);
|
||||||
|
|||||||
@@ -132,7 +132,6 @@ public class CostReturn extends CostPartWithList {
|
|||||||
return "ReturnedCards";
|
return "ReturnedCards";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public <T> T accept(ICostVisitor<T> visitor) {
|
public <T> T accept(ICostVisitor<T> visitor) {
|
||||||
return visitor.visit(this);
|
return visitor.visit(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.getShareAllColors() != null) {
|
if (this.getShareAllColors() != null) {
|
||||||
List<Card> tgts = AbilityUtils.getDefinedCards(sa.getHostCard(), this.getShareAllColors(), sa);
|
List<Card> tgts = AbilityUtils.getDefinedCards(host, this.getShareAllColors(), sa);
|
||||||
Card first = Iterables.getFirst(tgts, null);
|
Card first = Iterables.getFirst(tgts, null);
|
||||||
if (first == null) {
|
if (first == null) {
|
||||||
return false;
|
return false;
|
||||||
@@ -324,11 +324,11 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) {
|
if (this.getActivationLimit() != -1 && sa.getActivationsThisTurn() >= this.getActivationLimit()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) {
|
if (this.getGameActivationLimit() != -1 && sa.getActivationsThisGame() >= this.getGameActivationLimit()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,7 +352,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this.getColorToCheck() != null) {
|
if (this.getColorToCheck() != null) {
|
||||||
if (!sa.getHostCard().hasChosenColor(this.getColorToCheck())) {
|
if (!host.hasChosenColor(this.getColorToCheck())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
list = new FCollection<GameObject>(game.getCardsIn(getPresentZone()));
|
list = new FCollection<GameObject>(game.getCardsIn(getPresentZone()));
|
||||||
}
|
}
|
||||||
|
|
||||||
final int left = Iterables.size(Iterables.filter(list, GameObjectPredicates.restriction(getIsPresent().split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa)));
|
final int left = Iterables.size(Iterables.filter(list, GameObjectPredicates.restriction(getIsPresent().split(","), sa.getActivatingPlayer(), host, sa)));
|
||||||
|
|
||||||
final String rightString = this.getPresentCompare().substring(2);
|
final String rightString = this.getPresentCompare().substring(2);
|
||||||
int right = AbilityUtils.calculateAmount(host, rightString, sa);
|
int right = AbilityUtils.calculateAmount(host, rightString, sa);
|
||||||
@@ -378,9 +378,9 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
if (this.getPlayerContains() != null) {
|
if (this.getPlayerContains() != null) {
|
||||||
List<Player> list = new ArrayList<>();
|
List<Player> list = new ArrayList<>();
|
||||||
if (this.getPlayerDefined() != null) {
|
if (this.getPlayerDefined() != null) {
|
||||||
list.addAll(AbilityUtils.getDefinedPlayers(sa.getHostCard(), this.getPlayerDefined(), sa));
|
list.addAll(AbilityUtils.getDefinedPlayers(host, this.getPlayerDefined(), sa));
|
||||||
}
|
}
|
||||||
List<Player> contains = AbilityUtils.getDefinedPlayers(sa.getHostCard(), this.getPlayerContains(), sa);
|
List<Player> contains = AbilityUtils.getDefinedPlayers(host, this.getPlayerContains(), sa);
|
||||||
if (contains.isEmpty() || !list.containsAll(contains)) {
|
if (contains.isEmpty() || !list.containsAll(contains)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -417,7 +417,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
boolean result = false;
|
boolean result = false;
|
||||||
|
|
||||||
for (final GameObject o : matchTgt.getFirstTargetedSpell().getTargets()) {
|
for (final GameObject o : matchTgt.getFirstTargetedSpell().getTargets()) {
|
||||||
if (o.isValid(this.getTargetValidTargeting().split(","), sa.getActivatingPlayer(), sa.getHostCard(), sa)) {
|
if (o.isValid(this.getTargetValidTargeting().split(","), sa.getActivatingPlayer(), host, sa)) {
|
||||||
result = true;
|
result = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -448,7 +448,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isNotEmpty(getManaSpent())) {
|
if (StringUtils.isNotEmpty(getManaSpent())) {
|
||||||
SpellAbility castSa = sa.getHostCard().getCastSA();
|
SpellAbility castSa = host.getCastSA();
|
||||||
if (castSa == null) {
|
if (castSa == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -457,7 +457,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (StringUtils.isNotEmpty(getManaNotSpent())) {
|
if (StringUtils.isNotEmpty(getManaNotSpent())) {
|
||||||
SpellAbility castSa = sa.getHostCard().getCastSA();
|
SpellAbility castSa = host.getCastSA();
|
||||||
if (castSa != null && castSa.getPayingColors().hasAllColors(ColorSet.fromNames(getManaNotSpent().split(" ")).getColor())) {
|
if (castSa != null && castSa.getPayingColors().hasAllColors(ColorSet.fromNames(getManaNotSpent().split(" ")).getColor())) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ PT:*/4
|
|||||||
K:Vigilance
|
K:Vigilance
|
||||||
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | Description$ CARDNAME's power is equal to the number of creatures you control.
|
S:Mode$ Continuous | EffectZone$ All | CharacteristicDefining$ True | SetPower$ X | Description$ CARDNAME's power is equal to the number of creatures you control.
|
||||||
SVar:X:Count$Valid Creature.YouCtrl
|
SVar:X:Count$Valid Creature.YouCtrl
|
||||||
T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ TrigToken | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control.
|
T:Mode$ AttackersDeclared | AttackingPlayer$ You | Execute$ DBRepeat | TriggerZones$ Battlefield | TriggerDescription$ Whenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control.
|
||||||
SVar:TrigToken:DB$ Token | TokenAmount$ Y | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ True | ChoosePlayerOrPlaneswalker$ True | TokenOwner$ You
|
SVar:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Opponent | ChangeZoneTable$ True | RepeatSubAbility$ DBToken
|
||||||
SVar:Y:PlayerCountOpponents$Amount
|
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ Remembered | ChoosePlayerOrPlaneswalker$ True | TokenOwner$ You
|
||||||
DeckHas:Ability$Token
|
DeckHas:Ability$Token
|
||||||
Oracle:Vigilance\nAdeline, Resplendent Cathar's power is equal to the number of creatures you control.\nWhenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control.
|
Oracle:Vigilance\nAdeline, Resplendent Cathar's power is equal to the number of creatures you control.\nWhenever you attack, for each opponent, create a 1/1 white Human creature token that's tapped and attacking that player or a planeswalker they control.
|
||||||
|
|||||||
@@ -5,5 +5,5 @@ A:SP$ DealDamage | Cost$ X X R | ValidTgts$ Creature,Player,Planeswalker | TgtPr
|
|||||||
SVar:MaxTgts:PlayerCountPlayers$Amount/Plus.NumCreatures
|
SVar:MaxTgts:PlayerCountPlayers$Amount/Plus.NumCreatures
|
||||||
SVar:NumCreatures:Count$Valid Creature,Planeswalker
|
SVar:NumCreatures:Count$Valid Creature,Planeswalker
|
||||||
SVar:X:Count$xPaid
|
SVar:X:Count$xPaid
|
||||||
K:Flashback:R R Discard<X/Card/card>
|
K:Flashback:R R Discard<X/Card/cards>
|
||||||
Oracle:Conflagrate deals X damage divided as you choose among any number of targets.\nFlashback—{R}{R}, Discard X cards. (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
Oracle:Conflagrate deals X damage divided as you choose among any number of targets.\nFlashback—{R}{R}, Discard X cards. (You may cast this card from your graveyard for its flashback cost. Then exile it.)
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ Types:Artifact
|
|||||||
K:CARDNAME doesn't untap during your untap step.
|
K:CARDNAME doesn't untap during your untap step.
|
||||||
A:AB$ DealDamage | Cost$ 4 T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target.
|
A:AB$ DealDamage | Cost$ 4 T | ValidTgts$ Creature,Player,Planeswalker | TgtPrompt$ Select any target | NumDmg$ 2 | SpellDescription$ CARDNAME deals 2 damage to any target.
|
||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigUntap | TriggerDescription$ At the beginning of your upkeep, you may discard a card. If you do, untap CARDNAME.
|
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | Execute$ TrigUntap | TriggerDescription$ At the beginning of your upkeep, you may discard a card. If you do, untap CARDNAME.
|
||||||
SVar:TrigUntap:AB$Untap | Cost$ Discard<1/Card> | Defined$ Self
|
SVar:TrigUntap:AB$ Untap | Cost$ Discard<1/Card> | Defined$ Self
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/elaborate_firecannon.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/elaborate_firecannon.jpg
|
||||||
Oracle:Elaborate Firecannon doesn't untap during your untap step.\n{4}, {T}: Elaborate Firecannon deals 2 damage to any target.\nAt the beginning of your upkeep, you may discard a card. If you do, untap Elaborate Firecannon.
|
Oracle:Elaborate Firecannon doesn't untap during your untap step.\n{4}, {T}: Elaborate Firecannon deals 2 damage to any target.\nAt the beginning of your upkeep, you may discard a card. If you do, untap Elaborate Firecannon.
|
||||||
@@ -4,7 +4,7 @@ Types:Creature Cat Beast
|
|||||||
PT:4/6
|
PT:4/6
|
||||||
K:Vigilance
|
K:Vigilance
|
||||||
K:Lifelink
|
K:Lifelink
|
||||||
T:Mode$Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | LifeTotal$ You | LifeAmount$ GE40 | Execute$ TrigWin | TriggerDescription$ At the beginning of your upkeep, if you have 40 or more life, you win the game.
|
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Battlefield | LifeTotal$ You | LifeAmount$ GE40 | Execute$ TrigWin | TriggerDescription$ At the beginning of your upkeep, if you have 40 or more life, you win the game.
|
||||||
SVar:TrigWin:DB$ WinsGame | Defined$ You
|
SVar:TrigWin:DB$ WinsGame | Defined$ You
|
||||||
DeckHints:Ability$LifeGain
|
DeckHints:Ability$LifeGain
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/felidar_sovereign.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/felidar_sovereign.jpg
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ ManaCost:3 G G
|
|||||||
Types:Creature Insect
|
Types:Creature Insect
|
||||||
PT:6/1
|
PT:6/1
|
||||||
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Graveyard | IsPresent$ Card.StrictlySelf | PresentZone$ Graveyard | PresentPlayer$ You | OptionalDecider$ You | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is in your graveyard, you may discard a card. If you do, return CARDNAME to your hand.
|
T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | TriggerZones$ Graveyard | IsPresent$ Card.StrictlySelf | PresentZone$ Graveyard | PresentPlayer$ You | OptionalDecider$ You | Execute$ TrigChange | TriggerDescription$ At the beginning of your upkeep, if CARDNAME is in your graveyard, you may discard a card. If you do, return CARDNAME to your hand.
|
||||||
SVar:TrigChange:AB$ChangeZone | Cost$ Discard<1/Card> | Origin$ Graveyard | Destination$ Hand | Defined$ Self
|
SVar:TrigChange:AB$ ChangeZone | Cost$ Discard<1/Card> | Origin$ Graveyard | Destination$ Hand | Defined$ Self
|
||||||
K:Shroud
|
K:Shroud
|
||||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/gigapede.jpg
|
SVar:Picture:http://www.wizards.com/global/images/magic/general/gigapede.jpg
|
||||||
Oracle:Shroud (This creature can't be the target of spells or abilities.)\nAt the beginning of your upkeep, if Gigapede is in your graveyard, you may discard a card. If you do, return Gigapede to your hand.
|
Oracle:Shroud (This creature can't be the target of spells or abilities.)\nAt the beginning of your upkeep, if Gigapede is in your graveyard, you may discard a card. If you do, return Gigapede to your hand.
|
||||||
|
|||||||
Reference in New Issue
Block a user