diff --git a/forge-ai/src/main/java/forge/ai/GameState.java b/forge-ai/src/main/java/forge/ai/GameState.java index 1c09d0171ee..a1519659b0f 100644 --- a/forge-ai/src/main/java/forge/ai/GameState.java +++ b/forge-ai/src/main/java/forge/ai/GameState.java @@ -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."); diff --git a/forge-ai/src/main/java/forge/ai/SpecialCardAi.java b/forge-ai/src/main/java/forge/ai/SpecialCardAi.java index f4581c5ccca..3be1023947a 100644 --- a/forge-ai/src/main/java/forge/ai/SpecialCardAi.java +++ b/forge-ai/src/main/java/forge/ai/SpecialCardAi.java @@ -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 options) { - return ai.getGame().getPhaseHandler().getPhase().isBefore(PhaseType.MAIN2) ? options.get(0) : options.get(1); - } } // Cursed Scroll diff --git a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java index bf17cb7df54..3ffc9b493c7 100644 --- a/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/SpellAbilityAi.java @@ -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; diff --git a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java index 34d33387a54..0cb19367512 100644 --- a/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/AnimateAi.java @@ -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(); diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java index 9078eab7c4f..567739d4053 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseGenericEffectAi.java @@ -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 } diff --git a/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java b/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java index a47b8326bd1..6cee4388a36 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CountersPutAi.java @@ -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) { diff --git a/forge-ai/src/main/java/forge/ai/ability/RepeatEachAi.java b/forge-ai/src/main/java/forge/ai/ability/RepeatEachAi.java index 079a0cb8fb7..afcd0879fbd 100644 --- a/forge-ai/src/main/java/forge/ai/ability/RepeatEachAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/RepeatEachAi.java @@ -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 diff --git a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java index 8fce51f16e1..6cee9511771 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -53,6 +53,7 @@ public final class AbilityFactory { static final List 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)); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java index 9bf9d3eb09d..507875df874 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/AnimateEffect.java @@ -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 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 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) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java index 99a80f31f05..b6574fe12e3 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/BidLifeEffect.java @@ -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(); } } diff --git a/forge-game/src/main/java/forge/game/ability/effects/BranchEffect.java b/forge-game/src/main/java/forge/game/ability/effects/BranchEffect.java index 4a6df32b71c..da738e1fc7b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/BranchEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/BranchEffect.java @@ -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 { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java index af26897b838..d8a21d239c1 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChooseNumberEffect.java @@ -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); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java index b576b755b31..9e238b1ff99 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChoosePlayerEffect.java @@ -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..."); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ClashEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ClashEffect.java index 5afd9ce5626..51823fe1f3c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ClashEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ClashEffect.java @@ -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); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java index f094cb53eb0..cad9aff89be 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/DelayedTriggerEffect.java @@ -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())); diff --git a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java index 0dc54e056d0..1d37fc3c82b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/FlipCoinEffect.java @@ -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); diff --git a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java index d2d891385c3..af20f6a67dc 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ImmediateTriggerEffect.java @@ -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()); diff --git a/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java b/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java index 2c80b33e8a6..c9c10e36a73 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/MultiplePilesEffect.java @@ -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); } diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java index ef28ac2d20a..52a05d28f00 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEachEffect.java @@ -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 diff --git a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java index eaed68ffe73..5c384cd1401 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/RepeatEffect.java @@ -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 diff --git a/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java b/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java index 1bcd140cd0b..27f5571ee18 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/TwoPilesEffect.java @@ -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); } diff --git a/forge-game/src/main/java/forge/game/card/CardFactory.java b/forge-game/src/main/java/forge/game/card/CardFactory.java index 8dd1e5e87a7..f3b0e79075f 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactory.java +++ b/forge-game/src/main/java/forge/game/card/CardFactory.java @@ -538,8 +538,8 @@ public class CardFactory { if (from.getSubAbility() != null) { to.setSubAbility((AbilitySub) from.getSubAbility().copy(host, p, lki)); } - for (Map.Entry e : from.getAdditionalAbilities().entrySet()) { - to.setAdditionalAbility(e.getKey(), (AbilitySub) e.getValue().copy(host, p, lki)); + for (Map.Entry e : from.getAdditionalAbilities().entrySet()) { + to.setAdditionalAbility(e.getKey(), e.getValue().copy(host, p, lki)); } for (Map.Entry> e : from.getAdditionalAbilityLists().entrySet()) { to.setAdditionalAbilityList(e.getKey(), Lists.transform(e.getValue(), new Function() { diff --git a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java index 1f31fdd7d4c..77fb7b2dc83 100644 --- a/forge-game/src/main/java/forge/game/spellability/SpellAbility.java +++ b/forge-game/src/main/java/forge/game/spellability/SpellAbility.java @@ -139,7 +139,7 @@ public abstract class SpellAbility extends CardTraitBase implements ISpellAbilit private SpellAbilityCondition conditions = new SpellAbilityCondition(); private AbilitySub subAbility = null; - private Map additionalAbilities = Maps.newHashMap(); + private Map additionalAbilities = Maps.newHashMap(); private Map> 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 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 getAdditionalAbilities() { + public Map 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); } diff --git a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java index ad85d9ef7e4..bade2975b81 100644 --- a/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java +++ b/forge-game/src/main/java/forge/game/trigger/WrappedAbility.java @@ -421,7 +421,7 @@ public class WrappedAbility extends Ability { } @Override - public AbilitySub getAdditionalAbility(String ability) { + public SpellAbility getAdditionalAbility(String ability) { return sa.getAdditionalAbility(ability); } diff --git a/forge-gui/res/cardsfolder/c/crawling_barrens.txt b/forge-gui/res/cardsfolder/c/crawling_barrens.txt index 1f4957379ce..ad52fcdec67 100755 --- a/forge-gui/res/cardsfolder/c/crawling_barrens.txt +++ b/forge-gui/res/cardsfolder/c/crawling_barrens.txt @@ -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. diff --git a/forge-gui/res/cardsfolder/upcoming/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt b/forge-gui/res/cardsfolder/upcoming/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt index 21f5c106e74..a27337e8c2e 100644 --- a/forge-gui/res/cardsfolder/upcoming/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt +++ b/forge-gui/res/cardsfolder/upcoming/valentin_dean_of_the_vein_lisette_dean_of_the_root.txt @@ -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