mirror of
https://github.com/magefree/mage.git
synced 2025-12-29 15:02:13 -08:00
Refactor: private fields and performance tweaks (#9625)
1a. Make `costs`, `manaCosts`, and `manaCostsToPay` private in `AbilityImpl` with access through getters/setters 1b. fix cost adjuster for imprinted cards affected by the above 2a. Lazy instantiation for rarely used `data` field in `TargetPointerImpl` 3a. Pre-allocate certain array sizes in `Modes` and `CostsImpl` 4a. Make `manaTemplate` private in `BasicManaEffect`, copy when passing outside the class 4b. Don't copy `manaTemplate` in copy constructor since it doesn't change 4c. Add comments explaining copy usage for `manaTemplate` 4d. Remove redundant variable assignment and make fields final --------- Co-authored-by: xenohedron <xenohedron@users.noreply.github.com>
This commit is contained in:
parent
53be4f384e
commit
a2162ec3e7
65 changed files with 262 additions and 196 deletions
|
|
@ -102,6 +102,18 @@ public interface Ability extends Controllable, Serializable {
|
|||
*/
|
||||
void setSourceId(UUID sourceID);
|
||||
|
||||
default void clearCosts() {
|
||||
getCosts().clear();
|
||||
}
|
||||
|
||||
default void clearManaCosts() {
|
||||
getManaCosts().clear();
|
||||
}
|
||||
|
||||
default void clearManaCostsToPay() {
|
||||
getManaCostsToPay().clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all {@link Costs} associated with this ability.
|
||||
*
|
||||
|
|
@ -151,6 +163,8 @@ public interface Ability extends Controllable, Serializable {
|
|||
*/
|
||||
void addManaCost(ManaCost cost);
|
||||
|
||||
void addManaCostsToPay(ManaCost manaCost);
|
||||
|
||||
/**
|
||||
* Retrieves the effects that are put into the place by the resolution of
|
||||
* this ability.
|
||||
|
|
|
|||
|
|
@ -56,9 +56,9 @@ public abstract class AbilityImpl implements Ability {
|
|||
protected AbilityType abilityType;
|
||||
protected UUID controllerId;
|
||||
protected UUID sourceId;
|
||||
protected ManaCosts<ManaCost> manaCosts;
|
||||
protected ManaCosts<ManaCost> manaCostsToPay;
|
||||
protected Costs<Cost> costs;
|
||||
private ManaCosts<ManaCost> manaCosts;
|
||||
private ManaCosts<ManaCost> manaCostsToPay;
|
||||
private Costs<Cost> costs;
|
||||
protected Modes modes; // access to it by GetModes only (it can be overridden by some abilities)
|
||||
protected Zone zone;
|
||||
protected String name;
|
||||
|
|
@ -253,14 +253,14 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (noMana) {
|
||||
if (!this.getManaCostsToPay().getVariableCosts().isEmpty()) {
|
||||
int xValue = this.getManaCostsToPay().getX();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCostsToPay();
|
||||
VariableManaCost xCosts = new VariableManaCost(VariableCostType.ADDITIONAL);
|
||||
// no x events - rules from Unbound Flourishing:
|
||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||
xCosts.setAmount(xValue, xValue, false);
|
||||
this.getManaCostsToPay().add(xCosts);
|
||||
addManaCostsToPay(xCosts);
|
||||
} else {
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCostsToPay();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -379,7 +379,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
// this is a hack to prevent mana abilities with mana costs from causing endless loops - pay other costs first
|
||||
if (this instanceof ActivatedManaAbilityImpl && !costs.pay(this, game, this, controllerId, noMana, null)) {
|
||||
if (this instanceof ActivatedManaAbilityImpl && !getCosts().pay(this, game, this, controllerId, noMana, null)) {
|
||||
logger.debug("activate mana ability failed - non mana costs");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -396,12 +396,12 @@ public abstract class AbilityImpl implements Ability {
|
|||
}
|
||||
|
||||
//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, this, activatorId, false, null)) {
|
||||
if (!getManaCostsToPay().pay(this, game, this, activatorId, false, null)) {
|
||||
return false; // cancel during mana payment
|
||||
}
|
||||
|
||||
//20100716 - 601.2g
|
||||
if (!costs.pay(this, game, this, activatorId, noMana, null)) {
|
||||
if (!getCosts().pay(this, game, this, activatorId, noMana, null)) {
|
||||
logger.debug("activate failed - non mana costs");
|
||||
return false;
|
||||
}
|
||||
|
|
@ -509,13 +509,11 @@ public abstract class AbilityImpl implements Ability {
|
|||
*/
|
||||
protected String handleOtherXCosts(Game game, Player controller) {
|
||||
StringBuilder announceString = new StringBuilder();
|
||||
for (VariableCost variableCost : this.costs.getVariableCosts()) {
|
||||
for (VariableCost variableCost : this.getCosts().getVariableCosts()) {
|
||||
if (!(variableCost instanceof VariableManaCost) && !((Cost) variableCost).isPaid()) {
|
||||
int xValue = variableCost.announceXValue(this, game);
|
||||
Cost fixedCost = variableCost.getFixedCostsFromAnnouncedValue(xValue);
|
||||
if (fixedCost != null) {
|
||||
costs.add(fixedCost);
|
||||
}
|
||||
addCost(fixedCost);
|
||||
// set the xcosts to paid
|
||||
// no x events - rules from Unbound Flourishing:
|
||||
// - Spells with additional costs that include X won't be affected by Unbound Flourishing. X must be in the spell's mana cost.
|
||||
|
|
@ -534,7 +532,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
* life or the corresponding colored mana cost for each of those symbols.
|
||||
*/
|
||||
private void handlePhyrexianManaCosts(Game game, Player controller) {
|
||||
Iterator<ManaCost> costIterator = manaCostsToPay.iterator();
|
||||
Iterator<ManaCost> costIterator = getManaCostsToPay().iterator();
|
||||
while (costIterator.hasNext()) {
|
||||
ManaCost cost = costIterator.next();
|
||||
|
||||
|
|
@ -545,8 +543,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
if (payLifeCost.canPay(this, this, controller.getId(), game)
|
||||
&& controller.chooseUse(Outcome.LoseLife, "Pay 2 life instead of " + cost.getText().replace("/P", "") + '?', this, game)) {
|
||||
costIterator.remove();
|
||||
costs.add(payLifeCost);
|
||||
manaCostsToPay.incrPhyrexianPaid();
|
||||
addCost(payLifeCost);
|
||||
getManaCostsToPay().incrPhyrexianPaid();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -580,7 +578,7 @@ public abstract class AbilityImpl implements Ability {
|
|||
|
||||
// TODO: Handle announcing other variable costs here like: RemoveVariableCountersSourceCost
|
||||
VariableManaCost variableManaCost = null;
|
||||
for (ManaCost cost : manaCostsToPay) {
|
||||
for (ManaCost cost : getManaCostsToPay()) {
|
||||
if (cost instanceof VariableManaCost) {
|
||||
if (variableManaCost == null) {
|
||||
variableManaCost = (VariableManaCost) cost;
|
||||
|
|
@ -625,8 +623,8 @@ public abstract class AbilityImpl implements Ability {
|
|||
manaString.append('{').append(manaSymbol).append('}');
|
||||
}
|
||||
}
|
||||
manaCostsToPay.add(new ManaCostsImpl<>(manaString.toString()));
|
||||
manaCostsToPay.setX(xValue * xValueMultiplier, amountMana);
|
||||
addManaCostsToPay(new ManaCostsImpl<>(manaString.toString()));
|
||||
getManaCostsToPay().setX(xValue * xValueMultiplier, amountMana);
|
||||
}
|
||||
variableManaCost.setPaid();
|
||||
}
|
||||
|
|
@ -788,14 +786,14 @@ public abstract class AbilityImpl implements Ability {
|
|||
public String getRule(boolean all) {
|
||||
StringBuilder sbRule = threadLocalBuilder.get();
|
||||
if (all || this.abilityType != AbilityType.SPELL) { // TODO: Why the override for non-spells?
|
||||
if (!manaCosts.isEmpty()) {
|
||||
sbRule.append(manaCosts.getText());
|
||||
if (!getManaCosts().isEmpty()) {
|
||||
sbRule.append(getManaCosts().getText());
|
||||
}
|
||||
if (!costs.isEmpty()) {
|
||||
if (!getCosts().isEmpty()) {
|
||||
if (sbRule.length() > 0) {
|
||||
sbRule.append(", ");
|
||||
}
|
||||
sbRule.append(costs.getText());
|
||||
sbRule.append(getCosts().getText());
|
||||
}
|
||||
if (sbRule.length() > 0) {
|
||||
sbRule.append(": ");
|
||||
|
|
@ -866,19 +864,46 @@ public abstract class AbilityImpl implements Ability {
|
|||
} else {
|
||||
// as single cost
|
||||
if (cost instanceof ManaCost) {
|
||||
this.addManaCost((ManaCost) cost);
|
||||
addManaCost((ManaCost) cost);
|
||||
} else {
|
||||
this.costs.add(cost);
|
||||
if (costs == null) {
|
||||
costs = new CostsImpl<>();
|
||||
}
|
||||
costs.add(cost);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addManaCost(ManaCost cost) {
|
||||
if (cost != null) {
|
||||
this.manaCosts.add(cost);
|
||||
this.manaCostsToPay.add(cost);
|
||||
public void addManaCostsToPay(ManaCost manaCost) {
|
||||
if (manaCost == null) {
|
||||
return;
|
||||
}
|
||||
if (manaCostsToPay == null) {
|
||||
manaCostsToPay = new ManaCostsImpl<>();
|
||||
}
|
||||
if (manaCost instanceof ManaCosts) {
|
||||
manaCostsToPay.addAll((ManaCosts) manaCost);
|
||||
} else {
|
||||
manaCostsToPay.add(manaCost);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addManaCost(ManaCost manaCost) {
|
||||
if (manaCost == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (manaCosts == null) {
|
||||
manaCosts = new ManaCostsImpl<>();
|
||||
}
|
||||
if (manaCostsToPay == null) {
|
||||
manaCostsToPay = new ManaCostsImpl<>();
|
||||
}
|
||||
|
||||
manaCosts.add(manaCost);
|
||||
manaCostsToPay.add(manaCost);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -193,7 +193,7 @@ public abstract class ActivatedAbilityImpl extends AbilityImpl implements Activa
|
|||
}
|
||||
|
||||
// targets and costs check
|
||||
if (!costs.canPay(this, this, playerId, game)
|
||||
if (!getCosts().canPay(this, this, playerId, game)
|
||||
|| !canChooseTarget(game, playerId)) {
|
||||
return ActivationStatus.getFalse();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ public class LoyaltyAbility extends ActivatedAbilityImpl {
|
|||
|
||||
// cost modification support only 1 cost item
|
||||
int staticCount = 0;
|
||||
for (Cost cost : costs) {
|
||||
for (Cost cost : getCosts()) {
|
||||
if (cost instanceof PayLoyaltyCost) {
|
||||
// static cost
|
||||
PayLoyaltyCost staticCost = (PayLoyaltyCost) cost;
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ public class Modes extends LinkedHashMap<UUID, Mode> {
|
|||
|
||||
public List<UUID> getSelectedModes() {
|
||||
// modes can be selected in any order by user, but execution must be in rule's order
|
||||
List<UUID> res = new ArrayList<>();
|
||||
List<UUID> res = new ArrayList<>(this.size());
|
||||
for (Mode mode : this.values()) {
|
||||
for (UUID selectedId : this.selectedModes) {
|
||||
// selectedModes contains original mode and 2+ selected as duplicates (new modes)
|
||||
|
|
|
|||
|
|
@ -147,7 +147,7 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
}
|
||||
|
||||
// can pay all costs and choose targets
|
||||
if (costs.canPay(this, this, playerId, game)) {
|
||||
if (getCosts().canPay(this, this, playerId, game)) {
|
||||
if (getSpellAbilityType() == SpellAbilityType.SPLIT_FUSED) {
|
||||
SplitCard splitCard = (SplitCard) game.getCard(getSourceId());
|
||||
if (splitCard != null) {
|
||||
|
|
@ -180,12 +180,6 @@ public class SpellAbility extends ActivatedAbilityImpl {
|
|||
return super.getRule(false);
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
getTargets().clearChosen();
|
||||
this.manaCosts.clearPaid();
|
||||
this.costs.clearPaid();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class StriveCostIncreasingEffect extends CostModificationEffectImpl {
|
|||
sb.append(striveCosts.getText());
|
||||
}
|
||||
String finalCost = ManaUtil.condenseManaCostString(sb.toString());
|
||||
abilityToModify.getManaCostsToPay().add(new ManaCostsImpl<>(finalCost));
|
||||
abilityToModify.addManaCostsToPay(new ManaCostsImpl<>(finalCost));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -146,19 +146,19 @@ public class AlternativeCostSourceAbility extends StaticAbility implements Alter
|
|||
CardUtil.reduceCost((SpellAbility) ability, ability.getManaCosts());
|
||||
|
||||
} else {
|
||||
ability.getManaCostsToPay().clear();
|
||||
ability.clearManaCostsToPay();
|
||||
}
|
||||
if (!onlyMana) {
|
||||
ability.getCosts().clear();
|
||||
ability.clearCosts();
|
||||
}
|
||||
for (AlternativeCost alternateCost : alternativeCostsToCheck) {
|
||||
alternateCost.activate();
|
||||
for (Iterator it = ((Costs) alternateCost).iterator(); it.hasNext(); ) {
|
||||
Cost costDetailed = (Cost) it.next();
|
||||
if (costDetailed instanceof ManaCost) {
|
||||
ability.getManaCostsToPay().add((ManaCost) costDetailed.copy());
|
||||
ability.addManaCostsToPay((ManaCost) costDetailed.copy());
|
||||
} else if (costDetailed != null) {
|
||||
ability.getCosts().add(costDetailed.copy());
|
||||
ability.addCost(costDetailed.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -67,14 +67,14 @@ public abstract class AlternativeSourceCostsImpl extends StaticAbility implement
|
|||
throw new IllegalArgumentException("source card not found");
|
||||
}
|
||||
}
|
||||
ability.getManaCostsToPay().clear();
|
||||
ability.getCosts().clear();
|
||||
ability.clearManaCostsToPay();
|
||||
ability.clearCosts();
|
||||
for (Iterator<Cost> it = ((Costs<Cost>) alternativeCost).iterator(); it.hasNext(); ) {
|
||||
Cost cost = it.next();
|
||||
if (cost instanceof ManaCost) {
|
||||
ability.getManaCostsToPay().add((ManaCost) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCost) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ public class CostsImpl<T extends Cost> extends ArrayList<T> implements Costs<T>
|
|||
}
|
||||
|
||||
public CostsImpl(final CostsImpl<T> costs) {
|
||||
this.ensureCapacity(costs.size());
|
||||
for (Cost cost : costs) {
|
||||
this.add((T) cost.copy());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ public class ExileFromHandCost extends CostImpl {
|
|||
// TODO: wtf, look at setXFromCMC usage -- it used in cards with alternative costs, not additional... need to fix?
|
||||
vmc.setAmount(cmc, cmc, false);
|
||||
vmc.setPaid();
|
||||
ability.getManaCostsToPay().add(vmc);
|
||||
ability.addManaCostsToPay(vmc);
|
||||
}
|
||||
}
|
||||
return paid;
|
||||
|
|
|
|||
|
|
@ -17,16 +17,15 @@ import java.util.List;
|
|||
*/
|
||||
public class ConditionalManaEffect extends ManaEffect {
|
||||
|
||||
private BasicManaEffect effect;
|
||||
private BasicManaEffect otherwiseEffect;
|
||||
private Condition condition;
|
||||
|
||||
public ConditionalManaEffect(BasicManaEffect effect, Condition condition, String text) {
|
||||
this(effect, null, condition, text);
|
||||
}
|
||||
private final BasicManaEffect effect;
|
||||
private final BasicManaEffect otherwiseEffect;
|
||||
private final Condition condition;
|
||||
|
||||
public ConditionalManaEffect(BasicManaEffect effect, BasicManaEffect otherwiseEffect, Condition condition, String text) {
|
||||
super();
|
||||
if (effect == null || otherwiseEffect == null) {
|
||||
throw new IllegalArgumentException("Wrong code usage: mana effect must not be null");
|
||||
}
|
||||
this.effect = effect;
|
||||
this.otherwiseEffect = otherwiseEffect;
|
||||
this.condition = condition;
|
||||
|
|
@ -36,9 +35,7 @@ public class ConditionalManaEffect extends ManaEffect {
|
|||
public ConditionalManaEffect(ConditionalManaEffect effect) {
|
||||
super(effect);
|
||||
this.effect = effect.effect.copy();
|
||||
if (effect.otherwiseEffect != null) {
|
||||
this.otherwiseEffect = effect.otherwiseEffect.copy();
|
||||
}
|
||||
this.otherwiseEffect = effect.otherwiseEffect.copy();
|
||||
this.condition = effect.condition;
|
||||
}
|
||||
|
||||
|
|
@ -67,9 +64,9 @@ public class ConditionalManaEffect extends ManaEffect {
|
|||
return mana;
|
||||
}
|
||||
if (condition.apply(game, source)) {
|
||||
mana = effect.getManaTemplate().copy();
|
||||
} else if (otherwiseEffect != null) {
|
||||
mana = otherwiseEffect.getManaTemplate().copy();
|
||||
mana = effect.getManaTemplate(); // getManaTemplate returns a copy already
|
||||
} else {
|
||||
mana = otherwiseEffect.getManaTemplate(); // getManaTemplate returns a copy already
|
||||
}
|
||||
if (mana.getAny() > 0) {
|
||||
int amount = mana.getAny();
|
||||
|
|
|
|||
|
|
@ -71,9 +71,6 @@ public interface ContinuousEffect extends Effect {
|
|||
|
||||
boolean isYourNextUpkeepStep(Game game);
|
||||
|
||||
@Override
|
||||
void newId();
|
||||
|
||||
@Override
|
||||
ContinuousEffect copy();
|
||||
|
||||
|
|
|
|||
|
|
@ -129,13 +129,6 @@ public abstract class ContinuousEffectImpl extends EffectImpl implements Continu
|
|||
this.order = order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newId() {
|
||||
if (!(this instanceof MageSingleton)) {
|
||||
this.id = UUID.randomUUID();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasLayer(Layer layer) {
|
||||
return this.layer == layer;
|
||||
|
|
|
|||
|
|
@ -12,12 +12,11 @@ import mage.game.Game;
|
|||
|
||||
public class BasicManaEffect extends ManaEffect {
|
||||
|
||||
protected Mana manaTemplate;
|
||||
private final Mana manaTemplate; // This field must not become directly accessible outside this class
|
||||
private final DynamicValue netAmount;
|
||||
|
||||
public BasicManaEffect(Mana mana) {
|
||||
this(mana, null);
|
||||
this.manaTemplate = mana;
|
||||
}
|
||||
|
||||
public BasicManaEffect(Mana mana, DynamicValue netAmount) {
|
||||
|
|
@ -40,9 +39,8 @@ public class BasicManaEffect extends ManaEffect {
|
|||
|
||||
protected BasicManaEffect(final BasicManaEffect effect) {
|
||||
super(effect);
|
||||
this.manaTemplate = effect.manaTemplate.copy();
|
||||
this.manaTemplate = effect.manaTemplate; // Not copying for performance reasons. Never modified within the class.
|
||||
this.netAmount = effect.netAmount;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -88,7 +86,7 @@ public class BasicManaEffect extends ManaEffect {
|
|||
}
|
||||
|
||||
public Mana getManaTemplate() {
|
||||
return manaTemplate;
|
||||
return manaTemplate.copy(); // Copy is needed here to prevent unintentional modification
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -43,8 +43,8 @@ public class AwakenAbility extends SpellAbility {
|
|||
zone = Zone.HAND;
|
||||
spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
||||
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(new ManaCostsImpl<>(awakenCosts));
|
||||
|
||||
this.addTarget(new TargetControlledPermanent(new FilterControlledLandPermanent(filterMessage)));
|
||||
|
|
|
|||
|
|
@ -58,15 +58,15 @@ public class BlitzAbility extends SpellAbility {
|
|||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder("Blitz");
|
||||
if (costs.isEmpty()) {
|
||||
if (getCosts().isEmpty()) {
|
||||
sb.append(' ');
|
||||
} else {
|
||||
sb.append("—");
|
||||
}
|
||||
sb.append(manaCosts.getText());
|
||||
if (!costs.isEmpty()) {
|
||||
sb.append(getManaCosts().getText());
|
||||
if (!getCosts().isEmpty()) {
|
||||
sb.append(", ");
|
||||
sb.append(costs.getText());
|
||||
sb.append(getCosts().getText());
|
||||
sb.append('.');
|
||||
}
|
||||
sb.append(" <i>(If you cast this spell for its blitz cost, it gains haste ");
|
||||
|
|
|
|||
|
|
@ -144,9 +144,9 @@ public class BuybackAbility extends StaticAbility implements OptionalAdditionalS
|
|||
for (Iterator it = ((Costs) buybackCost).iterator(); it.hasNext(); ) {
|
||||
Cost cost = (Cost) it.next();
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCostsImpl) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ public class CasualtyAbility extends StaticAbility implements OptionalAdditional
|
|||
|
||||
additionalCost.activate();
|
||||
for (Cost cost : ((Costs<Cost>) additionalCost)) {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
game.fireReflexiveTriggeredAbility(new ReflexiveTriggeredAbility(
|
||||
new CopySourceSpellEffect(), false, "when you do, copy this spell"
|
||||
|
|
|
|||
|
|
@ -133,9 +133,9 @@ public class ConspireAbility extends StaticAbility implements OptionalAdditional
|
|||
ability.getAllEffects().setValue("ConspireActivation" + conspireId + addedById, true);
|
||||
for (Cost cost : (Costs<Cost>) conspireCost) {
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl<?>) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCostsImpl<?>) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ public class DisturbAbility extends SpellAbility {
|
|||
this.setSpellAbilityCastMode(SpellAbilityCastMode.DISTURB);
|
||||
|
||||
this.manaCost = manaCost;
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(new ManaCostsImpl<>(manaCost));
|
||||
this.addSubAbility(new TransformAbility());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public class EchoAbility extends TriggeredAbilityImpl {
|
|||
super(Zone.BATTLEFIELD, new EchoEffect(amount), false);
|
||||
this.amount = amount;
|
||||
this.echoPaid = false;
|
||||
this.echoCosts.add(costs);
|
||||
this.echoCosts.add(getCosts());
|
||||
this.lastController = null;
|
||||
this.manaEcho = true;
|
||||
this.rule = rule;
|
||||
|
|
|
|||
|
|
@ -34,8 +34,8 @@ public class EmergeAbility extends SpellAbility {
|
|||
zone = Zone.HAND;
|
||||
spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
||||
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(emergeCost.copy());
|
||||
|
||||
this.setRuleAtTheTop(true);
|
||||
|
|
|
|||
|
|
@ -92,9 +92,9 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
|||
for (Iterator it = ((Costs) entwineCost).iterator(); it.hasNext(); ) {
|
||||
Cost cost = (Cost) it.next();
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCostsImpl) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
activateEntwine(game, ability);
|
||||
|
|
|
|||
|
|
@ -63,19 +63,19 @@ public class EquipAbility extends ActivatedAbilityImpl {
|
|||
@Override
|
||||
public String getRule() {
|
||||
String targetText = getTargets().get(0) != null ? getTargets().get(0).getFilter().getMessage() : "creature";
|
||||
String reminderText = " <i>(" + manaCosts.getText() + ": Attach to target " + targetText + ". Equip only as a sorcery.)</i>";
|
||||
String reminderText = " <i>(" + getManaCosts().getText() + ": Attach to target " + targetText + ". Equip only as a sorcery.)</i>";
|
||||
|
||||
StringBuilder sb = new StringBuilder("Equip");
|
||||
if (!targetText.equals("creature you control")) {
|
||||
sb.append(' ').append(targetText);
|
||||
}
|
||||
String costText = costs.getText();
|
||||
String costText = getCosts().getText();
|
||||
if (costText != null && !costText.isEmpty()) {
|
||||
sb.append("—").append(costText).append('.');
|
||||
} else {
|
||||
sb.append(' ');
|
||||
}
|
||||
sb.append(manaCosts.getText());
|
||||
sb.append(getManaCosts().getText());
|
||||
if (costReduceText != null && !costReduceText.isEmpty()) {
|
||||
sb.append(". ");
|
||||
sb.append(costReduceText);
|
||||
|
|
|
|||
|
|
@ -38,8 +38,8 @@ public class EscapeAbility extends SpellAbility {
|
|||
|
||||
this.manaCost = manaCost;
|
||||
this.exileCount = exileCount;
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(new ManaCostsImpl<>(manaCost));
|
||||
this.addCost(new ExileFromGraveCost(new TargetCardInYourGraveyard(exileCount, filter), "")); // hide additional cost text from rules
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,9 +113,9 @@ public class FlashbackAbility extends SpellAbility {
|
|||
return null;
|
||||
}
|
||||
spellAbilityCopy.setId(this.getId());
|
||||
spellAbilityCopy.getManaCosts().clear();
|
||||
spellAbilityCopy.getManaCostsToPay().clear();
|
||||
spellAbilityCopy.getCosts().addAll(this.getCosts().copy());
|
||||
spellAbilityCopy.clearManaCosts();
|
||||
spellAbilityCopy.clearManaCostsToPay();
|
||||
spellAbilityCopy.addCost(this.getCosts().copy());
|
||||
spellAbilityCopy.addCost(this.getManaCosts().copy());
|
||||
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
|
||||
spellAbilityToResolve = spellAbilityCopy;
|
||||
|
|
@ -148,19 +148,19 @@ public class FlashbackAbility extends SpellAbility {
|
|||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sbRule = new StringBuilder("Flashback");
|
||||
if (!costs.isEmpty()) {
|
||||
if (!getCosts().isEmpty()) {
|
||||
sbRule.append("—");
|
||||
} else {
|
||||
sbRule.append(' ');
|
||||
}
|
||||
if (!manaCosts.isEmpty()) {
|
||||
sbRule.append(manaCosts.getText());
|
||||
if (!getManaCosts().isEmpty()) {
|
||||
sbRule.append(getManaCosts().getText());
|
||||
}
|
||||
if (!costs.isEmpty()) {
|
||||
if (!manaCosts.isEmpty()) {
|
||||
if (!getCosts().isEmpty()) {
|
||||
if (!getManaCosts().isEmpty()) {
|
||||
sbRule.append(", ");
|
||||
}
|
||||
sbRule.append(costs.getText());
|
||||
sbRule.append(getCosts().getText());
|
||||
sbRule.append('.');
|
||||
}
|
||||
if (abilityName != null) {
|
||||
|
|
|
|||
|
|
@ -404,9 +404,9 @@ public class ForetellAbility extends SpecialAction {
|
|||
return null;
|
||||
}
|
||||
spellAbilityCopy.setId(this.getId());
|
||||
spellAbilityCopy.getManaCosts().clear();
|
||||
spellAbilityCopy.getManaCostsToPay().clear();
|
||||
spellAbilityCopy.getCosts().addAll(this.getCosts().copy());
|
||||
spellAbilityCopy.clearManaCosts();
|
||||
spellAbilityCopy.clearManaCostsToPay();
|
||||
spellAbilityCopy.addCost(this.getCosts().copy());
|
||||
spellAbilityCopy.addCost(this.getManaCosts().copy());
|
||||
spellAbilityCopy.setSpellAbilityCastMode(this.getSpellAbilityCastMode());
|
||||
spellAbilityToResolve = spellAbilityCopy;
|
||||
|
|
@ -431,19 +431,19 @@ public class ForetellAbility extends SpecialAction {
|
|||
@Override
|
||||
public String getRule(boolean all) {
|
||||
StringBuilder sbRule = new StringBuilder("Foretell");
|
||||
if (!costs.isEmpty()) {
|
||||
if (!getCosts().isEmpty()) {
|
||||
sbRule.append("—");
|
||||
} else {
|
||||
sbRule.append(' ');
|
||||
}
|
||||
if (!manaCosts.isEmpty()) {
|
||||
sbRule.append(manaCosts.getText());
|
||||
if (!getManaCosts().isEmpty()) {
|
||||
sbRule.append(getManaCosts().getText());
|
||||
}
|
||||
if (!costs.isEmpty()) {
|
||||
if (!manaCosts.isEmpty()) {
|
||||
if (!getCosts().isEmpty()) {
|
||||
if (!getManaCosts().isEmpty()) {
|
||||
sbRule.append(", ");
|
||||
}
|
||||
sbRule.append(costs.getText());
|
||||
sbRule.append(getCosts().getText());
|
||||
sbRule.append('.');
|
||||
}
|
||||
if (abilityName != null) {
|
||||
|
|
|
|||
|
|
@ -44,6 +44,6 @@ public class FortifyAbility extends ActivatedAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return "Fortify " + costs.getText() + manaCosts.getText() + " (" + manaCosts.getText() + ": <i>Attach to target land you control. Fortify only as a sorcery.)</i>";
|
||||
return "Fortify " + getCosts().getText() + getManaCosts().getText() + " (" + getManaCosts().getText() + ": <i>Attach to target land you control. Fortify only as a sorcery.)</i>";
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -282,9 +282,9 @@ public class KickerAbility extends StaticAbility implements OptionalAdditionalSo
|
|||
// can contain multiple costs from multikicker ability
|
||||
// must be additional cost type
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCostsImpl) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ public class LevelUpAbility extends ActivatedAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
return new StringBuilder("Level up ").append(manaCostsToPay.getText())
|
||||
.append(" <i>(").append(manaCostsToPay.getText()).append(": Put a level counter on this. Level up only as a sorcery.)</i>").toString();
|
||||
return new StringBuilder("Level up ").append(getManaCostsToPay().getText())
|
||||
.append(" <i>(").append(getManaCostsToPay().getText()).append(": Put a level counter on this. Level up only as a sorcery.)</i>").toString();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class MadnessCastEffect extends OneShotEffect {
|
|||
ManaCosts<ManaCost> costRef = castByMadness.getManaCostsToPay();
|
||||
castByMadness.setSpellAbilityType(SpellAbilityType.BASE_ALTERNATE);
|
||||
castByMadness.setSpellAbilityCastMode(SpellAbilityCastMode.MADNESS);
|
||||
castByMadness.getCosts().clear();
|
||||
castByMadness.clearCosts();
|
||||
castByMadness.addCost(new PayLifeCost(this.lifeCost));
|
||||
costRef.clear();
|
||||
costRef.add(madnessCost);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ public class MeditateAbility extends ActivatedAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder("Meditate ").append(manaCosts.getText());
|
||||
StringBuilder sb = new StringBuilder("Meditate ").append(getManaCosts().getText());
|
||||
sb.append(" <i>(Return this creature to its owner's hand. Meditate only as a sorcery.)</i>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,8 +28,8 @@ public class MoreThanMeetsTheEyeAbility extends SpellAbility {
|
|||
this.setSpellAbilityCastMode(SpellAbilityCastMode.MORE_THAN_MEETS_THE_EYE);
|
||||
|
||||
this.manaCost = manaCost;
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(new ManaCostsImpl<>(manaCost));
|
||||
this.addSubAbility(new TransformAbility());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ public class OutlastAbility extends ActivatedAbilityImpl {
|
|||
|
||||
@Override
|
||||
public String getRule() {
|
||||
StringBuilder sb = new StringBuilder("Outlast ").append(manaCosts.getText());
|
||||
StringBuilder sb = new StringBuilder("Outlast ").append(getManaCosts().getText());
|
||||
sb.append(" <i>(").append(getManaCosts().getText()).append(", ").append(getCosts().getText()).append(": Put a +1/+1 counter on this creature. Outlast only as a sorcery.)</i>");
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -106,9 +106,9 @@ public class ReplicateAbility extends StaticAbility implements OptionalAdditiona
|
|||
for (Iterator it = ((Costs) additionalCost).iterator(); it.hasNext(); ) {
|
||||
Cost cost = (Cost) it.next();
|
||||
if (cost instanceof ManaCostsImpl) {
|
||||
ability.getManaCostsToPay().add((ManaCostsImpl) cost.copy());
|
||||
ability.addManaCostsToPay((ManaCostsImpl) cost.copy());
|
||||
} else {
|
||||
ability.getCosts().add(cost.copy());
|
||||
ability.addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ public class SpectacleAbility extends SpellAbility {
|
|||
zone = Zone.HAND;
|
||||
spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
||||
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(spectacleCosts.copy());
|
||||
|
||||
this.setRuleAtTheTop(true);
|
||||
|
|
|
|||
|
|
@ -174,9 +174,9 @@ class SpliceCardEffectImpl extends ContinuousEffectImpl implements SpliceCardEff
|
|||
for (Iterator it = ((SpliceAbility) source).getSpliceCosts().iterator(); it.hasNext();) {
|
||||
Cost cost = (Cost) it.next();
|
||||
if (cost instanceof ManaCost) {
|
||||
spell.getSpellAbility().getManaCostsToPay().add((ManaCost) cost.copy());
|
||||
spell.getSpellAbility().addManaCostsToPay((ManaCost) cost.copy());
|
||||
} else {
|
||||
spell.getSpellAbility().getCosts().add(cost.copy());
|
||||
spell.getSpellAbility().addCost(cost.copy());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,8 @@ public class SurgeAbility extends SpellAbility {
|
|||
zone = Zone.HAND;
|
||||
spellAbilityType = SpellAbilityType.BASE_ALTERNATE;
|
||||
|
||||
this.getManaCosts().clear();
|
||||
this.getManaCostsToPay().clear();
|
||||
this.clearManaCosts();
|
||||
this.clearManaCostsToPay();
|
||||
this.addManaCost(new ManaCostsImpl<>(surgeCosts));
|
||||
|
||||
this.setRuleAtTheTop(true);
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class AdventureCardSpellAbility extends SpellAbility {
|
|||
StringBuilder sbRule = new StringBuilder();
|
||||
sbRule.append(this.nameFull);
|
||||
sbRule.append(" ");
|
||||
sbRule.append(manaCosts.getText());
|
||||
sbRule.append(getManaCosts().getText());
|
||||
sbRule.append(" — ");
|
||||
Modes modes = this.getModes();
|
||||
if (modes.size() <= 1) {
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ public interface Card extends MageObject {
|
|||
CommanderPlaysCountWatcher watcher = game.getState().getWatcher(CommanderPlaysCountWatcher.class);
|
||||
int castCount = watcher.getPlaysCount(getMainCard().getId());
|
||||
if (castCount > 0) {
|
||||
abilityToModify.getManaCostsToPay().add(ManaUtil.createManaCost(2 * castCount, false));
|
||||
abilityToModify.addManaCostsToPay(ManaUtil.createManaCost(2 * castCount, false));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,7 +394,13 @@ public class StackAbility extends StackObjectImpl implements Ability {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void addManaCost(ManaCost cost) {
|
||||
public void addManaCost(ManaCost manaCost) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addManaCostsToPay(ManaCost manaCost) {
|
||||
// Do nothing
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -1194,15 +1194,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
if (alternateCosts == null) {
|
||||
noMana = true;
|
||||
} else {
|
||||
spellAbility.getManaCosts().clear();
|
||||
spellAbility.getManaCostsToPay().clear();
|
||||
spellAbility.getManaCosts().add(alternateCosts.copy());
|
||||
spellAbility.getManaCostsToPay().add(alternateCosts.copy());
|
||||
}
|
||||
spellAbility.getCosts().clear();
|
||||
if (costs != null) {
|
||||
spellAbility.getCosts().addAll(costs);
|
||||
spellAbility.clearManaCosts();
|
||||
spellAbility.clearManaCostsToPay();
|
||||
spellAbility.addManaCost(alternateCosts.copy());
|
||||
}
|
||||
spellAbility.clearCosts();
|
||||
spellAbility.addCost(costs);
|
||||
}
|
||||
clearCastSourceIdManaCosts(); // TODO: test multiple alternative cost for different cards as same time
|
||||
|
||||
|
|
@ -3620,8 +3617,8 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
// alternative cost reduce
|
||||
copyAbility = ability.copy();
|
||||
copyAbility.getManaCostsToPay().clear();
|
||||
copyAbility.getManaCostsToPay().addAll(manaCosts.copy());
|
||||
copyAbility.clearManaCostsToPay();
|
||||
copyAbility.addManaCostsToPay(manaCosts.copy());
|
||||
copyAbility.adjustCosts(game);
|
||||
game.getContinuousEffects().costModification(copyAbility, game);
|
||||
|
||||
|
|
@ -3686,12 +3683,12 @@ public abstract class PlayerImpl implements Player, Serializable {
|
|||
|
||||
// alternative cost reduce
|
||||
copyAbility = ability.copy();
|
||||
copyAbility.getManaCostsToPay().clear();
|
||||
copyAbility.clearManaCostsToPay();
|
||||
// TODO: IDE warning:
|
||||
// Unchecked assignment: 'mage.abilities.costs.mana.ManaCosts' to
|
||||
// 'java.util.Collection<? extends mage.abilities.costs.mana.ManaCost>'.
|
||||
// Reason: 'manaCosts' has raw type, so result of copy is erased
|
||||
copyAbility.getManaCostsToPay().addAll(manaCosts.copy());
|
||||
copyAbility.addManaCostsToPay(manaCosts.copy());
|
||||
copyAbility.adjustCosts(game);
|
||||
game.getContinuousEffects().costModification(copyAbility, game);
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ import java.util.Map;
|
|||
public abstract class TargetPointerImpl implements TargetPointer {
|
||||
|
||||
// Store custom data here. Use it to keep unique values for ability instances on stack (example: Gruul Ragebeast)
|
||||
Map<String, String> data = new HashMap<>();
|
||||
private Map<String, String> data;
|
||||
|
||||
public TargetPointerImpl() {
|
||||
super();
|
||||
|
|
@ -17,17 +17,26 @@ public abstract class TargetPointerImpl implements TargetPointer {
|
|||
|
||||
protected TargetPointerImpl(final TargetPointerImpl targetPointer) {
|
||||
super();
|
||||
this.data.putAll(targetPointer.data);
|
||||
if (targetPointer.data != null) {
|
||||
this.data = new HashMap<>();
|
||||
this.data.putAll(targetPointer.data);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getData(String key) {
|
||||
return this.data.getOrDefault(key, "");
|
||||
if (data == null) {
|
||||
return "";
|
||||
}
|
||||
return data.getOrDefault(key, "");
|
||||
}
|
||||
|
||||
@Override
|
||||
public TargetPointer withData(String key, String value) {
|
||||
this.data.put(key, value);
|
||||
if (data == null) {
|
||||
data = new HashMap<>();
|
||||
}
|
||||
data.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -141,8 +141,8 @@ public final class CardUtil {
|
|||
*/
|
||||
private static void adjustAbilityCost(Ability ability, int reduceCount) {
|
||||
ManaCosts<ManaCost> adjustedCost = adjustCost(ability.getManaCostsToPay(), reduceCount);
|
||||
ability.getManaCostsToPay().clear();
|
||||
ability.getManaCostsToPay().addAll(adjustedCost);
|
||||
ability.clearManaCostsToPay();
|
||||
ability.addManaCostsToPay(adjustedCost);
|
||||
}
|
||||
|
||||
private static ManaCosts<ManaCost> adjustCost(ManaCosts<ManaCost> manaCosts, int reduceCount) {
|
||||
|
|
@ -304,8 +304,8 @@ public final class CardUtil {
|
|||
increasedCost.add(manaCost.copy());
|
||||
}
|
||||
|
||||
spellAbility.getManaCostsToPay().clear();
|
||||
spellAbility.getManaCostsToPay().addAll(increasedCost);
|
||||
spellAbility.clearManaCostsToPay();
|
||||
spellAbility.addManaCostsToPay(increasedCost);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -468,8 +468,8 @@ public final class CardUtil {
|
|||
adjustedCost.add(new GenericManaCost(0)); // neede to check if cost was reduced to 0
|
||||
}
|
||||
adjustedCost.setSourceFilter(previousCost.getSourceFilter()); // keep mana source restrictions
|
||||
spellAbility.getManaCostsToPay().clear();
|
||||
spellAbility.getManaCostsToPay().addAll(adjustedCost);
|
||||
spellAbility.clearManaCostsToPay();
|
||||
spellAbility.addManaCostsToPay(adjustedCost);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue