Additional and alternative costs improved:

* Now player must choose additional costs before ability's modes;
* Fixed broken kicker ability from ZNR (see comments from d4ca287f0f);
* Improved compatibility of additional cost with cost modification effects (fixed that optional multi-costs doesn't affected by cost modification);
* Improved compatibility of additional cost with alternative cost (some cards ignores additional cost on alternative usage, e.g. on play free);
This commit is contained in:
Oleg Agafonov 2020-09-13 09:56:55 +04:00
parent 586538a66c
commit 6e0c7e868c
17 changed files with 504 additions and 156 deletions

View file

@ -1,6 +1,5 @@
package mage.abilities;
import mage.abilities.condition.common.KickedCondition;
import mage.abilities.costs.OptionalAdditionalModeSourceCosts;
import mage.cards.Card;
import mage.constants.Outcome;
@ -33,11 +32,9 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
private TargetController modeChooser;
private boolean eachModeMoreThanOnce; // each mode can be selected multiple times during one choice
private boolean eachModeOnlyOnce; // state if each mode can be chosen only once as long as the source object exists
private OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts = null; // only set if costs have to be paid
private Filter maxModesFilter = null; // calculates the max number of available modes
private boolean isRandom = false;
private String chooseText = null;
private boolean allWhenKicked = false;
private boolean resetEachTurn = false;
private int turnNum = 0;
@ -68,12 +65,10 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.modeChooser = modes.modeChooser;
this.eachModeOnlyOnce = modes.eachModeOnlyOnce;
this.eachModeMoreThanOnce = modes.eachModeMoreThanOnce;
this.optionalAdditionalModeSourceCosts = modes.optionalAdditionalModeSourceCosts;
this.maxModesFilter = modes.maxModesFilter; // can't change so no copy needed
this.isRandom = modes.isRandom;
this.chooseText = modes.chooseText;
this.allWhenKicked = modes.allWhenKicked;
this.resetEachTurn = modes.resetEachTurn;
this.turnNum = modes.turnNum;
if (modes.getSelectedModes().isEmpty()) {
@ -228,15 +223,6 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.turnNum = game.getTurnNum();
}
}
if (this.allWhenKicked) {
if (KickedCondition.instance.apply(game, source)) {
this.setMinModes(0);
this.setMaxModes(3);
} else {
this.setMinModes(1);
this.setMaxModes(1);
}
}
if (this.size() > 1) {
this.clearSelectedModes();
if (this.isRandom) {
@ -244,15 +230,18 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.addSelectedMode(modes.get(RandomUtil.nextInt(modes.size())).getId());
return true;
}
// check if mode modifying abilities exist
Card card = game.getCard(source.getSourceId());
if (card != null) {
for (Ability modeModifyingAbility : card.getAbilities()) {
for (Ability modeModifyingAbility : card.getAbilities(game)) {
if (modeModifyingAbility instanceof OptionalAdditionalModeSourceCosts) {
// cost must check activation conditional in changeModes
((OptionalAdditionalModeSourceCosts) modeModifyingAbility).changeModes(source, game);
}
}
}
// check if all modes can be activated automatically
if (this.size() == this.getMinModes() && !isEachModeMoreThanOnce()) {
Set<UUID> onceSelectedModes = null;
@ -434,8 +423,6 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
StringBuilder sb = new StringBuilder();
if (this.chooseText != null) {
sb.append(chooseText);
} else if (this.allWhenKicked) {
sb.append("choose one. If this spell was kicked, choose any number instead.");
} else if (this.getMaxModesFilter() != null) {
sb.append("choose one or more. Each mode must target ").append(getMaxModesFilter().getMessage());
} else if (this.getMinModes() == 0 && this.getMaxModes() == 1) {
@ -499,22 +486,10 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
this.eachModeMoreThanOnce = eachModeMoreThanOnce;
}
public OptionalAdditionalModeSourceCosts getAdditionalCost() {
return optionalAdditionalModeSourceCosts;
}
public void setAdditionalCost(OptionalAdditionalModeSourceCosts optionalAdditionalModeSourceCosts) {
this.optionalAdditionalModeSourceCosts = optionalAdditionalModeSourceCosts;
}
public void setRandom(boolean isRandom) {
this.isRandom = isRandom;
}
public void setAllWhenKicked(boolean allWhenKicked) {
this.allWhenKicked = allWhenKicked;
}
public boolean isResetEachTurn() {
return resetEachTurn;
}