diff --git a/src/main/java/forge/Card.java b/src/main/java/forge/Card.java index e3b599575be..351303af20a 100644 --- a/src/main/java/forge/Card.java +++ b/src/main/java/forge/Card.java @@ -9152,5 +9152,25 @@ public class Card extends GameEntity implements Comparable { public void setCommander(boolean b) { this.isCommander = b; } - + + public void setSplitStateToPlayAbility(SpellAbility sa) { + if( !isSplitCard() ) return; // just in case + // Split card support + List leftSplitAbilities = getState(CardCharacteristicName.LeftSplit).getSpellAbility(); + List rightSplitAbilities = getState(CardCharacteristicName.RightSplit).getSpellAbility(); + for (SpellAbility a : leftSplitAbilities) { + if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { + setState(CardCharacteristicName.LeftSplit); + return; + } + } + for (SpellAbility a : rightSplitAbilities) { + if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { + setState(CardCharacteristicName.RightSplit); + return; + } + } + throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + this); + } + } // end Card class diff --git a/src/main/java/forge/card/ability/effects/PlayEffect.java b/src/main/java/forge/card/ability/effects/PlayEffect.java index e7fa53acdf4..462dc538810 100644 --- a/src/main/java/forge/card/ability/effects/PlayEffect.java +++ b/src/main/java/forge/card/ability/effects/PlayEffect.java @@ -203,7 +203,7 @@ public class PlayEffect extends SpellAbilityEffect { boolean noManaCost = sa.hasParam("WithoutManaCost"); if (controller.isHuman()) { SpellAbility newSA = noManaCost ? tgtSA.copyWithNoManaCost() : tgtSA; - game.getActionPlay().playSpellAbility(newSA, (HumanPlayer)activator); + ((HumanPlayer)activator).playSpellAbility(newSA); } else { if (tgtSA instanceof Spell) { // Isn't it ALWAYS a spell? Spell spell = (Spell) tgtSA; diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index b73396e34a9..4fd6836501e 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -2914,7 +2914,7 @@ public class CardFactoryUtil { } if (card.getController().isHuman()) { - game.getActionPlay().playSpellAbilityNoStack((HumanPlayer)card.getController(), origSA); + ((HumanPlayer)card.getController()).playSpellAbilityNoStack(origSA); } else { ComputerUtil.playNoStack((AIPlayer) card.getController(), origSA, game); } diff --git a/src/main/java/forge/card/replacement/ReplacementHandler.java b/src/main/java/forge/card/replacement/ReplacementHandler.java index 2de3a967b87..1bad49e95c3 100644 --- a/src/main/java/forge/card/replacement/ReplacementHandler.java +++ b/src/main/java/forge/card/replacement/ReplacementHandler.java @@ -240,7 +240,7 @@ public class ReplacementHandler { Player player = replacementEffect.getHostCard().getController(); //player.getController().playNoStack() if (player.isHuman()) { - game.getActionPlay().playSpellAbilityNoStack((HumanPlayer)player, effectSA); + ((HumanPlayer)player).playSpellAbilityNoStack(effectSA); } else { ComputerUtil.playNoStack((AIPlayer) player, effectSA, game); } diff --git a/src/main/java/forge/card/trigger/TriggerHandler.java b/src/main/java/forge/card/trigger/TriggerHandler.java index 6905be17009..6a0c5c18db1 100644 --- a/src/main/java/forge/card/trigger/TriggerHandler.java +++ b/src/main/java/forge/card/trigger/TriggerHandler.java @@ -420,7 +420,7 @@ public class TriggerHandler { if (regtrig.isStatic()) { if (wrapperAbility.getActivatingPlayer().isHuman()) { - game.getActionPlay().playSpellAbilityNoStack((HumanPlayer)wrapperAbility.getActivatingPlayer(), wrapperAbility); + ((HumanPlayer)wrapperAbility.getActivatingPlayer()).playSpellAbilityNoStack(wrapperAbility); } else { wrapperAbility.doTrigger(isMandatory, (AIPlayer)wrapperAbility.getActivatingPlayer()); ComputerUtil.playNoStack((AIPlayer)wrapperAbility.getActivatingPlayer(), wrapperAbility, game); diff --git a/src/main/java/forge/card/trigger/WrappedAbility.java b/src/main/java/forge/card/trigger/WrappedAbility.java index 9bd4e7dcc77..30770fc53ef 100644 --- a/src/main/java/forge/card/trigger/WrappedAbility.java +++ b/src/main/java/forge/card/trigger/WrappedAbility.java @@ -415,7 +415,7 @@ public class WrappedAbility extends Ability implements ISpellAbility { } if (getActivatingPlayer().isHuman()) { - game.getActionPlay().playSpellAbilityNoStack((HumanPlayer)getActivatingPlayer(), sa, true); + ((HumanPlayer)getActivatingPlayer()).playSpellAbilityNoStack(sa, true); } else { // commented out because i don't think this should be called // again here diff --git a/src/main/java/forge/control/input/InputPayManaBase.java b/src/main/java/forge/control/input/InputPayManaBase.java index 02ed79ecf6e..1e633147e52 100644 --- a/src/main/java/forge/control/input/InputPayManaBase.java +++ b/src/main/java/forge/control/input/InputPayManaBase.java @@ -291,7 +291,7 @@ public abstract class InputPayManaBase extends InputSyncronizedBase implements I Runnable proc = new Runnable() { @Override public void run() { - player.getGame().getActionPlay().playSpellAbility(chosen, (HumanPlayer)chosen.getActivatingPlayer()); + ((HumanPlayer)chosen.getActivatingPlayer()).playSpellAbility(chosen); onManaAbilityPlayed(chosen); } }; diff --git a/src/main/java/forge/game/GameActionPlay.java b/src/main/java/forge/game/GameActionPlay.java index cacc8b2ffe7..fff072e4b3e 100644 --- a/src/main/java/forge/game/GameActionPlay.java +++ b/src/main/java/forge/game/GameActionPlay.java @@ -5,26 +5,20 @@ import java.util.List; import com.google.common.collect.Lists; import forge.Card; -import forge.CardCharacteristicName; import forge.CardColor; import forge.CardLists; import forge.CardPredicates; import forge.FThreads; import forge.card.MagicColor; -import forge.card.ability.AbilityUtils; import forge.card.ability.ApiType; import forge.card.ability.effects.CharmEffect; -import forge.card.cost.Cost; import forge.card.cost.CostPayment; import forge.card.mana.ManaCostBeingPaid; import forge.card.mana.ManaCostShard; import forge.card.spellability.SpellAbility; import forge.card.spellability.HumanPlaySpellAbility; -import forge.card.spellability.Target; import forge.card.staticability.StaticAbility; -import forge.control.input.InputPayManaSimple; import forge.game.ai.ComputerUtilCard; -import forge.game.player.HumanPlayer; import forge.game.player.Player; import forge.game.zone.ZoneType; import forge.gui.GuiChoose; @@ -68,8 +62,7 @@ public class GameActionPlay { FThreads.checkEDT("GameActionPlay.playSpellAbilityWithoutPayingManaCost", false); final Card source = sa.getSourceCard(); - if( source.isSplitCard()) - setSplitCardState(source, sa); + source.setSplitStateToPlayAbility(sa); if (sa.getPayCosts() != null) { if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { @@ -325,142 +318,6 @@ public class GameActionPlay { return manaCost; } - /** - * choose optional additional costs. For HUMAN only - * @param activator - * - * @param original - * the original sa - * @return an ArrayList. - */ - public static SpellAbility chooseOptionalAdditionalCosts(Player activator, final SpellAbility original) { - //final HashMap map = new HashMap(); - final ArrayList abilities = GameActionUtil.getOptionalAdditionalCosts(original); - - if (!original.isSpell()) { - return original; - } - - return activator.getController().getAbilityToPlay(abilities); - } - - /** - *

- * playSpellAbility. - *

- * - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - */ - public final void playSpellAbility(SpellAbility sa, HumanPlayer activator) { - FThreads.checkEDT("Player.playSpellAbility", false); - sa.setActivatingPlayer(activator); - - final Card source = sa.getSourceCard(); - - if(source.isSplitCard()) - setSplitCardState(source, sa); - - if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { - CharmEffect.makeChoices(sa); - } - - sa = chooseOptionalAdditionalCosts(activator, sa); - - if (sa == null) { - return; - } - - // Need to check PayCosts, and Ability + All SubAbilities for Target - boolean newAbility = sa.getPayCosts() != null; - SpellAbility ability = sa; - while ((ability != null) && !newAbility) { - final Target tgt = ability.getTarget(); - - newAbility |= tgt != null; - ability = ability.getSubAbility(); - } - - // System.out.println("Playing:" + sa.getDescription() + " of " + sa.getSourceCard() + " new = " + newAbility); - if (newAbility) { - CostPayment payment = null; - if (sa.getPayCosts() == null) { - payment = new CostPayment(new Cost(sa.getSourceCard(), "0", sa.isAbility()), sa); - } else { - payment = new CostPayment(sa.getPayCosts(), sa); - } - - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); - req.fillRequirements(false, false, false); - } else { - ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); - if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { - manaCost = new ManaCostBeingPaid("0"); - } else { - manaCost = this.getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); - } - - if (!manaCost.isPaid()) { - FThreads.setInputAndWait(new InputPayManaSimple(game, sa, manaCost)); - } - - - if (manaCost.isPaid()) { - if (sa.isSpell() && !source.isCopiedSpell()) { - sa.setSourceCard(game.getAction().moveToStack(source)); - } - - game.getStack().add(sa); - } - } - } - - /** - *

- * playSpellAbility_NoStack. - *

- * - * @param sa - * a {@link forge.card.spellability.SpellAbility} object. - * @param skipTargeting - * a boolean. - */ - public final void playSpellAbilityNoStack(final HumanPlayer human, final SpellAbility sa) { - playSpellAbilityNoStack(human, sa, false); - } - public final void playSpellAbilityNoStack(final HumanPlayer human, final SpellAbility sa, boolean useOldTargets) { - sa.setActivatingPlayer(human); - - if (sa.getPayCosts() != null) { - final CostPayment payment = new CostPayment(sa.getPayCosts(), sa); - - if (!sa.isTrigger()) { - payment.changeCost(); - } - - final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); - - req.fillRequirements(useOldTargets, false, true); - } else { - ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); - if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { - manaCost = new ManaCostBeingPaid("0"); - } else { - manaCost = this.getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); - } - - if( !manaCost.isPaid() ) { - FThreads.setInputAndWait(new InputPayManaSimple(game, sa, getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())))); - } - - if (manaCost.isPaid()) { - AbilityUtils.resolve(sa, false); - } - - } - } - - /** * Gets the convokable colors. * @@ -489,23 +346,4 @@ public class GameActionPlay { return usableColors; } - - private void setSplitCardState(final Card source, SpellAbility sa) { - // Split card support - List leftSplitAbilities = source.getState(CardCharacteristicName.LeftSplit).getSpellAbility(); - List rightSplitAbilities = source.getState(CardCharacteristicName.RightSplit).getSpellAbility(); - for (SpellAbility a : leftSplitAbilities) { - if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { - source.setState(CardCharacteristicName.LeftSplit); - return; - } - } - for (SpellAbility a : rightSplitAbilities) { - if (sa == a || sa.getDescription().equals(String.format("%s (without paying its mana cost)", a.getDescription()))) { - source.setState(CardCharacteristicName.RightSplit); - return; - } - } - throw new RuntimeException("Not found which part to choose for ability " + sa + " from card " + source); - } } diff --git a/src/main/java/forge/game/MatchController.java b/src/main/java/forge/game/MatchController.java index 5884945e7ff..edf8d8c174c 100644 --- a/src/main/java/forge/game/MatchController.java +++ b/src/main/java/forge/game/MatchController.java @@ -362,7 +362,7 @@ public class MatchController { if (GuiDialog.confirm(c, "Use " + c +"'s ability?")) { // If we ever let the AI memorize cards in the players // hand, this would be a place to do so. - currentGame.getActionPlay().playSpellAbilityNoStack((HumanPlayer)p, effect); + ((HumanPlayer)p).playSpellAbilityNoStack(effect); } } } diff --git a/src/main/java/forge/game/player/HumanPlayer.java b/src/main/java/forge/game/player/HumanPlayer.java index a8c14d7ab0d..80fe463e5d3 100644 --- a/src/main/java/forge/game/player/HumanPlayer.java +++ b/src/main/java/forge/game/player/HumanPlayer.java @@ -17,14 +17,25 @@ */ package forge.game.player; +import java.util.ArrayList; import java.util.List; import forge.Card; import forge.FThreads; +import forge.card.ability.AbilityUtils; +import forge.card.ability.ApiType; +import forge.card.ability.effects.CharmEffect; +import forge.card.cost.Cost; +import forge.card.cost.CostPayment; +import forge.card.mana.ManaCostBeingPaid; import forge.card.spellability.Ability; +import forge.card.spellability.HumanPlaySpellAbility; import forge.card.spellability.SpellAbility; +import forge.card.spellability.Target; +import forge.control.input.InputPayManaSimple; import forge.control.input.InputSelectCards; import forge.control.input.InputSelectCardsFromList; +import forge.game.GameActionUtil; import forge.game.GameState; import forge.game.zone.ZoneType; @@ -67,7 +78,7 @@ public class HumanPlayer extends Player { if (ab == Ability.PLAY_LAND_SURROGATE) this.playLand(c); else { - game.getActionPlay().playSpellAbility(ab, this); + this.playSpellAbility(ab); } game.getPhaseHandler().setPriority(this); } @@ -79,5 +90,142 @@ public class HumanPlayer extends Player { public PlayerController getController() { return controller; } + + + /** + *

+ * playSpellAbility. + *

+ * + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + */ + public final void playSpellAbility(SpellAbility sa) { + FThreads.checkEDT("Player.playSpellAbility", false); + sa.setActivatingPlayer(this); + + final Card source = sa.getSourceCard(); + + source.setSplitStateToPlayAbility(sa); + + if (sa.getApi() == ApiType.Charm && !sa.isWrapper()) { + CharmEffect.makeChoices(sa); + } + + sa = chooseOptionalAdditionalCosts(sa); + + if (sa == null) { + return; + } + + // Need to check PayCosts, and Ability + All SubAbilities for Target + boolean newAbility = sa.getPayCosts() != null; + SpellAbility ability = sa; + while ((ability != null) && !newAbility) { + final Target tgt = ability.getTarget(); + + newAbility |= tgt != null; + ability = ability.getSubAbility(); + } + + // System.out.println("Playing:" + sa.getDescription() + " of " + sa.getSourceCard() + " new = " + newAbility); + if (newAbility) { + CostPayment payment = null; + if (sa.getPayCosts() == null) { + payment = new CostPayment(new Cost(sa.getSourceCard(), "0", sa.isAbility()), sa); + } else { + payment = new CostPayment(sa.getPayCosts(), sa); + } + + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); + req.fillRequirements(false, false, false); + } else { + ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); + if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { + manaCost = new ManaCostBeingPaid("0"); + } else { + manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); + } + + if (!manaCost.isPaid()) { + FThreads.setInputAndWait(new InputPayManaSimple(game, sa, manaCost)); + } + + + if (manaCost.isPaid()) { + if (sa.isSpell() && !source.isCopiedSpell()) { + sa.setSourceCard(game.getAction().moveToStack(source)); + } + + game.getStack().add(sa); + } + } + } + + /** + *

+ * playSpellAbility_NoStack. + *

+ * + * @param sa + * a {@link forge.card.spellability.SpellAbility} object. + * @param skipTargeting + * a boolean. + */ + public final void playSpellAbilityNoStack( final SpellAbility sa) { + playSpellAbilityNoStack(sa, false); + } + public final void playSpellAbilityNoStack(final SpellAbility sa, boolean useOldTargets) { + sa.setActivatingPlayer(this); + + if (sa.getPayCosts() != null) { + final CostPayment payment = new CostPayment(sa.getPayCosts(), sa); + + if (!sa.isTrigger()) { + payment.changeCost(); + } + + final HumanPlaySpellAbility req = new HumanPlaySpellAbility(sa, payment); + + req.fillRequirements(useOldTargets, false, true); + } else { + ManaCostBeingPaid manaCost = new ManaCostBeingPaid(sa.getManaCost()); + if (sa.getSourceCard().isCopiedSpell() && sa.isSpell()) { + manaCost = new ManaCostBeingPaid("0"); + } else { + manaCost = game.getActionPlay().getSpellCostChange(sa, new ManaCostBeingPaid(sa.getManaCost())); + } + + if( !manaCost.isPaid() ) { + FThreads.setInputAndWait(new InputPayManaSimple(game, sa, manaCost)); + } + + if (manaCost.isPaid()) { + AbilityUtils.resolve(sa, false); + } + + } + } + + /** + * choose optional additional costs. For HUMAN only + * @param activator + * + * @param original + * the original sa + * @return an ArrayList. + */ + public SpellAbility chooseOptionalAdditionalCosts(final SpellAbility original) { + //final HashMap map = new HashMap(); + final ArrayList abilities = GameActionUtil.getOptionalAdditionalCosts(original); + + if (!original.isSpell()) { + return original; + } + + return getController().getAbilityToPlay(abilities); + } + + } // end HumanPlayer class diff --git a/src/main/java/forge/game/player/PlayerControllerHuman.java b/src/main/java/forge/game/player/PlayerControllerHuman.java index dc52d39ab0c..2dd14120caf 100644 --- a/src/main/java/forge/game/player/PlayerControllerHuman.java +++ b/src/main/java/forge/game/player/PlayerControllerHuman.java @@ -364,14 +364,14 @@ public class PlayerControllerHuman extends PlayerController { @Override public void playMiracle(SpellAbility miracle, Card card) { if (GuiDialog.confirm(card, card + " - Drawn. Play for Miracle Cost?")) { - game.getActionPlay().playSpellAbility(miracle, player); + player.playSpellAbility(miracle); } } @Override public void playMadness(SpellAbility madness) { if (GuiDialog.confirm(madness.getSourceCard(), madness.getSourceCard() + " - Discarded. Pay Madness Cost?")) { - game.getActionPlay().playSpellAbility(madness, player); + player.playSpellAbility(madness); } } } diff --git a/src/main/java/forge/game/zone/MagicStack.java b/src/main/java/forge/game/zone/MagicStack.java index 349d1f8d1b6..e14a936792a 100644 --- a/src/main/java/forge/game/zone/MagicStack.java +++ b/src/main/java/forge/game/zone/MagicStack.java @@ -1125,7 +1125,7 @@ public class MagicStack extends MyObservable { for (int i = size - 1; i >= 0; i--) { SpellAbility next = orderedSAs.get(i); if (next.isTrigger()) { - game.getActionPlay().playSpellAbility(next, (HumanPlayer)activePlayer); + ((HumanPlayer)activePlayer).playSpellAbility(next); } else { this.add(next); }