package forge.card.spellability; import forge.AllZone; import forge.Card; import forge.PlayerZone; import forge.card.abilityFactory.AbilityFactory; import java.util.ArrayList; /** * <p>SpellAbility_Requirements class.</p> * * @author Forge * @version $Id: $ */ public class SpellAbility_Requirements { private SpellAbility ability = null; private Target_Selection select = null; private Cost_Payment payment = null; private boolean isFree = false; private boolean skipStack = false; /** * <p>Setter for the field <code>skipStack</code>.</p> * * @param bSkip a boolean. */ public void setSkipStack(boolean bSkip) { skipStack = bSkip; } /** * <p>setFree.</p> * * @param bFree a boolean. */ public void setFree(boolean bFree) { isFree = bFree; } private PlayerZone fromZone = null; private boolean bCasting = false; /** * <p>Constructor for SpellAbility_Requirements.</p> * * @param sa a {@link forge.card.spellability.SpellAbility} object. * @param ts a {@link forge.card.spellability.Target_Selection} object. * @param cp a {@link forge.card.spellability.Cost_Payment} object. */ public SpellAbility_Requirements(SpellAbility sa, Target_Selection ts, Cost_Payment cp) { ability = sa; select = ts; payment = cp; } /** * <p>fillRequirements.</p> */ public void fillRequirements() { fillRequirements(false); } /** * <p>fillRequirements.</p> * * @param skipTargeting a boolean. */ public void fillRequirements(boolean skipTargeting) { if (ability instanceof Spell && !bCasting) { // remove from hand bCasting = true; if (!ability.getSourceCard().isCopiedSpell()) { Card c = ability.getSourceCard(); fromZone = AllZone.getZone(c); AllZone.getGameAction().moveToStack(c); } } // freeze Stack. No abilities should go onto the stack while I'm filling requirements. AllZone.getStack().freezeStack(); // Skip to paying if parent ability doesn't target and has no subAbilities. (or trigger case where its already targeted) if (!skipTargeting && (select.doesTarget() || ability.getSubAbility() != null)) { select.setRequirements(this); select.resetTargets(); select.chooseTargets(); } else needPayment(); } /** * <p>finishedTargeting.</p> */ public void finishedTargeting() { if (select.isCanceled()) { // cancel ability during target choosing Card c = ability.getSourceCard(); if (bCasting && !c.isCopiedSpell()) { // and not a copy // add back to where it came from AllZone.getGameAction().moveTo(fromZone, c); } select.resetTargets(); AllZone.getStack().clearFrozen(); return; } else needPayment(); } /** * <p>needPayment.</p> */ public void needPayment() { if (!isFree) startPaying(); else finishPaying(); } /** * <p>startPaying.</p> */ public void startPaying() { payment.setRequirements(this); payment.payCost(); } /** * <p>finishPaying.</p> */ public void finishPaying() { if (isFree || payment.isAllPaid()) { if (skipStack) AbilityFactory.resolve(ability, false); else addAbilityToStack(); select.resetTargets(); AllZone.getGameAction().checkStateEffects(); } else if (payment.isCanceled()) { Card c = ability.getSourceCard(); if (bCasting && !c.isCopiedSpell()) { // and not a copy // add back to Previous Zone AllZone.getGameAction().moveTo(fromZone, c); } if (select != null) select.resetTargets(); payment.cancelPayment(); AllZone.getStack().clearFrozen(); } } /** * <p>addAbilityToStack.</p> */ public void addAbilityToStack() { // For older abilities that don't setStackDescription set it here if (ability.getStackDescription().equals("")) { StringBuilder sb = new StringBuilder(); sb.append(ability.getSourceCard().getName()); if (ability.getTarget() != null) { ArrayList<Object> targets = ability.getTarget().getTargets(); if (targets.size() > 0) { sb.append(" - Targeting "); for (Object o : targets) sb.append(o.toString()).append(" "); } } ability.setStackDescription(sb.toString()); } AllZone.getManaPool().clearPay(ability, false); AllZone.getStack().addAndUnfreeze(ability); } }