mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 11:48:02 +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.player.Player;
|
||||
import forge.game.spellability.AbilityManaPart;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.PlayerZone;
|
||||
@@ -1346,7 +1345,7 @@ public abstract class GameState {
|
||||
}
|
||||
else if (info.startsWith("OnAdventure")) {
|
||||
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();
|
||||
sbPlay.append("Mode$ Continuous | MayPlay$ True | EffectZone$ Command | Affected$ Card.IsRemembered+nonAdventure");
|
||||
sbPlay.append(" | AffectedZone$ Exile | Description$ You may cast the card.");
|
||||
|
||||
@@ -159,8 +159,7 @@ public class SpecialCardAi {
|
||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||
final Combat combat = ai.getGame().getCombat();
|
||||
|
||||
Card animated = AnimateAi.becomeAnimated(sa.getHostCard(), sa);
|
||||
animated.addType("Creature");
|
||||
Card animated = AnimateAi.becomeAnimated(sa.getHostCard(), sa.getSubAbility());
|
||||
if (sa.getHostCard().canReceiveCounters(CounterEnumType.P1P1)) {
|
||||
animated.addCounter(CounterEnumType.P1P1, 2, ai, false, null);
|
||||
}
|
||||
@@ -170,10 +169,6 @@ public class SpecialCardAi {
|
||||
|
||||
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
|
||||
|
||||
@@ -299,7 +299,7 @@ public abstract class SpellAbilityAi {
|
||||
final AbilitySub subAb = ab.getSubAbility();
|
||||
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) {
|
||||
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;
|
||||
|
||||
@@ -30,6 +30,7 @@ import forge.game.cost.CostPutCounter;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.staticability.StaticAbility;
|
||||
import forge.game.staticability.StaticAbilityContinuous;
|
||||
@@ -243,6 +244,11 @@ public class AnimateAi extends SpellAbilityAi {
|
||||
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) {
|
||||
final Player ai = sa.getActivatingPlayer();
|
||||
final PhaseHandler ph = ai.getGame().getPhaseHandler();
|
||||
|
||||
@@ -363,8 +363,6 @@ public class ChooseGenericEffectAi extends SpellAbilityAi {
|
||||
} else if ("Riot".equals(logic)) {
|
||||
SpellAbility counterSA = spells.get(0), hasteSA = spells.get(1);
|
||||
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
|
||||
}
|
||||
|
||||
@@ -313,7 +313,12 @@ public class CountersPutAi extends SpellAbilityAi {
|
||||
} else if (logic.startsWith("MoveCounter")) {
|
||||
return doMoveCounterLogic(ai, sa, ph);
|
||||
} 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) {
|
||||
|
||||
@@ -16,7 +16,6 @@ import forge.game.card.CardPredicates.Presets;
|
||||
import forge.game.card.CardUtil;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.TextUtil;
|
||||
@@ -67,7 +66,7 @@ public class RepeatEachAi extends SpellAbilityAi {
|
||||
return false;
|
||||
} else if ("AllPlayerLoseLife".equals(logic)) {
|
||||
final Card source = sa.getHostCard();
|
||||
AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
|
||||
String svar = repeat.getSVar(repeat.getParam("LifeAmount"));
|
||||
// replace RememberedPlayerCtrl with YouCtrl
|
||||
|
||||
@@ -53,6 +53,7 @@ public final class AbilityFactory {
|
||||
|
||||
static final List<String> additionalAbilityKeys = Lists.newArrayList(
|
||||
"WinSubAbility", "OtherwiseSubAbility", // Clash
|
||||
"BidSubAbility", // BidLifeEffect
|
||||
"ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", // ChooseNumber
|
||||
"HeadsSubAbility", "TailsSubAbility", "LoseSubAbility", // FlipCoin
|
||||
"TrueSubAbility", "FalseSubAbility", // Branch
|
||||
@@ -272,7 +273,7 @@ public final class AbilityFactory {
|
||||
|
||||
for (final String key : additionalAbilityKeys) {
|
||||
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.event.GameEventCardStatsChanged;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Lang;
|
||||
import forge.util.TextUtil;
|
||||
|
||||
|
||||
public class AnimateEffect extends AnimateEffectBase {
|
||||
@@ -139,6 +141,17 @@ public class AnimateEffect extends AnimateEffectBase {
|
||||
|
||||
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) {
|
||||
doAnimate(c, sa, power, toughness, types, removeTypes, finalDesc,
|
||||
keywords, removeKeywords, hiddenKeywords,
|
||||
@@ -229,9 +242,7 @@ public class AnimateEffect extends AnimateEffectBase {
|
||||
|
||||
final List<Card> tgts = getCardsfromTargets(sa);
|
||||
|
||||
for (final Card c : tgts) {
|
||||
sb.append(c).append(" ");
|
||||
}
|
||||
sb.append(Lang.joinHomogenous(tgts)).append(" ");
|
||||
|
||||
// if power is -1, we'll assume it's not just setting toughness
|
||||
if (power != null && toughness != null) {
|
||||
|
||||
@@ -2,13 +2,11 @@ package forge.game.ability.effects;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
import forge.game.ability.AbilityFactory;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.player.PlayerActionConfirmMode;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Localizer;
|
||||
import forge.util.collect.FCollection;
|
||||
@@ -67,10 +65,10 @@ public class BidLifeEffect extends SpellAbilityEffect {
|
||||
|
||||
host.setChosenNumber(bid);
|
||||
host.addRemembered(winner);
|
||||
final SpellAbility action = AbilityFactory.getAbility(host.getSVar(sa.getParam("BidSubAbility")), host);
|
||||
action.setActivatingPlayer(sa.getActivatingPlayer());
|
||||
((AbilitySub) action).setParent(sa);
|
||||
AbilityUtils.resolve(action);
|
||||
final SpellAbility action = sa.getAdditionalAbility("BidSubAbility");
|
||||
if (action != null) {
|
||||
AbilityUtils.resolve(action);
|
||||
}
|
||||
host.clearRemembered();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package forge.game.ability.effects;
|
||||
import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.util.Expressions;
|
||||
|
||||
@@ -24,7 +23,7 @@ public class BranchEffect extends SpellAbilityEffect {
|
||||
final int svarValue = AbilityUtils.calculateAmount(host, branchSVar, sa);
|
||||
final int operandValue = AbilityUtils.calculateAmount(host, operand, sa);
|
||||
|
||||
AbilitySub sub = null;
|
||||
SpellAbility sub = null;
|
||||
if (Expressions.compare(svarValue, operator, operandValue)) {
|
||||
sub = sa.getAdditionalAbility("TrueSubAbility");
|
||||
} else {
|
||||
|
||||
@@ -11,7 +11,6 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.util.Localizer;
|
||||
@@ -106,7 +105,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
||||
}
|
||||
card.getGame().getAction().notifyOfValue(sa, card, sb.toString(), null);
|
||||
if (sa.hasParam("ChooseNumberSubAbility")) {
|
||||
AbilitySub sub = sa.getAdditionalAbility("ChooseNumberSubAbility");
|
||||
SpellAbility sub = sa.getAdditionalAbility("ChooseNumberSubAbility");
|
||||
|
||||
for (Player p : chooseMap.keySet()) {
|
||||
card.addRemembered(p);
|
||||
@@ -117,7 +116,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
if (sa.hasParam("Lowest")) {
|
||||
AbilitySub sub = sa.getAdditionalAbility("Lowest");
|
||||
SpellAbility sub = sa.getAdditionalAbility("Lowest");
|
||||
|
||||
for (Player p : lowestNum) {
|
||||
card.addRemembered(p);
|
||||
@@ -134,7 +133,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
||||
notLowestNum.add(p);
|
||||
}
|
||||
}
|
||||
AbilitySub sub = sa.getAdditionalAbility("NotLowest");
|
||||
SpellAbility sub = sa.getAdditionalAbility("NotLowest");
|
||||
|
||||
for (Player p : notLowestNum) {
|
||||
card.addRemembered(p);
|
||||
@@ -144,7 +143,7 @@ public class ChooseNumberEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
if (sa.hasParam("Highest")) {
|
||||
AbilitySub sub = sa.getAdditionalAbility("Highest");
|
||||
SpellAbility sub = sa.getAdditionalAbility("Highest");
|
||||
|
||||
for (Player p : highestNum) {
|
||||
card.addRemembered(p);
|
||||
|
||||
@@ -6,7 +6,6 @@ import forge.game.ability.AbilityUtils;
|
||||
import forge.game.ability.SpellAbilityEffect;
|
||||
import forge.game.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.util.Aggregates;
|
||||
@@ -63,7 +62,7 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
// SubAbility that only fires if a player is chosen
|
||||
AbilitySub chosenSA = sa.getAdditionalAbility("ChooseSubAbility");
|
||||
SpellAbility chosenSA = sa.getAdditionalAbility("ChooseSubAbility");
|
||||
if (chosenSA != null) {
|
||||
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...");
|
||||
@@ -73,7 +72,7 @@ public class ChoosePlayerEffect extends SpellAbilityEffect {
|
||||
}
|
||||
} else {
|
||||
// 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.getHostCard().equals(sa.getHostCard())) {
|
||||
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.card.Card;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.game.zone.PlayerZone;
|
||||
@@ -39,14 +38,14 @@ public class ClashEffect extends SpellAbilityEffect {
|
||||
|
||||
if (victory) {
|
||||
|
||||
AbilitySub sub = sa.getAdditionalAbility("WinSubAbility");
|
||||
SpellAbility sub = sa.getAdditionalAbility("WinSubAbility");
|
||||
if (sub != null) {
|
||||
AbilityUtils.resolve(sub);
|
||||
}
|
||||
|
||||
runParams.put(AbilityKey.Won, "True");
|
||||
} else {
|
||||
AbilitySub sub = sa.getAdditionalAbility("OtherwiseSubAbility");
|
||||
SpellAbility sub = sa.getAdditionalAbility("OtherwiseSubAbility");
|
||||
if (sub != null) {
|
||||
AbilityUtils.resolve(sub);
|
||||
}
|
||||
|
||||
@@ -82,9 +82,11 @@ public class DelayedTriggerEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
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
|
||||
overridingSA.setParent(null);
|
||||
if (overridingSA instanceof AbilitySub) {
|
||||
((AbilitySub)overridingSA).setParent(null);
|
||||
}
|
||||
// Set Transform timestamp when the delayed trigger is created
|
||||
if (ApiType.SetState == overridingSA.getApi()) {
|
||||
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.player.Player;
|
||||
import forge.game.player.PlayerController;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.trigger.TriggerType;
|
||||
import forge.util.Localizer;
|
||||
@@ -97,7 +96,7 @@ public class FlipCoinEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
if (countHeads > 0) {
|
||||
AbilitySub sub = sa.getAdditionalAbility("HeadsSubAbility");
|
||||
SpellAbility sub = sa.getAdditionalAbility("HeadsSubAbility");
|
||||
if (sub != null) {
|
||||
if (sa.hasParam("Amount")) {
|
||||
sub.setSVar(varName, "Number$" + countHeads);
|
||||
@@ -106,7 +105,7 @@ public class FlipCoinEffect extends SpellAbilityEffect {
|
||||
}
|
||||
}
|
||||
if (countTails > 0) {
|
||||
AbilitySub sub = sa.getAdditionalAbility("TailsSubAbility");
|
||||
SpellAbility sub = sa.getAdditionalAbility("TailsSubAbility");
|
||||
if (sub != null) {
|
||||
if (sa.hasParam("Amount")) {
|
||||
sub.setSVar(varName, "Number$" + countTails);
|
||||
|
||||
@@ -75,9 +75,11 @@ public class ImmediateTriggerEffect extends SpellAbilityEffect {
|
||||
}
|
||||
|
||||
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
|
||||
overridingSA.setParent(null);
|
||||
if (overridingSA instanceof AbilitySub) {
|
||||
((AbilitySub)overridingSA).setParent(null);
|
||||
}
|
||||
|
||||
if (sa.hasParam("CopyTriggeringObjects")) {
|
||||
overridingSA.setTriggeringObjects(sa.getTriggeringObjects());
|
||||
|
||||
@@ -15,7 +15,6 @@ import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
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) {
|
||||
AbilityUtils.resolve(sub);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ import forge.game.card.CardDamageMap;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.card.CardZoneTable;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.SpellAbilityStackInstance;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -33,7 +32,7 @@ public class RepeatEachEffect extends SpellAbilityEffect {
|
||||
// Things to loop over: Cards, Players, or SAs
|
||||
final Card source = sa.getHostCard();
|
||||
|
||||
final AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
final SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
|
||||
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
|
||||
|
||||
@@ -7,7 +7,6 @@ import forge.game.card.Card;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.Expressions;
|
||||
@@ -25,7 +24,7 @@ public class RepeatEffect extends SpellAbilityEffect {
|
||||
Card source = sa.getHostCard();
|
||||
|
||||
// setup subability to repeat
|
||||
AbilitySub repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
SpellAbility repeat = sa.getAdditionalAbility("RepeatSubAbility");
|
||||
|
||||
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
|
||||
|
||||
@@ -9,7 +9,6 @@ import forge.game.card.CardCollection;
|
||||
import forge.game.card.CardCollectionView;
|
||||
import forge.game.card.CardLists;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.spellability.AbilitySub;
|
||||
import forge.game.spellability.SpellAbility;
|
||||
import forge.game.spellability.TargetRestrictions;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -161,7 +160,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
|
||||
card.addRemembered(z);
|
||||
}
|
||||
|
||||
AbilitySub sub = sa.getAdditionalAbility("ChosenPile");
|
||||
SpellAbility sub = sa.getAdditionalAbility("ChosenPile");
|
||||
if (sub != null) {
|
||||
AbilityUtils.resolve(sub);
|
||||
}
|
||||
@@ -174,7 +173,7 @@ public class TwoPilesEffect extends SpellAbilityEffect {
|
||||
card.addRemembered(z);
|
||||
}
|
||||
|
||||
AbilitySub sub = sa.getAdditionalAbility("UnchosenPile");
|
||||
SpellAbility sub = sa.getAdditionalAbility("UnchosenPile");
|
||||
if (sub != null) {
|
||||
AbilityUtils.resolve(sub);
|
||||
}
|
||||
|
||||
@@ -538,8 +538,8 @@ public class CardFactory {
|
||||
if (from.getSubAbility() != null) {
|
||||
to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, p, lki));
|
||||
}
|
||||
for (Map.Entry<String, AbilitySub> e : from.getAdditionalAbilities().entrySet()) {
|
||||
to.setAdditionalAbility(e.getKey(), (AbilitySub) e.getValue().copy(host, p, lki));
|
||||
for (Map.Entry<String, SpellAbility> e : from.getAdditionalAbilities().entrySet()) {
|
||||
to.setAdditionalAbility(e.getKey(), e.getValue().copy(host, p, lki));
|
||||
}
|
||||
for (Map.Entry<String, List<AbilitySub>> e : from.getAdditionalAbilityLists().entrySet()) {
|
||||
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 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();
|
||||
|
||||
protected ApiType api = null;
|
||||
@@ -238,7 +238,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
if (subAbility != null) {
|
||||
subAbility.setHostCard(c);
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
for (SpellAbility sa : additionalAbilities.values()) {
|
||||
if (sa.getHostCard() != c) {
|
||||
sa.setHostCard(c);
|
||||
}
|
||||
@@ -437,7 +437,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
if (subAbility != null) {
|
||||
updated |= subAbility.setActivatingPlayer(player, lki);
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
for (SpellAbility sa : additionalAbilities.values()) {
|
||||
updated |= sa.setActivatingPlayer(player, lki);
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
public Map<String, AbilitySub> getAdditionalAbilities() {
|
||||
public Map<String, SpellAbility> getAdditionalAbilities() {
|
||||
return additionalAbilities;
|
||||
}
|
||||
public AbilitySub getAdditionalAbility(final String name) {
|
||||
public SpellAbility getAdditionalAbility(final String name) {
|
||||
if (hasAdditionalAbility(name)) {
|
||||
return additionalAbilities.get(name);
|
||||
}
|
||||
@@ -889,11 +889,13 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
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) {
|
||||
additionalAbilities.remove(name);
|
||||
} else {
|
||||
sa.setParent(this);
|
||||
if (sa instanceof AbilitySub) {
|
||||
((AbilitySub)sa).setParent(this);
|
||||
}
|
||||
additionalAbilities.put(name, sa);
|
||||
}
|
||||
view.updateDescription(this); //description changes when sub-abilities change
|
||||
@@ -2080,7 +2082,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
subAbility.changeText();
|
||||
}
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
for (SpellAbility sa : additionalAbilities.values()) {
|
||||
sa.changeText();
|
||||
}
|
||||
|
||||
@@ -2105,7 +2107,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
subAbility.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
for (SpellAbility sa : additionalAbilities.values()) {
|
||||
sa.changeTextIntrinsic(colorMap, typeMap);
|
||||
}
|
||||
|
||||
@@ -2122,7 +2124,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit
|
||||
if (subAbility != null) {
|
||||
subAbility.setIntrinsic(i);
|
||||
}
|
||||
for (AbilitySub sa : additionalAbilities.values()) {
|
||||
for (SpellAbility sa : additionalAbilities.values()) {
|
||||
if (sa.isIntrinsic() != i) {
|
||||
sa.setIntrinsic(i);
|
||||
}
|
||||
|
||||
@@ -421,7 +421,7 @@ public class WrappedAbility extends Ability {
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getAdditionalAbility(String ability) {
|
||||
public SpellAbility getAdditionalAbility(String ability) {
|
||||
return sa.getAdditionalAbility(ability);
|
||||
}
|
||||
|
||||
|
||||
@@ -2,9 +2,7 @@ Name:Crawling Barrens
|
||||
ManaCost:no cost
|
||||
Types:Land
|
||||
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.
|
||||
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: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.
|
||||
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:DBAnimate:DB$ Animate | Defined$ Self | Power$ 0 | Toughness$ 0 | Types$ Creature,Elemental | Optional$ True
|
||||
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.
|
||||
|
||||
@@ -5,8 +5,8 @@ PT:1/1
|
||||
K:Menace
|
||||
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."
|
||||
SVar:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard
|
||||
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:Exile:DB$ ChangeZone | Hidden$ True | Origin$ All | Destination$ Exile | Defined$ ReplacedCard | SubAbility$ DBImmediateTrigger
|
||||
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
|
||||
AlternateMode:Modal
|
||||
DeckHas:Ability$Token & Ability$LifeGain
|
||||
|
||||
Reference in New Issue
Block a user