mirror of
https://github.com/magefree/mage.git
synced 2025-12-23 12:02:01 -08:00
Convert Bargain/Entwine/Squad to costs tag system
This commit is contained in:
parent
ad873863fa
commit
1e76b59f4e
4 changed files with 18 additions and 128 deletions
|
|
@ -1,11 +1,10 @@
|
||||||
package mage.abilities.condition.common;
|
package mage.abilities.condition.common;
|
||||||
|
|
||||||
import mage.MageObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.condition.Condition;
|
import mage.abilities.condition.Condition;
|
||||||
import mage.abilities.keyword.BargainAbility;
|
import mage.abilities.keyword.BargainAbility;
|
||||||
import mage.cards.Card;
|
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the spell was cast with the alternate Bargain cost
|
* Checks if the spell was cast with the alternate Bargain cost
|
||||||
|
|
@ -18,16 +17,7 @@ public enum BargainedCondition implements Condition {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
// TODO: replace by Tag Cost Tracking.
|
return CardUtil.checkSourceCostsTagExists(game, source, BargainAbility.BARGAIN_ACTIVATION_VALUE_KEY);
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
|
||||||
if (sourceObject instanceof Card) {
|
|
||||||
for (Ability ability : ((Card) sourceObject).getAbilities(game)) {
|
|
||||||
if (ability instanceof BargainAbility) {
|
|
||||||
return ((BargainAbility) ability).wasBargained(game, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
|
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.StaticAbility;
|
import mage.abilities.StaticAbility;
|
||||||
|
|
@ -16,7 +15,6 @@ import mage.filter.predicate.Predicates;
|
||||||
import mage.filter.predicate.permanent.TokenPredicate;
|
import mage.filter.predicate.permanent.TokenPredicate;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
import mage.util.CardUtil;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Written before ruling was clarified. Feel free to put the ruling once it gets there.
|
* Written before ruling was clarified. Feel free to put the ruling once it gets there.
|
||||||
|
|
@ -37,7 +35,7 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
private static final String reminderText = "You may sacrifice an artifact, enchantment, or token as you cast this spell.";
|
private static final String reminderText = "You may sacrifice an artifact, enchantment, or token as you cast this spell.";
|
||||||
private final String rule;
|
private final String rule;
|
||||||
|
|
||||||
private String activationKey; // TODO: replace by Tag Cost Tracking.
|
public static final String BARGAIN_ACTIVATION_VALUE_KEY = "bargainActivation";
|
||||||
|
|
||||||
protected OptionalAdditionalCost additionalCost;
|
protected OptionalAdditionalCost additionalCost;
|
||||||
|
|
||||||
|
|
@ -61,14 +59,12 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
this.rule = additionalCost.getName() + ' ' + additionalCost.getReminderText();
|
this.rule = additionalCost.getName() + ' ' + additionalCost.getReminderText();
|
||||||
this.setRuleAtTheTop(true);
|
this.setRuleAtTheTop(true);
|
||||||
this.addHint(BargainCostWasPaidHint.instance);
|
this.addHint(BargainCostWasPaidHint.instance);
|
||||||
this.activationKey = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private BargainAbility(final BargainAbility ability) {
|
private BargainAbility(final BargainAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.rule = ability.rule;
|
this.rule = ability.rule;
|
||||||
this.additionalCost = ability.additionalCost.copy();
|
this.additionalCost = ability.additionalCost.copy();
|
||||||
this.activationKey = ability.activationKey;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -80,7 +76,6 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
if (additionalCost != null) {
|
if (additionalCost != null) {
|
||||||
additionalCost.reset();
|
additionalCost.reset();
|
||||||
}
|
}
|
||||||
this.activationKey = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -104,7 +99,7 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
for (Cost cost : ((Costs<Cost>) additionalCost)) {
|
for (Cost cost : ((Costs<Cost>) additionalCost)) {
|
||||||
ability.getCosts().add(cost.copy());
|
ability.getCosts().add(cost.copy());
|
||||||
}
|
}
|
||||||
this.activationKey = getActivationKey(ability, game);
|
ability.setCostsTag(BARGAIN_ACTIVATION_VALUE_KEY, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -112,40 +107,6 @@ public class BargainAbility extends StaticAbility implements OptionalAdditionalS
|
||||||
return additionalCost.getCastSuffixMessage(0);
|
return additionalCost.getCastSuffixMessage(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean wasBargained(Game game, Ability source) {
|
|
||||||
return activationKey != null && getActivationKey(source, game).equalsIgnoreCase(activationKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* TODO: remove with Tag Cost Tracking.
|
|
||||||
* Return activation zcc key for searching spell's settings in source object
|
|
||||||
*
|
|
||||||
* @param source
|
|
||||||
* @param game
|
|
||||||
*/
|
|
||||||
public static String getActivationKey(Ability source, Game game) {
|
|
||||||
// Bargain activates in STACK zone so all zcc must be from "stack moment"
|
|
||||||
// Use cases:
|
|
||||||
// * resolving spell have same zcc (example: check kicker status in sorcery/instant);
|
|
||||||
// * copied spell have same zcc as source spell (see Spell.copySpell and zcc sync);
|
|
||||||
// * creature/token from resolved spell have +1 zcc after moved to battlefield (example: check kicker status in ETB triggers/effects);
|
|
||||||
|
|
||||||
// find object info from the source ability (it can be a permanent or a spell on stack, on the moment of trigger/resolve)
|
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
|
||||||
Zone sourceObjectZone = game.getState().getZone(sourceObject.getId());
|
|
||||||
int zcc = CardUtil.getActualSourceObjectZoneChangeCounter(game, source);
|
|
||||||
|
|
||||||
// find "stack moment" zcc:
|
|
||||||
// * permanent cards enters from STACK to BATTLEFIELD (+1 zcc)
|
|
||||||
// * permanent tokens enters from OUTSIDE to BATTLEFIELD (+1 zcc, see prepare code in TokenImpl.putOntoBattlefieldHelper)
|
|
||||||
// * spells and copied spells resolves on STACK (zcc not changes)
|
|
||||||
if (sourceObjectZone != Zone.STACK) {
|
|
||||||
--zcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
return zcc + "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return rule;
|
return rule;
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,9 @@ import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
import mage.game.Game;
|
import mage.game.Game;
|
||||||
import mage.players.Player;
|
import mage.players.Player;
|
||||||
|
import mage.util.CardUtil;
|
||||||
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 702.40. Entwine
|
* 702.40. Entwine
|
||||||
|
|
@ -32,9 +31,9 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
|
|
||||||
private static final String keywordText = "Entwine";
|
private static final String keywordText = "Entwine";
|
||||||
protected static final String reminderText = "You may {cost} in addition to any other costs to use all modes.";
|
protected static final String reminderText = "You may {cost} in addition to any other costs to use all modes.";
|
||||||
|
protected static final String ENTWINE_ACTIVATION_VALUE_KEY = "entwineActivation";
|
||||||
|
|
||||||
protected OptionalAdditionalCost entwineCost;
|
protected OptionalAdditionalCost entwineCost;
|
||||||
protected Set<String> activations = new HashSet<>(); // same logic as KickerAbility: activations per zoneChangeCounter
|
|
||||||
|
|
||||||
public EntwineAbility(String manaString) {
|
public EntwineAbility(String manaString) {
|
||||||
super(Zone.STACK, null);
|
super(Zone.STACK, null);
|
||||||
|
|
@ -62,7 +61,6 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
if (ability.entwineCost != null) {
|
if (ability.entwineCost != null) {
|
||||||
this.entwineCost = ability.entwineCost.copy();
|
this.entwineCost = ability.entwineCost.copy();
|
||||||
}
|
}
|
||||||
this.activations.addAll(ability.activations);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -97,7 +95,7 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
ability.addCost(cost.copy());
|
ability.addCost(cost.copy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
activateEntwine(game, ability);
|
ability.setCostsTag(ENTWINE_ACTIVATION_VALUE_KEY, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -135,23 +133,9 @@ public class EntwineAbility extends StaticAbility implements OptionalAdditionalM
|
||||||
if (entwineCost != null) {
|
if (entwineCost != null) {
|
||||||
entwineCost.reset();
|
entwineCost.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
String key = getActivationKey(source, game);
|
|
||||||
this.activations.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void activateEntwine(Game game, Ability source) {
|
|
||||||
String key = getActivationKey(source, game);
|
|
||||||
this.activations.add(key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean costWasActivated(Ability ability, Game game) {
|
public boolean costWasActivated(Ability ability, Game game) {
|
||||||
String key = getActivationKey(ability, game);
|
return CardUtil.checkSourceCostsTagExists(game, ability, ENTWINE_ACTIVATION_VALUE_KEY);
|
||||||
return this.activations.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getActivationKey(Ability source, Game game) {
|
|
||||||
// same logic as KickerAbility
|
|
||||||
return KickerAbility.getActivationKey(source, game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
package mage.abilities.keyword;
|
package mage.abilities.keyword;
|
||||||
|
|
||||||
import mage.MageObject;
|
|
||||||
import mage.abilities.Ability;
|
import mage.abilities.Ability;
|
||||||
import mage.abilities.SpellAbility;
|
import mage.abilities.SpellAbility;
|
||||||
import mage.abilities.StaticAbility;
|
import mage.abilities.StaticAbility;
|
||||||
|
|
@ -9,7 +8,6 @@ import mage.abilities.costs.*;
|
||||||
import mage.abilities.costs.mana.GenericManaCost;
|
import mage.abilities.costs.mana.GenericManaCost;
|
||||||
import mage.abilities.costs.mana.ManaCostsImpl;
|
import mage.abilities.costs.mana.ManaCostsImpl;
|
||||||
import mage.abilities.effects.CreateTokenCopySourceEffect;
|
import mage.abilities.effects.CreateTokenCopySourceEffect;
|
||||||
import mage.abilities.effects.Effect;
|
|
||||||
import mage.abilities.effects.OneShotEffect;
|
import mage.abilities.effects.OneShotEffect;
|
||||||
import mage.constants.Outcome;
|
import mage.constants.Outcome;
|
||||||
import mage.constants.Zone;
|
import mage.constants.Zone;
|
||||||
|
|
@ -24,6 +22,7 @@ import mage.util.CardUtil;
|
||||||
public class SquadAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
public class SquadAbility extends StaticAbility implements OptionalAdditionalSourceCosts {
|
||||||
protected OptionalAdditionalCost cost;
|
protected OptionalAdditionalCost cost;
|
||||||
protected static final String SQUAD_KEYWORD = "Squad";
|
protected static final String SQUAD_KEYWORD = "Squad";
|
||||||
|
protected static final String SQUAD_ACTIVATION_VALUE_KEY = "squadActivationCount";
|
||||||
protected static final String SQUAD_REMINDER = "You may pay an additional "
|
protected static final String SQUAD_REMINDER = "You may pay an additional "
|
||||||
+ "{cost} any number of times as you cast this spell.";
|
+ "{cost} any number of times as you cast this spell.";
|
||||||
public SquadAbility() {
|
public SquadAbility() {
|
||||||
|
|
@ -34,7 +33,6 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
super(Zone.STACK, null);
|
super(Zone.STACK, null);
|
||||||
setSquadCost(cost);
|
setSquadCost(cost);
|
||||||
addSubAbility(new SquadTriggerAbility());
|
addSubAbility(new SquadTriggerAbility());
|
||||||
//Note that I get subabilities list's position 0 to modify the zcc/count references
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private SquadAbility(final SquadAbility ability) {
|
private SquadAbility(final SquadAbility ability) {
|
||||||
|
|
@ -47,7 +45,7 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
return new SquadAbility(this);
|
return new SquadAbility(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setSquadCost(Cost cost) {
|
private void setSquadCost(Cost cost) {
|
||||||
OptionalAdditionalCost newCost = new OptionalAdditionalCostImpl(
|
OptionalAdditionalCost newCost = new OptionalAdditionalCostImpl(
|
||||||
SQUAD_KEYWORD, SQUAD_REMINDER, cost);
|
SQUAD_KEYWORD, SQUAD_REMINDER, cost);
|
||||||
newCost.setRepeatable(true);
|
newCost.setRepeatable(true);
|
||||||
|
|
@ -59,28 +57,6 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
cost.reset();
|
cost.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static int get_zcc(Ability source, Game game) {
|
|
||||||
// Squad/Kicker activates in STACK zone so all zcc must be from "stack moment"
|
|
||||||
// Use cases:
|
|
||||||
// * resolving spell have same zcc (example: check kicker status in sorcery/instant);
|
|
||||||
// * copied spell have same zcc as source spell (see Spell.copySpell and zcc sync);
|
|
||||||
// * creature/token from resolved spell have +1 zcc after moved to battlefield (example: check kicker status in ETB triggers/effects);
|
|
||||||
|
|
||||||
// find object info from the source ability (it can be a permanent or a spell on stack, on the moment of trigger/resolve)
|
|
||||||
MageObject sourceObject = source.getSourceObject(game);
|
|
||||||
Zone sourceObjectZone = game.getState().getZone(sourceObject.getId());
|
|
||||||
int zcc = CardUtil.getActualSourceObjectZoneChangeCounter(game, source);
|
|
||||||
|
|
||||||
// find "stack moment" zcc:
|
|
||||||
// * permanent cards enters from STACK to BATTLEFIELD (+1 zcc)
|
|
||||||
// * permanent tokens enters from OUTSIDE to BATTLEFIELD (+1 zcc, see prepare code in TokenImpl.putOntoBattlefieldHelper)
|
|
||||||
// * spells and copied spells resolves on STACK (zcc not changes)
|
|
||||||
if (sourceObjectZone != Zone.STACK) {
|
|
||||||
--zcc;
|
|
||||||
}
|
|
||||||
return zcc;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
public void addOptionalAdditionalCosts(Ability ability, Game game) {
|
||||||
if (!(ability instanceof SpellAbility)) {
|
if (!(ability instanceof SpellAbility)) {
|
||||||
|
|
@ -94,7 +70,7 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
boolean again = true;
|
boolean again = true;
|
||||||
while (player.canRespond() && again) {
|
while (player.canRespond() && again) {
|
||||||
String times = "";
|
String times = "";
|
||||||
int activatedCount = getSquadCount();
|
int activatedCount = cost.getActivateCount();
|
||||||
times = (activatedCount + 1) + (activatedCount == 0 ? " time " : " times ");
|
times = (activatedCount + 1) + (activatedCount == 0 ? " time " : " times ");
|
||||||
// TODO: add AI support to find max number of possible activations (from available mana)
|
// TODO: add AI support to find max number of possible activations (from available mana)
|
||||||
// canPay checks only single mana available, not total mana usage
|
// canPay checks only single mana available, not total mana usage
|
||||||
|
|
@ -111,10 +87,7 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
again = false;
|
again = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
SquadTriggerAbility squadETB = (SquadTriggerAbility)getSubAbilities().get(0);
|
ability.setCostsTag(SQUAD_ACTIVATION_VALUE_KEY,cost.getActivateCount());
|
||||||
squadETB.zcc = get_zcc(ability, game);
|
|
||||||
SquadEffectETB squadEffect = (SquadEffectETB)squadETB.getEffects().get(0);
|
|
||||||
squadEffect.activationCount = cost.getActivateCount();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -131,18 +104,8 @@ public class SquadAbility extends StaticAbility implements OptionalAdditionalSou
|
||||||
cost.getText()+"any number of times. When this creature enters the battlefield, "+
|
cost.getText()+"any number of times. When this creature enters the battlefield, "+
|
||||||
"create that many tokens that are copies of it.)</i>";
|
"create that many tokens that are copies of it.)</i>";
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Number of times squad cost was paid
|
|
||||||
*
|
|
||||||
* @return int activation count
|
|
||||||
*/
|
|
||||||
public int getSquadCount() {
|
|
||||||
return cost.getActivateCount();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility {
|
class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility {
|
||||||
protected Integer zcc;
|
|
||||||
public SquadTriggerAbility() {
|
public SquadTriggerAbility() {
|
||||||
super(new SquadEffectETB());
|
super(new SquadEffectETB());
|
||||||
this.setRuleVisible(false);
|
this.setRuleVisible(false);
|
||||||
|
|
@ -150,7 +113,6 @@ class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility {
|
||||||
|
|
||||||
private SquadTriggerAbility(final SquadTriggerAbility ability) {
|
private SquadTriggerAbility(final SquadTriggerAbility ability) {
|
||||||
super(ability);
|
super(ability);
|
||||||
this.zcc = ability.zcc;
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public SquadTriggerAbility copy() {
|
public SquadTriggerAbility copy() {
|
||||||
|
|
@ -159,21 +121,17 @@ class SquadTriggerAbility extends EntersBattlefieldTriggeredAbility {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkInterveningIfClause(Game game) {
|
public boolean checkInterveningIfClause(Game game) {
|
||||||
if (zcc != null && zcc == SquadAbility.get_zcc(this, game)){
|
int squadCount = (int)CardUtil.getSourceCostsTag(game, this, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY,0);
|
||||||
SquadEffectETB effect = (SquadEffectETB)getEffects().get(0);
|
return (squadCount > 0);
|
||||||
return effect.activationCount > 0;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String getRule() {
|
public String getRule() {
|
||||||
return "Squad <i>(When this creature enters the battlefield, if its squad cost was paid, "
|
return "Squad <i>(When this creature enters the battlefield, if its squad cost was paid, "
|
||||||
+ "create a token that’s a copy of it for each time its squad cost was paid.)</i>";
|
+ "create a token that's a copy of it for each time its squad cost was paid.)</i>";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SquadEffectETB extends OneShotEffect {
|
class SquadEffectETB extends OneShotEffect {
|
||||||
protected Integer activationCount;
|
|
||||||
|
|
||||||
SquadEffectETB() {
|
SquadEffectETB() {
|
||||||
super(Outcome.Benefit);
|
super(Outcome.Benefit);
|
||||||
|
|
@ -181,7 +139,6 @@ class SquadEffectETB extends OneShotEffect {
|
||||||
|
|
||||||
private SquadEffectETB(final SquadEffectETB effect) {
|
private SquadEffectETB(final SquadEffectETB effect) {
|
||||||
super(effect);
|
super(effect);
|
||||||
this.activationCount = effect.activationCount;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -191,10 +148,8 @@ class SquadEffectETB extends OneShotEffect {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Game game, Ability source) {
|
public boolean apply(Game game, Ability source) {
|
||||||
if (activationCount != null) {
|
int squadCount = (int)CardUtil.getSourceCostsTag(game, source, SquadAbility.SQUAD_ACTIVATION_VALUE_KEY,0);
|
||||||
CreateTokenCopySourceEffect effect = new CreateTokenCopySourceEffect(activationCount);
|
CreateTokenCopySourceEffect effect = new CreateTokenCopySourceEffect(squadCount);
|
||||||
return effect.apply(game, source);
|
return effect.apply(game, source);
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue