diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java index 96533a22d5e..4db53dcaf13 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAi.java @@ -596,7 +596,7 @@ public class PumpAi extends PumpAiBase { } return true; - } // pumpTgtAI() + } private boolean pumpMandatoryTarget(final Player ai, final SpellAbility sa) { final Game game = ai.getGame(); @@ -657,7 +657,7 @@ public class PumpAi extends PumpAiBase { } return true; - } // pumpMandatoryTarget() + } @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { @@ -706,7 +706,7 @@ public class PumpAi extends PumpAiBase { } return true; - } // pumpTriggerAI + } @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { @@ -778,7 +778,7 @@ public class PumpAi extends PumpAiBase { } return true; - } // pumpDrawbackAI() + } @Override public boolean confirmAction(Player player, SpellAbility sa, PlayerActionConfirmMode mode, String message) { diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java index 2d0fcd29403..6b57f4f7753 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAiBase.java @@ -428,7 +428,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } }); return list; - } // getPumpCreatures() + } /** *

@@ -519,7 +519,7 @@ public abstract class PumpAiBase extends SpellAbilityAi { } return list; - } // getCurseCreatures() + } protected boolean containsNonCombatKeyword(final List keywords) { for (final String keyword : keywords) { 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 03e45c72dfc..f6851384376 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityFactory.java @@ -50,7 +50,7 @@ import io.sentry.Sentry; */ public final class AbilityFactory { - static final List additionalAbilityKeys = Lists.newArrayList( + public static final List additionalAbilityKeys = Lists.newArrayList( "WinSubAbility", "OtherwiseSubAbility", // Clash "BidSubAbility", // BidLifeEffect "ChooseNumberSubAbility", "Lowest", "Highest", "NotLowest", // ChooseNumber @@ -80,7 +80,7 @@ public final class AbilityFactory { return prefix; } - public SpellAbility buildSpellAbility(ApiType api, Card hostCard, Cost abCost, TargetRestrictions abTgt, Map mapParams ) { + public SpellAbility buildSpellAbility(ApiType api, Card hostCard, Cost abCost, TargetRestrictions abTgt, Map mapParams) { switch(this) { case Ability: return new AbilityApiBased(api, hostCard, abCost, abTgt, mapParams); case Spell: return new SpellApiBased(api, hostCard, abCost, abTgt, mapParams); diff --git a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java index a06228b7122..d870da734d3 100644 --- a/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java +++ b/forge-gui/src/main/java/forge/gui/card/CardScriptParser.java @@ -14,6 +14,8 @@ import com.google.common.collect.Maps; import com.google.common.collect.Sets; import forge.card.CardType; +import forge.game.ability.AbilityFactory; +import forge.game.ability.AbilityFactory.AbilityRecordType; import forge.game.ability.ApiType; import forge.game.replacement.ReplacementType; import forge.game.trigger.TriggerType; @@ -74,6 +76,7 @@ public final class CardScriptParser { bad = true; } } else if (trimLine.startsWith("A:")) { + // TODO check if it's non-permanent, then Cost$ isn't mandatory result.putAll(getActivatedAbilityErrors(trimLine.substring("A:".length()), index + "A:".length())); } else if (trimLine.startsWith("R:")) { result.putAll(getReplacementErrors(trimLine.substring("R:".length()), index + "R:".length())); @@ -221,7 +224,7 @@ public final class CardScriptParser { if (trimValue.isEmpty()) { isBadValue = true; } - } else if (trimKey.equals("SubAbility")) { + } else if (trimKey.equals("SubAbility") || AbilityFactory.additionalAbilityKeys.contains(trimKey)) { if (sVars.contains(trimValue)) { sVarAbilities.add(trimValue); } else { @@ -315,7 +318,10 @@ public final class CardScriptParser { private static boolean isAbilityApiDeclarerLegal(final String declarer) { final String tDeclarer = declarer.trim(); - return tDeclarer.equals("AB") || tDeclarer.equals("DB") || tDeclarer.equals("SP"); + for (AbilityRecordType type : AbilityRecordType.values()) { + if (type.getPrefix().equals(tDeclarer)) return true; + } + return false; } private static boolean isAbilityApiLegal(final String api) { try { @@ -506,7 +512,10 @@ public final class CardScriptParser { "RememberMap", "wasCastFrom", "wasNotCastFrom", "set", "inZone", "HasSVar"); - private static boolean isValidExclusive(final String valid) { + private static boolean isValidExclusive(String valid) { + if (valid.charAt(0) == '!') { + valid = valid.substring(1); + } if (VALID_EXCLUSIVE.contains(valid)) { return true; }