mirror of
https://github.com/correl/mage.git
synced 2024-11-16 03:00:12 +00:00
Some changes to kicker implementation.
This commit is contained in:
parent
9f140579e5
commit
66ebfb6aa3
7 changed files with 173 additions and 20 deletions
|
@ -30,7 +30,6 @@ package mage.abilities.condition.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.costs.OptionalAdditionalCost;
|
|
||||||
import mage.abilities.keyword.KickerAbility;
|
import mage.abilities.keyword.KickerAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
|
|
@ -3,7 +3,6 @@ package mage.abilities.condition.common;
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.costs.OptionalAdditionalCost;
|
import mage.abilities.costs.OptionalAdditionalCost;
|
||||||
import mage.abilities.costs.mana.KickerManaCost;
|
|
||||||
import mage.abilities.keyword.KickerAbility;
|
import mage.abilities.keyword.KickerAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
@ -15,10 +14,10 @@ import mage.game.Game;
|
||||||
*/
|
*/
|
||||||
public class KickedCostCondition implements Condition {
|
public class KickedCostCondition implements Condition {
|
||||||
|
|
||||||
protected KickerManaCost kickerManaCost;
|
protected String kickerCostText;
|
||||||
|
|
||||||
public KickedCostCondition(KickerManaCost kickerManaCost) {
|
public KickedCostCondition(String kickerCostText) {
|
||||||
this.kickerManaCost = kickerManaCost;
|
this.kickerCostText = kickerCostText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -33,7 +32,7 @@ public class KickedCostCondition implements Condition {
|
||||||
}
|
}
|
||||||
if (kickerAbility != null) {
|
if (kickerAbility != null) {
|
||||||
for (OptionalAdditionalCost cost: kickerAbility.getKickerCosts()) {
|
for (OptionalAdditionalCost cost: kickerAbility.getKickerCosts()) {
|
||||||
if (cost.equals(kickerManaCost)) {
|
if (cost.getText(true).equals(kickerCostText)) {
|
||||||
return cost.isActivated();
|
return cost.isActivated();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -74,6 +74,12 @@ public interface OptionalAdditionalCost extends Cost {
|
||||||
*/
|
*/
|
||||||
public void reset();
|
public void reset();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the cost be multiple times activated
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setRepeatable(boolean repeatable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can the cost be multiple times activated
|
* Can the cost be multiple times activated
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
|
|
||||||
package mage.abilities.costs;
|
package mage.abilities.costs;
|
||||||
|
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author LevelX2
|
* @author LevelX2
|
||||||
|
@ -41,14 +39,21 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
|
|
||||||
protected String name;
|
protected String name;
|
||||||
protected String reminderText;
|
protected String reminderText;
|
||||||
|
protected String delimiter;
|
||||||
|
|
||||||
protected boolean activated;
|
protected boolean activated;
|
||||||
protected int activatedCounter;
|
protected int activatedCounter;
|
||||||
protected boolean repeatable;
|
protected boolean repeatable;
|
||||||
|
|
||||||
public OptionalAdditionalCostImpl(String name, String reminderText, Cost cost) {
|
public OptionalAdditionalCostImpl(String name, String reminderText, Cost cost) {
|
||||||
|
this(name, " ", reminderText, cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OptionalAdditionalCostImpl(String name, String delimiter, String reminderText, Cost cost) {
|
||||||
this.activated = false;
|
this.activated = false;
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.reminderText = reminderText;
|
this.delimiter = delimiter;
|
||||||
|
this.reminderText = new StringBuilder("<i>").append(reminderText).append("</i>").toString();
|
||||||
this.activatedCounter = 0;
|
this.activatedCounter = 0;
|
||||||
this.add((Cost) cost);
|
this.add((Cost) cost);
|
||||||
}
|
}
|
||||||
|
@ -59,6 +64,7 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
this.reminderText = cost.reminderText;
|
this.reminderText = cost.reminderText;
|
||||||
this.activated = cost.activated;
|
this.activated = cost.activated;
|
||||||
this.activatedCounter = cost.activatedCounter;
|
this.activatedCounter = cost.activatedCounter;
|
||||||
|
this.delimiter = cost.delimiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -67,7 +73,7 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the complete text for the addional coast or if onlyCost is true
|
* Returns the complete text for the addional cost or if onlyCost is true
|
||||||
* only the pure text fore the included native cost
|
* only the pure text fore the included native cost
|
||||||
*
|
*
|
||||||
* @param onlyCost
|
* @param onlyCost
|
||||||
|
@ -78,7 +84,7 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
if (onlyCost) {
|
if (onlyCost) {
|
||||||
return getText();
|
return getText();
|
||||||
} else {
|
} else {
|
||||||
return name + " " + getText();
|
return new StringBuffer(name).append(delimiter).append(getText()).toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +111,12 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String getCastSuffixMessage(int position) {
|
public String getCastSuffixMessage(int position) {
|
||||||
return " with " + name;
|
StringBuilder sb = new StringBuilder(position > 0 ? " and ":"").append(" with ");
|
||||||
|
if (isRepeatable()) {
|
||||||
|
sb.append(getActivateCount()).append(getActivateCount() > 1? " times ":" time ");
|
||||||
|
}
|
||||||
|
sb.append(name);
|
||||||
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,6 +141,14 @@ public class OptionalAdditionalCostImpl <T extends OptionalAdditionalCostImpl<T>
|
||||||
activatedCounter = 0;
|
activatedCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set if the cost be multiple times activated
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setRepeatable(boolean repeatable) {
|
||||||
|
this.repeatable = repeatable;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Can the cost be multiple times activated
|
* Can the cost be multiple times activated
|
||||||
*
|
*
|
||||||
|
|
|
@ -28,7 +28,6 @@
|
||||||
package mage.abilities.dynamicvalue.common;
|
package mage.abilities.dynamicvalue.common;
|
||||||
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.costs.OptionalAdditionalCost;
|
|
||||||
import mage.abilities.dynamicvalue.DynamicValue;
|
import mage.abilities.dynamicvalue.DynamicValue;
|
||||||
import mage.abilities.keyword.KickerAbility;
|
import mage.abilities.keyword.KickerAbility;
|
||||||
import mage.cards.Card;
|
import mage.cards.Card;
|
||||||
|
|
|
@ -39,24 +39,78 @@ import mage.abilities.StaticAbility;
|
||||||
import mage.abilities.costs.Cost;
|
import mage.abilities.costs.Cost;
|
||||||
import mage.abilities.costs.Costs;
|
import mage.abilities.costs.Costs;
|
||||||
import mage.abilities.costs.OptionalAdditionalCost;
|
import mage.abilities.costs.OptionalAdditionalCost;
|
||||||
|
import mage.abilities.costs.OptionalAdditionalCostImpl;
|
||||||
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
import mage.abilities.costs.OptionalAdditionalSourceCosts;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 20121001 702.31. Kicker
|
||||||
|
* 702.31a Kicker is a static ability that functions while the spell with kicker
|
||||||
|
* is on the stack. "Kicker [cost]" means "You may pay an additional [cost]
|
||||||
|
* as you cast this spell." Paying a spell's kicker cost(s) follows the
|
||||||
|
* rules for paying additional costs in rules 601.2b and 601.2e-g.
|
||||||
|
* 702.31b The phrase "Kicker [cost 1] and/or [cost 2]" means the same thing as
|
||||||
|
* "Kicker [cost 1], kicker [cost 2]."
|
||||||
|
* 702.31c Multikicker is a variant of the kicker ability. "Multikicker [cost]"
|
||||||
|
* means "You may pay an additional [cost] any number of times as you cast
|
||||||
|
* this spell." A multikicker cost is a kicker cost.
|
||||||
|
* 702.31d If a spell's controller declares the intention to pay any of that spell's
|
||||||
|
* kicker costs, that spell has been "kicked." If a spell has two kicker
|
||||||
|
* costs or has multikicker, it may be kicked multiple times. See rule 601.2b.
|
||||||
|
* 702.31e Objects with kicker or multikicker have additional abilities that specify
|
||||||
|
* what happens if they are kicked. These abilities are linked to the kicker
|
||||||
|
* or multikicker abilities printed on that object: they can refer only to
|
||||||
|
* those specific kicker or multikicker abilities. See rule 607,
|
||||||
|
* "Linked Abilities."
|
||||||
|
* 702.31f Objects with more than one kicker cost have abilities that each correspond
|
||||||
|
* to a specific kicker cost. They contain the phrases "if it was kicked with
|
||||||
|
* its [A] kicker" and "if it was kicked with its [B] kicker," where A and B
|
||||||
|
* are the first and second kicker costs listed on the card, respectively. Each
|
||||||
|
* of those abilities is linked to the appropriate kicker ability.
|
||||||
|
* 702.31g If part of a spell's ability has its effect only if that spell was kicked,
|
||||||
|
* and that part of the ability includes any targets, the spell's controller
|
||||||
|
* chooses those targets only if that spell was kicked. Otherwise, the spell is
|
||||||
|
* cast as if it did not have those targets. See rule 601.2c.
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*
|
||||||
|
*/
|
||||||
public class KickerAbility extends StaticAbility<KickerAbility> implements OptionalAdditionalSourceCosts {
|
public class KickerAbility extends StaticAbility<KickerAbility> implements OptionalAdditionalSourceCosts {
|
||||||
|
|
||||||
|
protected static final String KickerKeyword = "Kicker";
|
||||||
|
protected static final String KickerReminderMana = "(You may pay an additional {cost} as you cast this spell.)";
|
||||||
|
protected static final String KickerReminderCost = "(You may {cost} in addition to any other costs as you cast this spell.)";
|
||||||
|
|
||||||
|
protected String keywordText;
|
||||||
|
protected String reminderText;
|
||||||
protected List<OptionalAdditionalCost> kickerCosts = new LinkedList<OptionalAdditionalCost>();
|
protected List<OptionalAdditionalCost> kickerCosts = new LinkedList<OptionalAdditionalCost>();
|
||||||
|
|
||||||
public KickerAbility(OptionalAdditionalCost kickerCost) {
|
public KickerAbility(String manaString) {
|
||||||
|
this(KickerKeyword, KickerReminderMana);
|
||||||
|
this.addKickerCost(manaString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KickerAbility(Cost cost) {
|
||||||
|
this(KickerKeyword, KickerReminderCost);
|
||||||
|
this.addKickerCost(cost);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KickerAbility(String keywordText, String reminderText) {
|
||||||
super(Zone.STACK, null);
|
super(Zone.STACK, null);
|
||||||
kickerCosts.add(kickerCost);
|
name = keywordText;
|
||||||
|
this.keywordText = keywordText;
|
||||||
|
this.reminderText = reminderText;
|
||||||
setRuleAtTheTop(true);
|
setRuleAtTheTop(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public KickerAbility(final KickerAbility ability) {
|
public KickerAbility(final KickerAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.kickerCosts = ability.kickerCosts;
|
this.kickerCosts = ability.kickerCosts;
|
||||||
|
this.keywordText = ability.keywordText;
|
||||||
|
this.reminderText = ability.reminderText;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -64,6 +118,18 @@ public class KickerAbility extends StaticAbility<KickerAbility> implements Optio
|
||||||
return new KickerAbility(this);
|
return new KickerAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public final OptionalAdditionalCost addKickerCost(String manaString) {
|
||||||
|
OptionalAdditionalCost kickerCost = new OptionalAdditionalCostImpl(keywordText, reminderText, new ManaCostsImpl(manaString));
|
||||||
|
kickerCosts.add(kickerCost);
|
||||||
|
return kickerCost;
|
||||||
|
}
|
||||||
|
|
||||||
|
public final OptionalAdditionalCost addKickerCost(Cost cost) {
|
||||||
|
OptionalAdditionalCost kickerCost = new OptionalAdditionalCostImpl(keywordText, "-", reminderText, cost);
|
||||||
|
kickerCosts.add(kickerCost);
|
||||||
|
return kickerCost;
|
||||||
|
}
|
||||||
|
|
||||||
public void resetKicker() {
|
public void resetKicker() {
|
||||||
for (OptionalAdditionalCost cost: kickerCosts) {
|
for (OptionalAdditionalCost cost: kickerCosts) {
|
||||||
cost.reset();
|
cost.reset();
|
||||||
|
@ -91,10 +157,6 @@ public class KickerAbility extends StaticAbility<KickerAbility> implements Optio
|
||||||
return kickerCosts;
|
return kickerCosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addKickerManaCost(OptionalAdditionalCost kickerCost) {
|
|
||||||
kickerCosts.add(kickerCost);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
||||||
if (ability instanceof SpellAbility) {
|
if (ability instanceof SpellAbility) {
|
||||||
|
@ -109,7 +171,8 @@ public class KickerAbility extends StaticAbility<KickerAbility> implements Optio
|
||||||
int activated = kickerCost.getActivateCount();
|
int activated = kickerCost.getActivateCount();
|
||||||
times = Integer.toString(activated + 1) + (activated == 0 ? " time ":" times ");
|
times = Integer.toString(activated + 1) + (activated == 0 ? " time ":" times ");
|
||||||
}
|
}
|
||||||
if (player.chooseUse(Constants.Outcome.Benefit, "Pay " + times + kickerCost.getText(false) + " ?", game)) {
|
if (kickerCost.canPay(sourceId, controllerId, game) &&
|
||||||
|
player.chooseUse(Constants.Outcome.Benefit, new StringBuilder("Pay ").append(times).append(kickerCost.getText(false)).append(" ?").toString(), game)) {
|
||||||
kickerCost.activate();
|
kickerCost.activate();
|
||||||
for (Iterator it = ((Costs) kickerCost).iterator(); it.hasNext();) {
|
for (Iterator it = ((Costs) kickerCost).iterator(); it.hasNext();) {
|
||||||
Cost cost = (Cost) it.next();
|
Cost cost = (Cost) it.next();
|
||||||
|
|
68
Mage/src/mage/abilities/keyword/MultikickerAbility.java
Normal file
68
Mage/src/mage/abilities/keyword/MultikickerAbility.java
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2010 BetaSteward_at_googlemail.com. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification, are
|
||||||
|
* permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* 1. Redistributions of source code must retain the above copyright notice, this list of
|
||||||
|
* conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
||||||
|
* of conditions and the following disclaimer in the documentation and/or other materials
|
||||||
|
* provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY BetaSteward_at_googlemail.com ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||||
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BetaSteward_at_googlemail.com OR
|
||||||
|
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
|
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* The views and conclusions contained in the software and documentation are those of the
|
||||||
|
* authors and should not be interpreted as representing official policies, either expressed
|
||||||
|
* or implied, of BetaSteward_at_googlemail.com.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
|
import mage.abilities.costs.Cost;
|
||||||
|
import mage.abilities.costs.OptionalAdditionalCost;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 20121001 702.31c Multikicker is a variant of the kicker ability. "Multikicker [cost]" means
|
||||||
|
* "You may pay an additional [cost] any number of times as you cast this spell."
|
||||||
|
* A multikicker cost is a kicker cost.
|
||||||
|
*
|
||||||
|
* @author LevelX2
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class MultikickerAbility extends KickerAbility {
|
||||||
|
|
||||||
|
protected static final String MultikickerKeyword = "Multikicker";
|
||||||
|
protected static final String MultikickerReminder = "(You may pay an additional {cost} any number of times as you cast this spell.)";
|
||||||
|
|
||||||
|
public MultikickerAbility(String manaString) {
|
||||||
|
super(MultikickerKeyword, MultikickerReminder);
|
||||||
|
OptionalAdditionalCost multikickerCost = this.addKickerCost(manaString);
|
||||||
|
multikickerCost.setRepeatable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultikickerAbility(Cost cost) {
|
||||||
|
super(MultikickerKeyword, MultikickerReminder);
|
||||||
|
OptionalAdditionalCost multikickerCost =this.addKickerCost(cost);
|
||||||
|
multikickerCost.setRepeatable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public MultikickerAbility(final MultikickerAbility ability) {
|
||||||
|
super(ability);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MultikickerAbility copy() {
|
||||||
|
return new MultikickerAbility(this);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue