mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +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.
|
||||
if (sa.usesTargeting()) {
|
||||
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())) {
|
||||
int amount = 0;
|
||||
Cost wardCost = ComputerUtilCard.getTotalWardCost(tgt);
|
||||
|
||||
@@ -2497,4 +2497,27 @@ public class ComputerUtilCombat {
|
||||
}
|
||||
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.
|
||||
*
|
||||
* @param sa
|
||||
* the sa
|
||||
* @param mandatory
|
||||
* the mandatory
|
||||
* @param newParam TODO
|
||||
*
|
||||
* @return the player
|
||||
*/
|
||||
public static Player attachToPlayerAIPreferences(final Player aiPlayer, final SpellAbility sa, final boolean mandatory) {
|
||||
List<Player> targetable = new ArrayList<>();
|
||||
for (final Player player : aiPlayer.getGame().getPlayers()) {
|
||||
if (sa.canTarget(player)) {
|
||||
targetable.add(player);
|
||||
}
|
||||
}
|
||||
|
||||
public static Player attachToPlayerAIPreferences(final Player aiPlayer, final SpellAbility sa, final boolean mandatory, List<Player> targetable) {
|
||||
if ("Curse".equals(sa.getParam("AILogic"))) {
|
||||
if (!mandatory) {
|
||||
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) {
|
||||
GameObject o;
|
||||
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 {
|
||||
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,
|
||||
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)
|
||||
|| "MoveAllAuras".equals(logic)) {
|
||||
prefPlayer = ai;
|
||||
} else {
|
||||
prefPlayer = AiAttackController.choosePreferredDefenderPlayer(ai);
|
||||
}
|
||||
// Some ChangeType cards are beneficial, and PrefPlayer should be
|
||||
// changed to represent that
|
||||
@@ -1765,6 +1767,6 @@ public class AttachAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
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.card.MagicColor;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.GameObject;
|
||||
import forge.game.GlobalRuleChange;
|
||||
import forge.game.ability.AbilityKey;
|
||||
@@ -50,6 +51,7 @@ import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.staticability.StaticAbilityMustTarget;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
public class ChangeZoneAi extends SpellAbilityAi {
|
||||
/*
|
||||
@@ -423,7 +425,6 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
}
|
||||
return canBouncePermanent(ai, sa, list) != null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (ComputerUtil.playImmediately(ai, sa)) {
|
||||
@@ -1784,8 +1785,20 @@ public class ChangeZoneAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
public Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||
// Called when attaching Aura to player
|
||||
return AttachAi.attachToPlayerAIPreferences(ai, sa, true);
|
||||
// Called when attaching Aura to player or adding creature to combat
|
||||
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) {
|
||||
|
||||
@@ -12,10 +12,12 @@ import forge.ai.AiPlayDecision;
|
||||
import forge.ai.ComputerUtil;
|
||||
import forge.ai.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityKey;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
@@ -32,6 +34,7 @@ import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.player.PlayerCollection;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
public class CopyPermanentAi extends SpellAbilityAi {
|
||||
@Override
|
||||
@@ -244,9 +247,21 @@ public class CopyPermanentAi extends SpellAbilityAi {
|
||||
|
||||
@Override
|
||||
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();
|
||||
Card chosen = ComputerUtilCard.getBestCreatureAI(cards);
|
||||
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.ComputerUtilAbility;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.SpecialCardAi;
|
||||
import forge.ai.SpellAbilityAi;
|
||||
import forge.game.Game;
|
||||
import forge.game.GameEntity;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.card.CardCollection;
|
||||
@@ -25,6 +27,7 @@ import forge.game.player.PlayerPredicates;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.TextUtil;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
|
||||
public class DigAi extends SpellAbilityAi {
|
||||
@@ -180,10 +183,22 @@ public class DigAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
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
|
||||
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)
|
||||
* @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.ComputerUtil;
|
||||
import forge.ai.ComputerUtilCard;
|
||||
import forge.ai.ComputerUtilCombat;
|
||||
import forge.ai.ComputerUtilCost;
|
||||
import forge.ai.ComputerUtilMana;
|
||||
import forge.ai.PlayerControllerAi;
|
||||
@@ -37,6 +38,7 @@ import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
import forge.util.collect.FCollection;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -312,15 +314,8 @@ public class TokenAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
protected Player chooseSinglePlayer(Player ai, SpellAbility sa, Iterable<Player> options, Map<String, Object> params) {
|
||||
Combat combat = ai.getGame().getCombat();
|
||||
// TokenAttacking
|
||||
if (combat != null && sa.hasParam("TokenAttacking")) {
|
||||
Card attacker = spawnToken(ai, sa);
|
||||
for (Player p : options) {
|
||||
if (!ComputerUtilCard.canBeBlockedProfitably(p, attacker)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
if (params.containsKey("Attacker")) {
|
||||
return (Player) ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||
}
|
||||
return Iterables.getFirst(options, null);
|
||||
}
|
||||
@@ -330,28 +325,11 @@ public class TokenAi extends SpellAbilityAi {
|
||||
*/
|
||||
@Override
|
||||
protected GameEntity chooseSinglePlayerOrPlaneswalker(Player ai, SpellAbility sa, Iterable<GameEntity> options, Map<String, Object> params) {
|
||||
Combat combat = ai.getGame().getCombat();
|
||||
// TokenAttacking
|
||||
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;
|
||||
}
|
||||
}
|
||||
if (params.containsKey("Attacker")) {
|
||||
return ComputerUtilCombat.addAttackerToCombat(sa, (Card) params.get("Attacker"), new FCollection<GameEntity>(options));
|
||||
}
|
||||
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());
|
||||
// replace top card with copied card for correct name for human to choose.
|
||||
cards.set(cards.indexOf(c), copied);
|
||||
// 721.3b
|
||||
// 723.3b
|
||||
if (cause != null && zoneTo.getZoneType() == ZoneType.Exile) {
|
||||
cards = (CardCollection) cause.getHostCard().getController().getController().orderMoveToZoneList(cards, zoneTo.getZoneType(), cause);
|
||||
} else {
|
||||
|
||||
@@ -575,14 +575,14 @@ public abstract class SpellAbilityEffect {
|
||||
FCollection<GameEntity> defs = null;
|
||||
// important to update defenders here, maybe some PW got removed
|
||||
combat.initConstraints();
|
||||
if ("True".equalsIgnoreCase(attacking)) {
|
||||
defs = (FCollection<GameEntity>) combat.getDefenders();
|
||||
} else if (sa.hasParam("ChoosePlayerOrPlaneswalker")) {
|
||||
if (sa.hasParam("ChoosePlayerOrPlaneswalker")) {
|
||||
PlayerCollection defendingPlayers = AbilityUtils.getDefinedPlayers(host, attacking, sa);
|
||||
defs = new FCollection<>();
|
||||
for (Player p : defendingPlayers) {
|
||||
defs.addAll(game.getCombat().getDefendersControlledBy(p));
|
||||
}
|
||||
} else if ("True".equalsIgnoreCase(attacking)) {
|
||||
defs = (FCollection<GameEntity>) combat.getDefenders();
|
||||
} else {
|
||||
defs = AbilityUtils.getDefinedEntities(host, attacking, sa);
|
||||
}
|
||||
@@ -593,8 +593,7 @@ public abstract class SpellAbilityEffect {
|
||||
Player chooser;
|
||||
if (sa.hasParam("Chooser")) {
|
||||
chooser = Iterables.getFirst(AbilityUtils.getDefinedPlayers(host, sa.getParam("Chooser"), sa), null);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
chooser = controller;
|
||||
}
|
||||
defender = chooser.getController().chooseSingleEntityForEffect(defs, sa,
|
||||
|
||||
@@ -164,7 +164,6 @@ public class DigUntilEffect extends SpellAbilityEffect {
|
||||
game.getAction().reveal(revealed, p, false);
|
||||
}
|
||||
|
||||
|
||||
if (foundDest != null) {
|
||||
// Allow ordering of found cards
|
||||
if ((foundDest.isKnown()) && found.size() >= 2 && !foundDest.equals(ZoneType.Exile)) {
|
||||
|
||||
@@ -52,7 +52,7 @@ public class DrawEffect extends SpellAbilityEffect {
|
||||
|
||||
int actualNum = numCards;
|
||||
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);
|
||||
|
||||
@@ -132,7 +132,6 @@ public class CostReturn extends CostPartWithList {
|
||||
return "ReturnedCards";
|
||||
}
|
||||
|
||||
|
||||
public <T> T accept(ICostVisitor<T> visitor) {
|
||||
return visitor.visit(this);
|
||||
}
|
||||
|
||||
@@ -294,7 +294,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
}
|
||||
|
||||
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);
|
||||
if (first == null) {
|
||||
return false;
|
||||
@@ -324,11 +324,11 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this.getActivationLimit() != -1) && (sa.getActivationsThisTurn() >= this.getActivationLimit())) {
|
||||
if (this.getActivationLimit() != -1 && sa.getActivationsThisTurn() >= this.getActivationLimit()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((this.getGameActivationLimit() != -1) && (sa.getActivationsThisGame() >= this.getGameActivationLimit())) {
|
||||
if (this.getGameActivationLimit() != -1 && sa.getActivationsThisGame() >= this.getGameActivationLimit()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -352,7 +352,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
}
|
||||
|
||||
if (this.getColorToCheck() != null) {
|
||||
if (!sa.getHostCard().hasChosenColor(this.getColorToCheck())) {
|
||||
if (!host.hasChosenColor(this.getColorToCheck())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -365,7 +365,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
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);
|
||||
int right = AbilityUtils.calculateAmount(host, rightString, sa);
|
||||
@@ -378,9 +378,9 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
if (this.getPlayerContains() != null) {
|
||||
List<Player> list = new ArrayList<>();
|
||||
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)) {
|
||||
return false;
|
||||
}
|
||||
@@ -417,7 +417,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
boolean result = false;
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
@@ -448,7 +448,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
}
|
||||
|
||||
if (StringUtils.isNotEmpty(getManaSpent())) {
|
||||
SpellAbility castSa = sa.getHostCard().getCastSA();
|
||||
SpellAbility castSa = host.getCastSA();
|
||||
if (castSa == null) {
|
||||
return false;
|
||||
}
|
||||
@@ -457,7 +457,7 @@ public class SpellAbilityCondition extends SpellAbilityVariables {
|
||||
}
|
||||
}
|
||||
if (StringUtils.isNotEmpty(getManaNotSpent())) {
|
||||
SpellAbility castSa = sa.getHostCard().getCastSA();
|
||||
SpellAbility castSa = host.getCastSA();
|
||||
if (castSa != null && castSa.getPayingColors().hasAllColors(ColorSet.fromNames(getManaNotSpent().split(" ")).getColor())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,8 @@ PT:*/4
|
||||
K:Vigilance
|
||||
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
|
||||
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.
|
||||
SVar:TrigToken:DB$ Token | TokenAmount$ Y | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ True | ChoosePlayerOrPlaneswalker$ True | TokenOwner$ You
|
||||
SVar:Y:PlayerCountOpponents$Amount
|
||||
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:DBRepeat:DB$ RepeatEach | RepeatPlayers$ Opponent | ChangeZoneTable$ True | RepeatSubAbility$ DBToken
|
||||
SVar:DBToken:DB$ Token | TokenAmount$ 1 | TokenScript$ w_1_1_human | TokenTapped$ True | TokenAttacking$ Remembered | ChoosePlayerOrPlaneswalker$ True | TokenOwner$ You
|
||||
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.
|
||||
|
||||
@@ -5,5 +5,5 @@ A:SP$ DealDamage | Cost$ X X R | ValidTgts$ Creature,Player,Planeswalker | TgtPr
|
||||
SVar:MaxTgts:PlayerCountPlayers$Amount/Plus.NumCreatures
|
||||
SVar:NumCreatures:Count$Valid Creature,Planeswalker
|
||||
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.)
|
||||
|
||||
@@ -4,6 +4,6 @@ Types:Artifact
|
||||
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.
|
||||
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
|
||||
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
|
||||
K:Vigilance
|
||||
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
|
||||
DeckHints:Ability$LifeGain
|
||||
SVar:Picture:http://www.wizards.com/global/images/magic/general/felidar_sovereign.jpg
|
||||
|
||||
@@ -3,7 +3,7 @@ ManaCost:3 G G
|
||||
Types:Creature Insect
|
||||
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.
|
||||
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
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user