mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 19:58:00 +00:00
Merge branch 'spellAbilityAdditionalAbilities' into 'master'
SpellAbility: use SpellAbility for additionalAbilities so Trigger can have cost See merge request core-developers/forge!4303
This commit is contained in:
@@ -44,7 +44,6 @@ import forge.game.mana.ManaPool;
|
|||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilityManaPart;
|
import forge.game.spellability.AbilityManaPart;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
@@ -1346,7 +1345,7 @@ public abstract class GameState {
|
|||||||
}
|
}
|
||||||
else if (info.startsWith("OnAdventure")) {
|
else if (info.startsWith("OnAdventure")) {
|
||||||
String abAdventure = "DB$ Effect | RememberObjects$ Self | StaticAbilities$ Play | ExileOnMoved$ Exile | Duration$ Permanent | ConditionDefined$ Self | ConditionPresent$ Card.nonCopiedSpell";
|
String abAdventure = "DB$ Effect | RememberObjects$ Self | StaticAbilities$ Play | ExileOnMoved$ Exile | Duration$ Permanent | ConditionDefined$ Self | ConditionPresent$ Card.nonCopiedSpell";
|
||||||
AbilitySub saAdventure = (AbilitySub)AbilityFactory.getAbility(abAdventure, c);
|
SpellAbility saAdventure = AbilityFactory.getAbility(abAdventure, c);
|
||||||
StringBuilder sbPlay = new StringBuilder();
|
StringBuilder sbPlay = new StringBuilder();
|
||||||
sbPlay.append("Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonAdventure");
|
sbPlay.append("Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonAdventure");
|
||||||
sbPlay.append(" | AffectedZone$ Exile | Description$ You may cast the card.");
|
sbPlay.append(" | AffectedZone$ Exile | Description$ You may cast the card.");
|
||||||
|
|||||||
@@ -159,8 +159,7 @@ public class SpecialCardAi {
|
|||||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||||
final Combat combat = ai.getGame().getCombat();
|
final Combat combat = ai.getGame().getCombat();
|
||||||
|
|
||||||
Card animated = AnimateAi.becomeAnimated(sa.getHostCard(), sa);
|
Card animated = AnimateAi.becomeAnimated(sa.getHostCard(), sa.getSubAbility());
|
||||||
animated.addType("Creature");
|
|
||||||
if (sa.getHostCard().canReceiveCounters(CounterEnumType.P1P1)) {
|
if (sa.getHostCard().canReceiveCounters(CounterEnumType.P1P1)) {
|
||||||
animated.addCounter(CounterEnumType.P1P1, 2, ai, false, null);
|
animated.addCounter(CounterEnumType.P1P1, 2, ai, false, null);
|
||||||
}
|
}
|
||||||
@@ -170,10 +169,6 @@ public class SpecialCardAi {
|
|||||||
|
|
||||||
return isOppEOT || isValuableAttacker || isValuableBlocker;
|
return isOppEOT || isValuableAttacker || isValuableBlocker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SpellAbility considerAnimating(final Player ai, final SpellAbility sa, final List<SpellAbility> options) {
|
|
||||||
return ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2) ? options.get(0) : options.get(1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cursed Scroll
|
// Cursed Scroll
|
||||||
|
|||||||
@@ -299,7 +299,7 @@ public abstract class SpellAbilityAi {
|
|||||||
final AbilitySub subAb = ab.getSubAbility();
|
final AbilitySub subAb = ab.getSubAbility();
|
||||||
return SpellApiToAi.Converter.get(ab.getApi()).chkAIDrawback(ab, aiPlayer) && (subAb == null || chkDrawbackWithSubs(aiPlayer, subAb));
|
return SpellApiToAi.Converter.get(ab.getApi()).chkAIDrawback(ab, aiPlayer) && (subAb == null || chkDrawbackWithSubs(aiPlayer, subAb));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
System.err.println("Warning: default (ie. inherited from base class) implementation of confirmAction is used by " + sa.getHostCard().getName() + " for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
System.err.println("Warning: default (ie. inherited from base class) implementation of confirmAction is used by " + sa.getHostCard().getName() + " for " + this.getClass().getName() + ". Consider declaring an overloaded method");
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ import forge.game.cost.CostPutCounter;
|
|||||||
import forge.game.phase.PhaseHandler;
|
import forge.game.phase.PhaseHandler;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.staticability.StaticAbility;
|
import forge.game.staticability.StaticAbility;
|
||||||
import forge.game.staticability.StaticAbilityContinuous;
|
import forge.game.staticability.StaticAbilityContinuous;
|
||||||
@@ -243,6 +244,11 @@ public class AnimateAi extends SpellAbilityAi {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) {
|
||||||
|
return player.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean animateTgtAI(final SpellAbility sa) {
|
private boolean animateTgtAI(final SpellAbility sa) {
|
||||||
final Player ai = sa.getActivatingPlayer();
|
final Player ai = sa.getActivatingPlayer();
|
||||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||||
|
|||||||
@@ -363,8 +363,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
|||||||
} else if ("Riot".equals(logic)) {
|
} else if ("Riot".equals(logic)) {
|
||||||
SpellAbility counterSA = spells.get(0), hasteSA = spells.get(1);
|
SpellAbility counterSA = spells.get(0), hasteSA = spells.get(1);
|
||||||
return preferHasteForRiot(sa, player) ? hasteSA : counterSA;
|
return preferHasteForRiot(sa, player) ? hasteSA : counterSA;
|
||||||
} else if ("CrawlingBarrens".equals(logic)) {
|
|
||||||
return SpecialCardAi.CrawlingBarrens.considerAnimating(player, sa, spells);
|
|
||||||
}
|
}
|
||||||
return spells.get(0); // return first choice if no logic found
|
return spells.get(0); // return first choice if no logic found
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -313,7 +313,12 @@ public class CountersPutAi extends SpellAbilityAi {
|
|||||||
} else if (logic.startsWith("MoveCounter")) {
|
} else if (logic.startsWith("MoveCounter")) {
|
||||||
return doMoveCounterLogic(ai, sa, ph);
|
return doMoveCounterLogic(ai, sa, ph);
|
||||||
} else if (logic.equals("CrawlingBarrens")) {
|
} else if (logic.equals("CrawlingBarrens")) {
|
||||||
return SpecialCardAi.CrawlingBarrens.consider(ai, sa);
|
boolean willActivate = SpecialCardAi.CrawlingBarrens.consider(ai, sa);
|
||||||
|
if (willActivate && ph.getPhase().isBefore(PhaseType.MAIN2)) {
|
||||||
|
// don't use this for mana until after combat
|
||||||
|
AiCardMemory.rememberCard(ai, source, AiCardMemory.MemorySet.HELD_MANA_SOURCES_FOR_MAIN2);
|
||||||
|
}
|
||||||
|
return willActivate;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sa.metConditions() && sa.getSubAbility() == null) {
|
if (!sa.metConditions() && sa.getSubAbility() == null) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import forge.game.card.CardPredicates.Presets;
|
|||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.phase.PhaseType;
|
import forge.game.phase.PhaseType;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
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;
|
||||||
@@ -67,7 +66,7 @@ public class RepeatEachAi extends SpellAbilityAi {
|
|||||||
return false;
|
return false;
|
||||||
} else if ("AllPlayerLoseLife".equals(logic)) {
|
} else if ("AllPlayerLoseLife".equals(logic)) {
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||||
|
|
||||||
String svar = repeat.getSVar(repeat.getParam("LifeAmount"));
|
String svar = repeat.getSVar(repeat.getParam("LifeAmount"));
|
||||||
// replace RememberedPlayerCtrl with YouCtrl
|
// replace RememberedPlayerCtrl with YouCtrl
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ public final class AbilityFactory {
|
|||||||
|
|
||||||
static final List<String> additionalAbilityKeys = Lists.newArrayList(
|
static final List<String> additionalAbilityKeys = Lists.newArrayList(
|
||||||
"WinSubAbility", "OtherwiseSubAbility", // Clash
|
"WinSubAbility", "OtherwiseSubAbility", // Clash
|
||||||
|
"BidSubAbility", // BidLifeEffect
|
||||||
"ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", // ChooseNumber
|
"ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", // ChooseNumber
|
||||||
"HeadsSubAbility", "TailsSubAbility", "LoseSubAbility", // FlipCoin
|
"HeadsSubAbility", "TailsSubAbility", "LoseSubAbility", // FlipCoin
|
||||||
"TrueSubAbility", "FalseSubAbility", // Branch
|
"TrueSubAbility", "FalseSubAbility", // Branch
|
||||||
@@ -272,7 +273,7 @@ public final class AbilityFactory {
|
|||||||
|
|
||||||
for (final String key : additionalAbilityKeys) {
|
for (final String key : additionalAbilityKeys) {
|
||||||
if (mapParams.containsKey(key) && spellAbility.getAdditionalAbility(key) == null) {
|
if (mapParams.containsKey(key) && spellAbility.getAdditionalAbility(key) == null) {
|
||||||
spellAbility.setAdditionalAbility(key, getSubAbility(state, mapParams.get(key), sVarHolder));
|
spellAbility.setAdditionalAbility(key, getAbility(state, mapParams.get(key), sVarHolder));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardUtil;
|
import forge.game.card.CardUtil;
|
||||||
import forge.game.event.GameEventCardStatsChanged;
|
import forge.game.event.GameEventCardStatsChanged;
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
|
import forge.util.Lang;
|
||||||
|
import forge.util.TextUtil;
|
||||||
|
|
||||||
|
|
||||||
public class AnimateEffect extends AnimateEffectBase {
|
public class AnimateEffect extends AnimateEffectBase {
|
||||||
@@ -139,6 +141,17 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
|
|
||||||
List<Card> tgts = getCardsfromTargets(sa);
|
List<Card> tgts = getCardsfromTargets(sa);
|
||||||
|
|
||||||
|
if (sa.hasParam("Optional")) {
|
||||||
|
final String targets = Lang.joinHomogenous(tgts);
|
||||||
|
final String message = sa.hasParam("OptionQuestion")
|
||||||
|
? TextUtil.fastReplace(sa.getParam("OptionQuestion"), "TARGETS", targets)
|
||||||
|
: getStackDescription(sa);
|
||||||
|
|
||||||
|
if (!sa.getActivatingPlayer().getController().confirmAction(sa, null, message)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (final Card c : tgts) {
|
for (final Card c : tgts) {
|
||||||
doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc,
|
doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc,
|
||||||
keywords, removeKeywords, hiddenKeywords,
|
keywords, removeKeywords, hiddenKeywords,
|
||||||
@@ -229,9 +242,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
|||||||
|
|
||||||
final List<Card> tgts = getCardsfromTargets(sa);
|
final List<Card> tgts = getCardsfromTargets(sa);
|
||||||
|
|
||||||
for (final Card c : tgts) {
|
sb.append(Lang.joinHomogenous(tgts)).append(" ");
|
||||||
sb.append(c).append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
// if power is -1, we'll assume it's not just setting toughness
|
// if power is -1, we'll assume it's not just setting toughness
|
||||||
if (power != null && toughness != null) {
|
if (power != null && toughness != null) {
|
||||||
|
|||||||
@@ -2,13 +2,11 @@ package forge.game.ability.effects;
|
|||||||
|
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
import forge.game.ability.AbilityFactory;
|
|
||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerActionConfirmMode;
|
import forge.game.player.PlayerActionConfirmMode;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
import forge.util.collect.FCollection;
|
import forge.util.collect.FCollection;
|
||||||
@@ -67,10 +65,10 @@ public class BidLifeEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
host.setChosenNumber(bid);
|
host.setChosenNumber(bid);
|
||||||
host.addRemembered(winner);
|
host.addRemembered(winner);
|
||||||
final SpellAbility action = AbilityFactory.getAbility(host.getSVar(sa.getParam("BidSubAbility")), host);
|
final SpellAbility action = sa.getAdditionalAbility("BidSubAbility");
|
||||||
action.setActivatingPlayer(sa.getActivatingPlayer());
|
if (action != null) {
|
||||||
((AbilitySub) action).setParent(sa);
|
AbilityUtils.resolve(action);
|
||||||
AbilityUtils.resolve(action);
|
}
|
||||||
host.clearRemembered();
|
host.clearRemembered();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package forge.game.ability.effects;
|
|||||||
import forge.game.ability.AbilityUtils;
|
import forge.game.ability.AbilityUtils;
|
||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
|
|
||||||
@@ -24,7 +23,7 @@ public class BranchEffect extends SpellAbilityEffect {
|
|||||||
final int svarValue = AbilityUtils.calculateAmount(host, branchSVar, sa);
|
final int svarValue = AbilityUtils.calculateAmount(host, branchSVar, sa);
|
||||||
final int operandValue = AbilityUtils.calculateAmount(host, operand, sa);
|
final int operandValue = AbilityUtils.calculateAmount(host, operand, sa);
|
||||||
|
|
||||||
AbilitySub sub = null;
|
SpellAbility sub = null;
|
||||||
if (Expressions.compare(svarValue, operator, operandValue)) {
|
if (Expressions.compare(svarValue, operator, operandValue)) {
|
||||||
sub = sa.getAdditionalAbility("TrueSubAbility");
|
sub = sa.getAdditionalAbility("TrueSubAbility");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
@@ -106,7 +105,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
card.getGame().getAction().notifyOfValue(sa, card, sb.toString(), null);
|
card.getGame().getAction().notifyOfValue(sa, card, sb.toString(), null);
|
||||||
if (sa.hasParam("ChooseNumberSubAbility")) {
|
if (sa.hasParam("ChooseNumberSubAbility")) {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("ChooseNumberSubAbility");
|
SpellAbility sub = sa.getAdditionalAbility("ChooseNumberSubAbility");
|
||||||
|
|
||||||
for (Player p : chooseMap.keySet()) {
|
for (Player p : chooseMap.keySet()) {
|
||||||
card.addRemembered(p);
|
card.addRemembered(p);
|
||||||
@@ -117,7 +116,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sa.hasParam("Lowest")) {
|
if (sa.hasParam("Lowest")) {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("Lowest");
|
SpellAbility sub = sa.getAdditionalAbility("Lowest");
|
||||||
|
|
||||||
for (Player p : lowestNum) {
|
for (Player p : lowestNum) {
|
||||||
card.addRemembered(p);
|
card.addRemembered(p);
|
||||||
@@ -134,7 +133,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
|||||||
notLowestNum.add(p);
|
notLowestNum.add(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
AbilitySub sub = sa.getAdditionalAbility("NotLowest");
|
SpellAbility sub = sa.getAdditionalAbility("NotLowest");
|
||||||
|
|
||||||
for (Player p : notLowestNum) {
|
for (Player p : notLowestNum) {
|
||||||
card.addRemembered(p);
|
card.addRemembered(p);
|
||||||
@@ -144,7 +143,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sa.hasParam("Highest")) {
|
if (sa.hasParam("Highest")) {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("Highest");
|
SpellAbility sub = sa.getAdditionalAbility("Highest");
|
||||||
|
|
||||||
for (Player p : highestNum) {
|
for (Player p : highestNum) {
|
||||||
card.addRemembered(p);
|
card.addRemembered(p);
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.TargetRestrictions;
|
import forge.game.spellability.TargetRestrictions;
|
||||||
import forge.util.Aggregates;
|
import forge.util.Aggregates;
|
||||||
@@ -63,7 +62,7 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SubAbility that only fires if a player is chosen
|
// SubAbility that only fires if a player is chosen
|
||||||
AbilitySub chosenSA = sa.getAdditionalAbility("ChooseSubAbility");
|
SpellAbility chosenSA = sa.getAdditionalAbility("ChooseSubAbility");
|
||||||
if (chosenSA != null) {
|
if (chosenSA != null) {
|
||||||
if (!chosenSA.getHostCard().equals(sa.getHostCard())) {
|
if (!chosenSA.getHostCard().equals(sa.getHostCard())) {
|
||||||
System.out.println("Warning: ChooseSubAbility had the wrong host set (potentially after cloning the root SA), attempting to correct...");
|
System.out.println("Warning: ChooseSubAbility had the wrong host set (potentially after cloning the root SA), attempting to correct...");
|
||||||
@@ -73,7 +72,7 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// SubAbility that only fires if a player is not chosen
|
// SubAbility that only fires if a player is not chosen
|
||||||
AbilitySub notChosenSA = sa.getAdditionalAbility("CantChooseSubAbility");
|
SpellAbility notChosenSA = sa.getAdditionalAbility("CantChooseSubAbility");
|
||||||
if (notChosenSA != null) {
|
if (notChosenSA != null) {
|
||||||
if (!notChosenSA.getHostCard().equals(sa.getHostCard())) {
|
if (!notChosenSA.getHostCard().equals(sa.getHostCard())) {
|
||||||
System.out.println("Warning: CantChooseSubAbility had the wrong host set (potentially after cloning the root SA), attempting to correct...");
|
System.out.println("Warning: CantChooseSubAbility had the wrong host set (potentially after cloning the root SA), attempting to correct...");
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import forge.game.ability.AbilityUtils;
|
|||||||
import forge.game.ability.SpellAbilityEffect;
|
import forge.game.ability.SpellAbilityEffect;
|
||||||
import forge.game.card.Card;
|
import forge.game.card.Card;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.game.zone.PlayerZone;
|
import forge.game.zone.PlayerZone;
|
||||||
@@ -39,14 +38,14 @@ public class ClashEffect extends SpellAbilityEffect {
|
|||||||
|
|
||||||
if (victory) {
|
if (victory) {
|
||||||
|
|
||||||
AbilitySub sub = sa.getAdditionalAbility("WinSubAbility");
|
SpellAbility sub = sa.getAdditionalAbility("WinSubAbility");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
AbilityUtils.resolve(sub);
|
AbilityUtils.resolve(sub);
|
||||||
}
|
}
|
||||||
|
|
||||||
runParams.put(AbilityKey.Won, "True");
|
runParams.put(AbilityKey.Won, "True");
|
||||||
} else {
|
} else {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("OtherwiseSubAbility");
|
SpellAbility sub = sa.getAdditionalAbility("OtherwiseSubAbility");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
AbilityUtils.resolve(sub);
|
AbilityUtils.resolve(sub);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,9 +82,11 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (sa.hasAdditionalAbility("Execute")) {
|
||||||
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
SpellAbility overridingSA = sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
||||||
// need to reset the parent, additionalAbility does set it to this
|
// need to reset the parent, additionalAbility does set it to this
|
||||||
overridingSA.setParent(null);
|
if (overridingSA instanceof AbilitySub) {
|
||||||
|
((AbilitySub)overridingSA).setParent(null);
|
||||||
|
}
|
||||||
// Set Transform timestamp when the delayed trigger is created
|
// Set Transform timestamp when the delayed trigger is created
|
||||||
if (ApiType.SetState == overridingSA.getApi()) {
|
if (ApiType.SetState == overridingSA.getApi()) {
|
||||||
overridingSA.setSVar("StoredTransform", String.valueOf(sa.getHostCard().getTransformedTimestamp()));
|
overridingSA.setSVar("StoredTransform", String.valueOf(sa.getHostCard().getTransformedTimestamp()));
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ import forge.game.card.Card;
|
|||||||
import forge.game.event.GameEventFlipCoin;
|
import forge.game.event.GameEventFlipCoin;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.player.PlayerController;
|
import forge.game.player.PlayerController;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.trigger.TriggerType;
|
import forge.game.trigger.TriggerType;
|
||||||
import forge.util.Localizer;
|
import forge.util.Localizer;
|
||||||
@@ -97,7 +96,7 @@ public class FlipCoinEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (countHeads > 0) {
|
if (countHeads > 0) {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("HeadsSubAbility");
|
SpellAbility sub = sa.getAdditionalAbility("HeadsSubAbility");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
if (sa.hasParam("Amount")) {
|
if (sa.hasParam("Amount")) {
|
||||||
sub.setSVar(varName, "Number$" + countHeads);
|
sub.setSVar(varName, "Number$" + countHeads);
|
||||||
@@ -106,7 +105,7 @@ public class FlipCoinEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (countTails > 0) {
|
if (countTails > 0) {
|
||||||
AbilitySub sub = sa.getAdditionalAbility("TailsSubAbility");
|
SpellAbility sub = sa.getAdditionalAbility("TailsSubAbility");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
if (sa.hasParam("Amount")) {
|
if (sa.hasParam("Amount")) {
|
||||||
sub.setSVar(varName, "Number$" + countTails);
|
sub.setSVar(varName, "Number$" + countTails);
|
||||||
|
|||||||
@@ -75,9 +75,11 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (sa.hasAdditionalAbility("Execute")) {
|
if (sa.hasAdditionalAbility("Execute")) {
|
||||||
AbilitySub overridingSA = (AbilitySub)sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
SpellAbility overridingSA = sa.getAdditionalAbility("Execute").copy(lki, sa.getActivatingPlayer(), false);
|
||||||
// need to set Parent to null, otherwise it might have wrong root ability
|
// need to set Parent to null, otherwise it might have wrong root ability
|
||||||
overridingSA.setParent(null);
|
if (overridingSA instanceof AbilitySub) {
|
||||||
|
((AbilitySub)overridingSA).setParent(null);
|
||||||
|
}
|
||||||
|
|
||||||
if (sa.hasParam("CopyTriggeringObjects")) {
|
if (sa.hasParam("CopyTriggeringObjects")) {
|
||||||
overridingSA.setTriggeringObjects(sa.getTriggeringObjects());
|
overridingSA.setTriggeringObjects(sa.getTriggeringObjects());
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
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;
|
||||||
@@ -105,7 +104,7 @@ public class MultiplePilesEffect extends SpellAbilityEffect {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AbilitySub sub = sa.getAdditionalAbility("ChosenPile");
|
SpellAbility sub = sa.getAdditionalAbility("ChosenPile");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
AbilityUtils.resolve(sub);
|
AbilityUtils.resolve(sub);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import forge.game.card.CardDamageMap;
|
|||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.card.CardZoneTable;
|
import forge.game.card.CardZoneTable;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.spellability.SpellAbilityStackInstance;
|
import forge.game.spellability.SpellAbilityStackInstance;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
@@ -33,7 +32,7 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
|||||||
// Things to loop over: Cards, Players, or SAs
|
// Things to loop over: Cards, Players, or SAs
|
||||||
final Card source = sa.getHostCard();
|
final Card source = sa.getHostCard();
|
||||||
|
|
||||||
final AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
final SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||||
|
|
||||||
if (repeat != null && !repeat.getHostCard().equalsWithTimestamp(source)) {
|
if (repeat != null && !repeat.getHostCard().equalsWithTimestamp(source)) {
|
||||||
// TODO: for some reason, the host card of the original additional SA is set to the cloned card when
|
// TODO: for some reason, the host card of the original additional SA is set to the cloned card when
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import forge.game.card.Card;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
import forge.game.spellability.SpellAbility;
|
||||||
import forge.game.zone.ZoneType;
|
import forge.game.zone.ZoneType;
|
||||||
import forge.util.Expressions;
|
import forge.util.Expressions;
|
||||||
@@ -25,7 +24,7 @@ public class RepeatEffect extends SpellAbilityEffect {
|
|||||||
Card source = sa.getHostCard();
|
Card source = sa.getHostCard();
|
||||||
|
|
||||||
// setup subability to repeat
|
// setup subability to repeat
|
||||||
AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||||
|
|
||||||
if (repeat != null && !repeat.getHostCard().equals(source)) {
|
if (repeat != null && !repeat.getHostCard().equals(source)) {
|
||||||
// TODO: for some reason, the host card of the original additional SA is set to the cloned card when
|
// TODO: for some reason, the host card of the original additional SA is set to the cloned card when
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import forge.game.card.CardCollection;
|
|||||||
import forge.game.card.CardCollectionView;
|
import forge.game.card.CardCollectionView;
|
||||||
import forge.game.card.CardLists;
|
import forge.game.card.CardLists;
|
||||||
import forge.game.player.Player;
|
import forge.game.player.Player;
|
||||||
import forge.game.spellability.AbilitySub;
|
|
||||||
import forge.game.spellability.SpellAbility;
|
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;
|
||||||
@@ -161,7 +160,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
|
|||||||
card.addRemembered(z);
|
card.addRemembered(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbilitySub sub = sa.getAdditionalAbility("ChosenPile");
|
SpellAbility sub = sa.getAdditionalAbility("ChosenPile");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
AbilityUtils.resolve(sub);
|
AbilityUtils.resolve(sub);
|
||||||
}
|
}
|
||||||
@@ -174,7 +173,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
|
|||||||
card.addRemembered(z);
|
card.addRemembered(z);
|
||||||
}
|
}
|
||||||
|
|
||||||
AbilitySub sub = sa.getAdditionalAbility("UnchosenPile");
|
SpellAbility sub = sa.getAdditionalAbility("UnchosenPile");
|
||||||
if (sub != null) {
|
if (sub != null) {
|
||||||
AbilityUtils.resolve(sub);
|
AbilityUtils.resolve(sub);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -538,8 +538,8 @@ public class CardFactory {
|
|||||||
if (from.getSubAbility() != null) {
|
if (from.getSubAbility() != null) {
|
||||||
to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, p, lki));
|
to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, p, lki));
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, AbilitySub> e : from.getAdditionalAbilities().entrySet()) {
|
for (Map.Entry<String, SpellAbility> e : from.getAdditionalAbilities().entrySet()) {
|
||||||
to.setAdditionalAbility(e.getKey(), (AbilitySub) e.getValue().copy(host, p, lki));
|
to.setAdditionalAbility(e.getKey(), e.getValue().copy(host, p, lki));
|
||||||
}
|
}
|
||||||
for (Map.Entry<String, List<AbilitySub>> e : from.getAdditionalAbilityLists().entrySet()) {
|
for (Map.Entry<String, List<AbilitySub>> e : from.getAdditionalAbilityLists().entrySet()) {
|
||||||
to.setAdditionalAbilityList(e.getKey(), Lists.transform(e.getValue(), new Function<AbilitySub, AbilitySub>() {
|
to.setAdditionalAbilityList(e.getKey(), Lists.transform(e.getValue(), new Function<AbilitySub, AbilitySub>() {
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
private SpellAbilityCondition conditions = new SpellAbilityCondition();
|
private SpellAbilityCondition conditions = new SpellAbilityCondition();
|
||||||
private AbilitySub subAbility = null;
|
private AbilitySub subAbility = null;
|
||||||
|
|
||||||
private Map<String, AbilitySub> additionalAbilities = Maps.newHashMap();
|
private Map<String, SpellAbility> additionalAbilities = Maps.newHashMap();
|
||||||
private Map<String, List<AbilitySub>> additionalAbilityLists = Maps.newHashMap();
|
private Map<String, List<AbilitySub>> additionalAbilityLists = Maps.newHashMap();
|
||||||
|
|
||||||
protected ApiType api = null;
|
protected ApiType api = null;
|
||||||
@@ -238,7 +238,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
if (subAbility != null) {
|
if (subAbility != null) {
|
||||||
subAbility.setHostCard(c);
|
subAbility.setHostCard(c);
|
||||||
}
|
}
|
||||||
for (AbilitySub sa : additionalAbilities.values()) {
|
for (SpellAbility sa : additionalAbilities.values()) {
|
||||||
if (sa.getHostCard() != c) {
|
if (sa.getHostCard() != c) {
|
||||||
sa.setHostCard(c);
|
sa.setHostCard(c);
|
||||||
}
|
}
|
||||||
@@ -437,7 +437,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
if (subAbility != null) {
|
if (subAbility != null) {
|
||||||
updated |= subAbility.setActivatingPlayer(player, lki);
|
updated |= subAbility.setActivatingPlayer(player, lki);
|
||||||
}
|
}
|
||||||
for (AbilitySub sa : additionalAbilities.values()) {
|
for (SpellAbility sa : additionalAbilities.values()) {
|
||||||
updated |= sa.setActivatingPlayer(player, lki);
|
updated |= sa.setActivatingPlayer(player, lki);
|
||||||
}
|
}
|
||||||
for (List<AbilitySub> list : additionalAbilityLists.values()) {
|
for (List<AbilitySub> list : additionalAbilityLists.values()) {
|
||||||
@@ -875,10 +875,10 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
view.updateDescription(this); //description changes when sub-abilities change
|
view.updateDescription(this); //description changes when sub-abilities change
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, AbilitySub> getAdditionalAbilities() {
|
public Map<String, SpellAbility> getAdditionalAbilities() {
|
||||||
return additionalAbilities;
|
return additionalAbilities;
|
||||||
}
|
}
|
||||||
public AbilitySub getAdditionalAbility(final String name) {
|
public SpellAbility getAdditionalAbility(final String name) {
|
||||||
if (hasAdditionalAbility(name)) {
|
if (hasAdditionalAbility(name)) {
|
||||||
return additionalAbilities.get(name);
|
return additionalAbilities.get(name);
|
||||||
}
|
}
|
||||||
@@ -889,11 +889,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
return additionalAbilities.containsKey(name);
|
return additionalAbilities.containsKey(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAdditionalAbility(final String name, final AbilitySub sa) {
|
public void setAdditionalAbility(final String name, final SpellAbility sa) {
|
||||||
if (sa == null) {
|
if (sa == null) {
|
||||||
additionalAbilities.remove(name);
|
additionalAbilities.remove(name);
|
||||||
} else {
|
} else {
|
||||||
sa.setParent(this);
|
if (sa instanceof AbilitySub) {
|
||||||
|
((AbilitySub)sa).setParent(this);
|
||||||
|
}
|
||||||
additionalAbilities.put(name, sa);
|
additionalAbilities.put(name, sa);
|
||||||
}
|
}
|
||||||
view.updateDescription(this); //description changes when sub-abilities change
|
view.updateDescription(this); //description changes when sub-abilities change
|
||||||
@@ -2080,7 +2082,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
subAbility.changeText();
|
subAbility.changeText();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AbilitySub sa : additionalAbilities.values()) {
|
for (SpellAbility sa : additionalAbilities.values()) {
|
||||||
sa.changeText();
|
sa.changeText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2105,7 +2107,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
subAbility.changeTextIntrinsic(colorMap, typeMap);
|
subAbility.changeTextIntrinsic(colorMap, typeMap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AbilitySub sa : additionalAbilities.values()) {
|
for (SpellAbility sa : additionalAbilities.values()) {
|
||||||
sa.changeTextIntrinsic(colorMap, typeMap);
|
sa.changeTextIntrinsic(colorMap, typeMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2122,7 +2124,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
|||||||
if (subAbility != null) {
|
if (subAbility != null) {
|
||||||
subAbility.setIntrinsic(i);
|
subAbility.setIntrinsic(i);
|
||||||
}
|
}
|
||||||
for (AbilitySub sa : additionalAbilities.values()) {
|
for (SpellAbility sa : additionalAbilities.values()) {
|
||||||
if (sa.isIntrinsic() != i) {
|
if (sa.isIntrinsic() != i) {
|
||||||
sa.setIntrinsic(i);
|
sa.setIntrinsic(i);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ public class WrappedAbility extends Ability {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AbilitySub getAdditionalAbility(String ability) {
|
public SpellAbility getAdditionalAbility(String ability) {
|
||||||
return sa.getAdditionalAbility(ability);
|
return sa.getAdditionalAbility(ability);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,9 +2,7 @@ Name:Crawling Barrens
|
|||||||
ManaCost:no cost
|
ManaCost:no cost
|
||||||
Types:Land
|
Types:Land
|
||||||
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
A:AB$ Mana | Cost$ T | Produced$ C | SpellDescription$ Add {C}.
|
||||||
A:AB$ PutCounter | Cost$ 4 | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBChoice | AILogic$ CrawlingBarrens | SpellDescription$ Put two +1/+1 counters on CARDNAME. Then you may have it become a 0/0 Elemental creature until end of turn. It's still a land.
|
A:AB$ PutCounter | Cost$ 4 | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBAnimate | AILogic$ CrawlingBarrens | SpellDescription$ Put two +1/+1 counters on CARDNAME. Then you may have it become a 0/0 Elemental creature until end of turn. It's still a land.
|
||||||
SVar:DBChoice:DB$ GenericChoice | Defined$ You | Choices$ Animate,NoAnimate | AILogic$ CrawlingBarrens | StackDescription$ Then you may have it become a 0/0 Elemental creature until end of turn. It's still a land.
|
SVar:DBAnimate:DB$ Animate | Defined$ Self | Power$ 0 | Toughness$ 0 | Types$ Creature,Elemental | Optional$ True
|
||||||
SVar:Animate:DB$ Animate | Defined$ Self | Power$ 0 | Toughness$ 0 | Types$ Creature,Elemental | SpellDescription$ CARDNAME becomes a 0/0 Elemental creature until end of turn.
|
|
||||||
SVar:NoAnimate:DB$ Pump | SpellDescription$ CARDNAME does not become a 0/0 Elemental creature until end of turn.
|
|
||||||
DeckHas:Ability$Counters
|
DeckHas:Ability$Counters
|
||||||
Oracle:{T}: Add {C}.\n{4}: Put two +1/+1 counters on Crawling Barrens. Then you may have it become a 0/0 Elemental creature until end of turn. It's still a land.
|
Oracle:{T}: Add {C}.\n{4}: Put two +1/+1 counters on Crawling Barrens. Then you may have it become a 0/0 Elemental creature until end of turn. It's still a land.
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ PT:1/1
|
|||||||
K:Menace
|
K:Menace
|
||||||
K:Lifelink
|
K:Lifelink
|
||||||
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Creature+nonToken+OppOwn | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life."
|
R:Event$ Moved | ActiveZones$ Battlefield | Origin$ Battlefield | Destination$ Graveyard | ValidCard$ Card.Creature+nonToken+OppOwn | ReplaceWith$ Exile | Description$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life."
|
||||||
SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard
|
SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBImmediateTrigger
|
||||||
T:Mode$ ChangesZone | TriggerZones$ Battlefield | Origin$ Any | Destination$ Exile | ValidCard$ Card.ExiledWithSource | Execute$ TrigToken | Secondary$ True | TriggerDescription$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life."
|
SVar:DBImmediateTrigger:DB$ ImmediateTrigger | Execute$ TrigToken | TriggerDescription$ If a nontoken creature an opponent controls would die, exile it instead. When you do, you may pay {2}. If you do, create a 1/1 black and green Pest creature token with "When this creature dies, you gain 1 life."
|
||||||
SVar:TrigToken:AB$ Token | Cost$ 2 | TokenAmount$ 1 | TokenScript$ bg_1_1_pest_lifegain | TokenOwner$ You
|
SVar:TrigToken:AB$ Token | Cost$ 2 | TokenAmount$ 1 | TokenScript$ bg_1_1_pest_lifegain | TokenOwner$ You
|
||||||
AlternateMode:Modal
|
AlternateMode:Modal
|
||||||
DeckHas:Ability$Token & Ability$LifeGain
|
DeckHas:Ability$Token & Ability$LifeGain
|
||||||
|
|||||||
Reference in New Issue
Block a user