From e13865a96659629f4e7edb6aa14031fe3cbb882f Mon Sep 17 00:00:00 2001 From: swordshine Date: Sat, 21 Dec 2013 01:08:36 +0000 Subject: [PATCH] - Converted "You may discard CARDNAME any time you could cast an instant." to script --- .gitattributes | 1 + .../res/cardsfolder/c/circling_vultures.txt | 2 +- .../forge/game/ability/AbilityFactory.java | 4 ++ .../game/ability/StaticAbilityApiBased.java | 54 +++++++++++++++++++ .../game/ability/effects/DiscardEffect.java | 23 ++++---- .../src/main/java/forge/game/card/Card.java | 3 +- .../java/forge/game/card/CardFactoryUtil.java | 40 -------------- .../game/spellability/AbilityStatic.java | 12 +++++ .../main/java/forge/game/zone/MagicStack.java | 2 +- 9 files changed, 88 insertions(+), 53 deletions(-) create mode 100644 forge-gui/src/main/java/forge/game/ability/StaticAbilityApiBased.java diff --git a/.gitattributes b/.gitattributes index 4873c217b06..c27e5699dd9 100644 --- a/.gitattributes +++ b/.gitattributes @@ -14856,6 +14856,7 @@ forge-gui/src/main/java/forge/game/ability/ApiType.java -text forge-gui/src/main/java/forge/game/ability/SaTargetRoutines.java -text forge-gui/src/main/java/forge/game/ability/SpellAbilityEffect.java -text forge-gui/src/main/java/forge/game/ability/SpellApiBased.java -text +forge-gui/src/main/java/forge/game/ability/StaticAbilityApiBased.java -text forge-gui/src/main/java/forge/game/ability/effects/AbandonEffect.java -text forge-gui/src/main/java/forge/game/ability/effects/AddPhaseEffect.java -text forge-gui/src/main/java/forge/game/ability/effects/AddTurnEffect.java -text diff --git a/forge-gui/res/cardsfolder/c/circling_vultures.txt b/forge-gui/res/cardsfolder/c/circling_vultures.txt index 717f547077f..db89a3e3200 100644 --- a/forge-gui/res/cardsfolder/c/circling_vultures.txt +++ b/forge-gui/res/cardsfolder/c/circling_vultures.txt @@ -3,7 +3,7 @@ ManaCost:B Types:Creature Bird PT:3/2 K:Flying -K:MayDiscardFromHand +A:ST$ Discard | Cost$ 0 | Mode$ Defined | DefinedCards$ Self | Optional$ True | DiscardMessage$ Do you want discard this card? | ActivationZone$ Hand | InstantSpeed$ True | SpellDescription$ You may discard CARDNAME any time you could cast an instant. T:Mode$ Phase | Phase$ Upkeep | ValidPlayer$ You | Execute$ TrigSacUnless | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your upkeep, sacrifice CARDNAME unless you exile the top creature card of your graveyard. SVar:TrigSacUnless:AB$ Sacrifice | Cost$ 0 | Defined$ Self | UnlessCost$ ExileFromGrave<1/Card.TopGraveyardCreature> | UnlessPayer$ You SVar:RemAIDeck:True diff --git a/forge-gui/src/main/java/forge/game/ability/AbilityFactory.java b/forge-gui/src/main/java/forge/game/ability/AbilityFactory.java index 3e4b970f771..e3798eeb807 100644 --- a/forge-gui/src/main/java/forge/game/ability/AbilityFactory.java +++ b/forge-gui/src/main/java/forge/game/ability/AbilityFactory.java @@ -45,6 +45,7 @@ public final class AbilityFactory { public enum AbilityRecordType { Ability("AB"), Spell("SP"), + StaticAbility("ST"), SubAbility("DB"); private final String prefix; @@ -59,6 +60,7 @@ public final class AbilityFactory { switch(this) { case Ability: return new AbilityApiBased(api, hostCard, abCost, abTgt, mapParams); case Spell: return new SpellApiBased(api, hostCard, abCost, abTgt, mapParams); + case StaticAbility: return new StaticAbilityApiBased(api, hostCard, abCost, abTgt, mapParams); case SubAbility: return new AbilitySub(api, hostCard, abTgt, mapParams); } return null; // exception here would be fine! @@ -73,6 +75,8 @@ public final class AbilityFactory { return AbilityRecordType.Ability; } else if (abParams.containsKey(AbilityRecordType.Spell.getPrefix())) { return AbilityRecordType.Spell; + } else if (abParams.containsKey(AbilityRecordType.StaticAbility.getPrefix())) { + return AbilityRecordType.StaticAbility; } else if (abParams.containsKey(AbilityRecordType.SubAbility.getPrefix())) { return AbilityRecordType.SubAbility; } else { diff --git a/forge-gui/src/main/java/forge/game/ability/StaticAbilityApiBased.java b/forge-gui/src/main/java/forge/game/ability/StaticAbilityApiBased.java new file mode 100644 index 00000000000..16d86b83859 --- /dev/null +++ b/forge-gui/src/main/java/forge/game/ability/StaticAbilityApiBased.java @@ -0,0 +1,54 @@ +package forge.game.ability; + +import java.util.Map; + +import forge.ai.SpellAbilityAi; +import forge.game.ability.effects.ChangeZoneAllEffect; +import forge.game.ability.effects.ChangeZoneEffect; +import forge.game.card.Card; +import forge.game.cost.Cost; +import forge.game.player.Player; +import forge.game.spellability.AbilityStatic; +import forge.game.spellability.TargetRestrictions; + +public class StaticAbilityApiBased extends AbilityStatic { + + private final SpellAbilityEffect effect; + private final SpellAbilityAi ai; + + public StaticAbilityApiBased(ApiType api0, Card sourceCard, Cost abCost, TargetRestrictions tgt, Map params0) { + super(sourceCard, abCost, tgt); + params = params0; + api = api0; + effect = api.getSpellEffect(); + ai = api.getAi(); + + if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) { + AbilityFactory.adjustChangeZoneTarget(params, this); + } + } + + @Override + public String getStackDescription() { + return effect.getStackDescriptionWithSubs(params, this); + } + + + /* (non-Javadoc) + * @see forge.card.spellability.SpellAbility#resolve() + */ + @Override + public void resolve() { + effect.resolve(this); + } + + @Override + public boolean canPlayAI(Player aiPlayer) { + return ai.canPlayAIWithSubs(aiPlayer, this); + } + + @Override + public boolean doTrigger(final boolean mandatory, Player aiPlayer) { + return ai.doTriggerAI(aiPlayer, this, mandatory); + } +} diff --git a/forge-gui/src/main/java/forge/game/ability/effects/DiscardEffect.java b/forge-gui/src/main/java/forge/game/ability/effects/DiscardEffect.java index 0e90a886483..afa89275e17 100644 --- a/forge-gui/src/main/java/forge/game/ability/effects/DiscardEffect.java +++ b/forge-gui/src/main/java/forge/game/ability/effects/DiscardEffect.java @@ -102,15 +102,20 @@ public class DiscardEffect extends SpellAbilityEffect { } final int numCardsInHand = p.getCardsIn(ZoneType.Hand).size(); if (mode.equals("Defined")) { - final List toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa); - for (final Card c : toDiscard) { - boolean hasDiscarded = p.discard(c, sa); - if(hasDiscarded) - discarded.add(c); - } - if (sa.hasParam("RememberDiscarded")) { - for (final Card c : discarded) { - source.addRemembered(c); + boolean runDiscard = !sa.hasParam("Optional") || p.getController().confirmAction(sa, PlayerActionConfirmMode.Random, sa.getParam("DiscardMessage")); + if (runDiscard) { + final List toDiscard = AbilityUtils.getDefinedCards(source, sa.getParam("DefinedCards"), sa); + for (final Card c : toDiscard) { + boolean hasDiscarded = p.discard(c, sa); + if (hasDiscarded) { + discarded.add(c); + } + } + + if (sa.hasParam("RememberDiscarded")) { + for (final Card c : discarded) { + source.addRemembered(c); + } } } continue; diff --git a/forge-gui/src/main/java/forge/game/card/Card.java b/forge-gui/src/main/java/forge/game/card/Card.java index 12ffd541fc0..ddce35304c3 100644 --- a/forge-gui/src/main/java/forge/game/card/Card.java +++ b/forge-gui/src/main/java/forge/game/card/Card.java @@ -1959,8 +1959,7 @@ public class Card extends GameEntity implements Comparable { || keyword.startsWith("PreventAllDamageBy") || keyword.startsWith("CantBlock") || keyword.startsWith("CantEquip") - || keyword.startsWith("SpellCantTarget") - || keyword.equals("MayDiscardFromHand")) { + || keyword.startsWith("SpellCantTarget")) { continue; } if (keyword.startsWith("etbCounter")) { diff --git a/forge-gui/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-gui/src/main/java/forge/game/card/CardFactoryUtil.java index 7e7ff1ca882..ad6a8667ee8 100644 --- a/forge-gui/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-gui/src/main/java/forge/game/card/CardFactoryUtil.java @@ -3193,10 +3193,6 @@ public class CardFactoryUtil { } } // Morph - if (hasKeyword(card, "MayDiscardFromHand") != -1) { - card.addSpellAbility(abilityDiscardSource(card)); // Circling Vultures - } - if (hasKeyword(card, "Unearth") != -1) { final int n = hasKeyword(card, "Unearth"); if (n != -1) { @@ -3451,42 +3447,6 @@ public class CardFactoryUtil { } // Ripple } - /** - * TODO: Write javadoc for this method. - * @param card - * @return - */ - public static AbilityStatic abilityDiscardSource(final Card sourceCard) { - final AbilityStatic discard = new AbilityStatic(sourceCard, new Cost("0", true), null) { - @Override - public void resolve() { - if (this.getActivatingPlayer().getController().confirmAction(this, null, "Discard this card?")) { - this.getActivatingPlayer().discard(sourceCard, this); - } - } - - @Override - public boolean canPlay() { - return sourceCard.isInZone(ZoneType.Hand) - && sourceCard.getController().equals(this.getActivatingPlayer()); - } - - @Override - public boolean canPlayAI(Player aiPlayer) { - return false; - } - - }; - final StringBuilder sb = new StringBuilder(); - sb.append("You may discard ").append(sourceCard.getName()); - sb.append(" any time you could cast an instant."); - discard.setDescription(sb.toString()); - - final StringBuilder sbStack = new StringBuilder(); - sbStack.append(sourceCard.getName()).append(" - discard this card."); - discard.setStackDescription(sbStack.toString()); - return discard; - } public final static void refreshTotemArmor(Card c) { boolean hasKw = c.hasKeyword("Totem armor"); diff --git a/forge-gui/src/main/java/forge/game/spellability/AbilityStatic.java b/forge-gui/src/main/java/forge/game/spellability/AbilityStatic.java index 3ccbf095a90..707171d8947 100644 --- a/forge-gui/src/main/java/forge/game/spellability/AbilityStatic.java +++ b/forge-gui/src/main/java/forge/game/spellability/AbilityStatic.java @@ -20,6 +20,7 @@ package forge.game.spellability; import forge.card.mana.ManaCost; import forge.game.card.Card; import forge.game.cost.Cost; +import forge.game.player.Player; /** *

@@ -50,4 +51,15 @@ public abstract class AbilityStatic extends Ability { this.setTargetRestrictions(tgt); } } + @Override + public boolean canPlay() { + Player player = getActivatingPlayer(); + if (player == null) { + player = this.getSourceCard().getController(); + } + + final Card c = this.getSourceCard(); + + return this.getRestrictions().canPlay(c, this); + } } diff --git a/forge-gui/src/main/java/forge/game/zone/MagicStack.java b/forge-gui/src/main/java/forge/game/zone/MagicStack.java index be79a3efca2..9ec17b15301 100644 --- a/forge-gui/src/main/java/forge/game/zone/MagicStack.java +++ b/forge-gui/src/main/java/forge/game/zone/MagicStack.java @@ -340,7 +340,7 @@ public class MagicStack /* extends MyObservable */ implements Iterable