// For Flashback ability can be set X before, so the X costs have to be restored for the flashbacked ability
if (noMana) {
if (this.getManaCostsToPay().getVariableCosts().size() > 0) {
int xValue = this.getManaCostsToPay().getX();
this.getManaCostsToPay().clear();
VariableManaCost xCosts = new VariableManaCost();
xCosts.setAmount(xValue);
this.getManaCostsToPay().add(xCosts);
} else {
this.getManaCostsToPay().clear();
}
}
// 20130201 - 601.2b
// If the spell has alternative or additional costs that will be paid as it's being cast such
// as buyback, kicker, or convoke costs (see rules 117.8 and 117.9), the player announces his
// or her intentions to pay any or all of those costs (see rule 601.2e).
// A player can't apply two alternative methods of casting or two alternative costs to a single spell.
if (sourceObject != null && !(this instanceof FlashbackAbility)) {
boolean alternativeCostisUsed = false;
for (Ability ability : sourceObject.getAbilities()) {
// if cast for noMana no Alternative costs are allowed
if (!noMana && ability instanceof AlternativeSourceCosts) {
AlternativeSourceCosts alternativeSpellCosts = (AlternativeSourceCosts) ability;
if (alternativeSpellCosts.isAvailable(this, game)) {
if (alternativeSpellCosts.askToActivateAlternativeCosts(this, game)) {
// only one alternative costs may be activated
alternativeCostisUsed = true;
break;
}
}
}
if (ability instanceof OptionalAdditionalSourceCosts) {
((OptionalAdditionalSourceCosts)ability).addOptionalAdditionalCosts(this, game);
}
}
// controller specific alternate spell costs
if (!noMana && !alternativeCostisUsed) {
if (this.getAbilityType().equals(AbilityType.SPELL)) {
for (AlternativeSourceCosts alternativeSourceCosts: controller.getAlternativeSourceCosts()) {
if (alternativeSourceCosts.isAvailable(this, game)) {
if (alternativeSourceCosts.askToActivateAlternativeCosts(this, game)) {
// only one alternative costs may be activated
break;
}
}
}
}
}
}
// 20121001 - 601.2b
// If the spell has a variable cost that will be paid as it's being cast (such as an {X} in
// its mana cost; see rule 107.3), the player announces the value of that variable.
VariableManaCost variableManaCost = handleManaXCosts(game, noMana, controller);
String announceString = handleOtherXCosts(game, controller);
for (UUID modeId :this.getModes().getSelectedModes()) {
this.getModes().setMode(this.getModes().get(modeId));
//20121001 - 601.2c
// 601.2c The player announces his or her choice of an appropriate player, object, or zone for
// each target the spell requires. A spell may require some targets only if an alternative or
// additional cost (such as a buyback or kicker cost), or a particular mode, was chosen for it;
// otherwise, the spell is cast as though it did not require those targets. If the spell has a
// variable number of targets, the player announces how many targets he or she will choose before
// he or she announces those targets. The same target can't be chosen multiple times for any one
// instance of the word "target" on the spell. However, if the spell uses the word "target" in
// multiple places, the same object, player, or zone can be chosen once for each instance of the
// word "target" (as long as it fits the targeting criteria). If any effects say that an object
// or player must be chosen as a target, the player chooses targets so that he or she obeys the
// maximum possible number of such effects without violating any rules or effects that say that
// an object or player can't be chosen as a target. The chosen players, objects, and/or zones
// each become a target of that spell. (Any abilities that trigger when those players, objects,
// and/or zones become the target of a spell trigger at this point; they'll wait to be put on
// the stack until the spell has finished being cast.)
if (sourceObject != null) {
sourceObject.adjustTargets(this, game);
}
if (getTargets().size() > 0 && getTargets().chooseTargets(getEffects().get(0).getOutcome(), this.controllerId, this, game) == false) {
if (variableManaCost != null || announceString != null) {
game.informPlayer(controller, new StringBuilder(sourceObject != null ? sourceObject.getLogName(): "").append(": no valid targets with this value of X").toString());
}
return false; // when activation of ability is canceled during target selection
}
} // end modes
// TODO: Handle optionalCosts at the same time as already OptionalAdditionalSourceCosts are handled.
for (Cost cost : optionalCosts) {
if (cost instanceof ManaCost) {
cost.clearPaid();
if (controller.chooseUse(Outcome.Benefit, "Pay optional cost " + cost.getText() + "?", game)) {
manaCostsToPay.add((ManaCost) cost);
}
}
}
//20100716 - 601.2e
if (sourceObject != null) {
sourceObject.adjustCosts(this, game);
for (Ability ability : sourceObject.getAbilities()) {
if (ability instanceof AdjustingSourceCosts) {
((AdjustingSourceCosts)ability).adjustCosts(this, game);
}
}
}
// this is a hack to prevent mana abilities with mana costs from causing endless loops - pay other costs first
if (this instanceof ManaAbility && !costs.pay(this, game, sourceId, controllerId, noMana)) {
logger.debug("activate mana ability failed - non mana costs");
return false;
}
//20101001 - 601.2e
if (costModificationActive) {
game.getContinuousEffects().costModification(this, game);
} else {
costModificationActive = true;
}
UUID activatorId = controllerId;
if ((this instanceof ActivatedAbilityImpl) && ((ActivatedAbilityImpl)this).getActivatorId()!= null) {
activatorId = ((ActivatedAbilityImpl)this).getActivatorId();
}
if (!useAlternativeCost(game)) { // old way still used?
//20100716 - 601.2f (noMana is not used here, because mana costs were cleared for this ability before adding additional costs and applying cost modification effects)
if (!manaCostsToPay.pay(this, game, sourceId, activatorId, false)) {
return false; // cancel during mana payment
}
}
//20100716 - 601.2g
if (!costs.pay(this, game, sourceId, activatorId, noMana)) {
logger.debug("activate failed - non mana costs");
return false;
}
// inform about x costs now, so canceled announcements are not shown in the log
if (announceString != null) {
game.informPlayers(announceString);
}
if (variableManaCost != null) {
int xValue = getManaCostsToPay().getX();
game.informPlayers(new StringBuilder(controller.getName()).append(" announces a value of ").append(xValue).append(" for ").append(variableManaCost.getText()).toString());
}
activated = true;
// fire if tapped for mana (may only fires now because else costs of ability itself can be payed with mana of abilities that trigger for that event
if (this.getAbilityType().equals(AbilityType.MANA)) {
for (Cost cost: costs) {