mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 20:28:00 +00:00
AF:Tokens - split into pieces
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -12488,7 +12488,6 @@ src/main/java/forge/card/abilityfactory/AbilityFactoryReveal.java svneol=native#
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactorySacrifice.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactorySetState.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java -text
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryToken.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/AbilityFactoryZoneAffecting.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/SpellAiLogic.java -text
|
||||
src/main/java/forge/card/abilityfactory/SpellEffect.java -text
|
||||
@@ -12504,6 +12503,7 @@ src/main/java/forge/card/abilityfactory/ai/GainLifeAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/LoseLifeAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/PoisonAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/SetLifeAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
||||
@@ -12516,6 +12516,7 @@ src/main/java/forge/card/abilityfactory/effects/HelperAnimate.java svneol=native
|
||||
src/main/java/forge/card/abilityfactory/effects/LoseLifeEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/PoisonEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/SetLifeEffect.java -text
|
||||
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
||||
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cardfactory/CardFactory.java svneol=native#text/plain
|
||||
src/main/java/forge/card/cardfactory/CardFactoryArtifacts.java -text
|
||||
|
||||
@@ -21,6 +21,8 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.tools.ant.types.resources.Tokens;
|
||||
|
||||
import forge.Card;
|
||||
|
||||
import forge.CardLists;
|
||||
@@ -1237,15 +1239,8 @@ public class AbilityFactory {
|
||||
}
|
||||
|
||||
else if (this.api.equals("Token")) {
|
||||
final AbilityFactoryToken aft = new AbilityFactoryToken(this);
|
||||
|
||||
if (this.isAb) {
|
||||
spellAbility = aft.getAbility();
|
||||
} else if (this.isSp) {
|
||||
spellAbility = aft.getSpell();
|
||||
} else if (this.isDb) {
|
||||
spellAbility = aft.getDrawback();
|
||||
}
|
||||
ai = new TokenAi();
|
||||
se = new TokenEffect();
|
||||
}
|
||||
|
||||
else if (this.api.equals("TwoPiles")) {
|
||||
|
||||
@@ -1,653 +0,0 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card.abilityfactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
import forge.Card;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Token class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public class AbilityFactoryToken extends AbilityFactory {
|
||||
private AbilityFactory abilityFactory = null;
|
||||
|
||||
private final String tokenAmount;
|
||||
private final String tokenName;
|
||||
private final String[] tokenTypes;
|
||||
private String tokenOwner;
|
||||
private final String[] tokenColors;
|
||||
private final String[] tokenKeywords;
|
||||
private final String tokenPower;
|
||||
private final String tokenToughness;
|
||||
private final String tokenImage;
|
||||
private String[] tokenAbilities;
|
||||
private String[] tokenTriggers;
|
||||
private String[] tokenSVars;
|
||||
private String[] tokenStaticAbilities;
|
||||
private boolean tokenTapped;
|
||||
private boolean tokenAttacking;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for AbilityFactory_Token.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
*/
|
||||
public AbilityFactoryToken(final AbilityFactory af) {
|
||||
this.abilityFactory = af;
|
||||
|
||||
final HashMap<String, String> mapParams = af.getMapParams();
|
||||
String image;
|
||||
String[] keywords;
|
||||
|
||||
if (mapParams.containsKey("TokenKeywords")) {
|
||||
// TODO: Change this Split to a semicolon or something else
|
||||
keywords = mapParams.get("TokenKeywords").split("<>");
|
||||
} else {
|
||||
keywords = new String[0];
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("TokenImage")) {
|
||||
image = mapParams.get("TokenImage");
|
||||
} else {
|
||||
image = "";
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("TokenTapped")) {
|
||||
this.tokenTapped = mapParams.get("TokenTapped").equals("True");
|
||||
} else {
|
||||
this.tokenTapped = false;
|
||||
}
|
||||
if (mapParams.containsKey("TokenAttacking")) {
|
||||
this.tokenAttacking = mapParams.get("TokenAttacking").equals("True");
|
||||
} else {
|
||||
this.tokenAttacking = false;
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("TokenAbilities")) {
|
||||
this.tokenAbilities = mapParams.get("TokenAbilities").split(",");
|
||||
} else {
|
||||
this.tokenAbilities = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenTriggers")) {
|
||||
this.tokenTriggers = mapParams.get("TokenTriggers").split(",");
|
||||
} else {
|
||||
this.tokenTriggers = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenSVars")) {
|
||||
this.tokenSVars = mapParams.get("TokenSVars").split(",");
|
||||
} else {
|
||||
this.tokenSVars = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenStaticAbilities")) {
|
||||
this.tokenStaticAbilities = mapParams.get("TokenStaticAbilities").split(",");
|
||||
} else {
|
||||
this.tokenStaticAbilities = null;
|
||||
}
|
||||
|
||||
this.tokenAmount = mapParams.get("TokenAmount");
|
||||
this.tokenPower = mapParams.get("TokenPower");
|
||||
this.tokenToughness = mapParams.get("TokenToughness");
|
||||
this.tokenName = mapParams.get("TokenName");
|
||||
this.tokenTypes = mapParams.get("TokenTypes").split(",");
|
||||
this.tokenColors = mapParams.get("TokenColors").split(",");
|
||||
this.tokenKeywords = keywords;
|
||||
this.tokenImage = image;
|
||||
if (mapParams.containsKey("TokenOwner")) {
|
||||
this.tokenOwner = mapParams.get("TokenOwner");
|
||||
} else {
|
||||
this.tokenOwner = "You";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getAbility.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public final SpellAbility getAbility() {
|
||||
class AbilityToken extends AbilityActivated {
|
||||
public AbilityToken(final Card ca, final Cost co, final Target t) {
|
||||
super(ca, co, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
AbilityActivated res = new AbilityToken(getSourceCard(),
|
||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 8460074843405764620L;
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryToken.this.tokenCanPlayAI(getActivatingPlayer(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryToken.this.doResolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryToken.this.doStackDescription(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryToken.this.tokenDoTriggerAI(getActivatingPlayer(), this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility abToken = new AbilityToken(this.abilityFactory.getHostCard(),
|
||||
this.abilityFactory.getAbCost(), this.abilityFactory.getAbTgt());
|
||||
|
||||
return abToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getSpell.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public final SpellAbility getSpell() {
|
||||
final SpellAbility spToken = new Spell(this.abilityFactory.getHostCard(), this.abilityFactory.getAbCost(),
|
||||
this.abilityFactory.getAbTgt()) {
|
||||
private static final long serialVersionUID = -8041427947613029670L;
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return AbilityFactoryToken.this.tokenCanPlayAI(getActivatingPlayer(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryToken.this.doResolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryToken.this.doStackDescription(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayFromEffectAI(final boolean mandatory, final boolean withOutManaCost) {
|
||||
if (withOutManaCost) {
|
||||
return AbilityFactoryToken.this.tokenDoTriggerAINoCost(getActivatingPlayer(), this, mandatory);
|
||||
}
|
||||
return AbilityFactoryToken.this.tokenDoTriggerAI(getActivatingPlayer(), this, mandatory);
|
||||
}
|
||||
};
|
||||
|
||||
return spToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* getDrawback.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
public final SpellAbility getDrawback() {
|
||||
class DrawbackToken extends AbilitySub {
|
||||
public DrawbackToken(final Card ca, final Target t) {
|
||||
super(ca, t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
AbilitySub res = new DrawbackToken(getSourceCard(),
|
||||
getTarget() == null ? null : new Target(getTarget()));
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = 7239608350643325111L;
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return AbilityFactoryToken.this.doStackDescription(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
AbilityFactoryToken.this.doResolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory) {
|
||||
return AbilityFactoryToken.this.tokenDoTriggerAI(getActivatingPlayer(), this, mandatory);
|
||||
}
|
||||
}
|
||||
final SpellAbility dbToken = new DrawbackToken(this.abilityFactory.getHostCard(),
|
||||
this.abilityFactory.getAbTgt()); // Spell
|
||||
|
||||
return dbToken;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tokenCanPlayAI.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
private boolean tokenCanPlayAI(final Player ai, final SpellAbility sa) {
|
||||
final Cost cost = sa.getPayCosts();
|
||||
final AbilityFactory af = sa.getAbilityFactory();
|
||||
final HashMap<String, String> mapParams = af.getMapParams();
|
||||
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player opp = ai.getOpponent();
|
||||
for (final String type : this.tokenTypes) {
|
||||
if (type.equals("Legendary")) {
|
||||
// Don't kill AIs Legendary tokens
|
||||
if (ai.getCardsIn(ZoneType.Battlefield, this.tokenName).size() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean haste = false;
|
||||
boolean oneShot = false;
|
||||
for (final String kw : this.tokenKeywords) {
|
||||
if (kw.equals("Haste")) {
|
||||
haste = true;
|
||||
}
|
||||
if (kw.equals("At the beginning of the end step, exile CARDNAME.")
|
||||
|| kw.equals("At the beginning of the end step, sacrifice CARDNAME.")) {
|
||||
oneShot = true;
|
||||
}
|
||||
}
|
||||
|
||||
PhaseHandler ph = Singletons.getModel().getGame().getPhaseHandler();
|
||||
// Don't generate tokens without haste before main 2 if possible
|
||||
if (ph.getPhase().isBefore(PhaseType.MAIN2)
|
||||
&& ph.isPlayerTurn(ai) && !haste
|
||||
&& !mapParams.containsKey("ActivationPhases")) {
|
||||
return false;
|
||||
}
|
||||
if ((ph.isPlayerTurn(ai)
|
||||
|| ph.getPhase().isBefore(
|
||||
PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY))
|
||||
&& !mapParams.containsKey("ActivationPhases") && !mapParams.containsKey("PlayerTurn")
|
||||
&& !AbilityFactory.isSorcerySpeed(sa) && !haste) {
|
||||
return false;
|
||||
}
|
||||
if ((ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN) || Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(
|
||||
opp))
|
||||
&& oneShot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
final Random r = MyRandom.getRandom();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
if (tgt.canOnlyTgtOpponent()) {
|
||||
tgt.addTarget(opp);
|
||||
} else {
|
||||
tgt.addTarget(ai);
|
||||
}
|
||||
}
|
||||
|
||||
if (cost != null) {
|
||||
if (!CostUtil.checkLifeCost(ai, cost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkDiscardCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tokenAmount.equals("X") || this.tokenPower.equals("X") || this.tokenToughness.equals("X")) {
|
||||
int x = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenAmount, sa);
|
||||
if (source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
x = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(x));
|
||||
}
|
||||
if (x <= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (AbilityFactory.playReusable(ai, sa)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) {
|
||||
return true;
|
||||
}
|
||||
if (sa.isAbility()) {
|
||||
return (r.nextFloat() < .9);
|
||||
}
|
||||
|
||||
return (r.nextFloat() < .8);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tokenDoTriggerAI.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param mandatory
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
private boolean tokenDoTriggerAI(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||
if (!ComputerUtil.canPayCost(sa, ai)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return tokenDoTriggerAINoCost(ai, sa, mandatory);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tokenDoTriggerAINoCost.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param mandatory
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
private boolean tokenDoTriggerAINoCost(final Player ai, final SpellAbility sa, final boolean mandatory) {
|
||||
final Card source = sa.getSourceCard();
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
if (tgt.canOnlyTgtOpponent()) {
|
||||
tgt.addTarget(ai.getOpponent());
|
||||
} else {
|
||||
tgt.addTarget(ai);
|
||||
}
|
||||
}
|
||||
if (this.tokenAmount.equals("X") || this.tokenPower.equals("X") || this.tokenToughness.equals("X")) {
|
||||
int x = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenAmount, sa);
|
||||
if (source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
x = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(x));
|
||||
}
|
||||
if (x <= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doStackDescription.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a {@link java.lang.String} object.
|
||||
*/
|
||||
private String doStackDescription(final SpellAbility sa) {
|
||||
|
||||
final HashMap<String, String> params = this.abilityFactory.getMapParams();
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final Card host = this.abilityFactory.getHostCard();
|
||||
|
||||
if (sa instanceof AbilitySub) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
sb.append(host.getName()).append(" - ");
|
||||
}
|
||||
|
||||
if (params.containsKey("StackDescription")) {
|
||||
sb.append(params.get("StackDescription"));
|
||||
}
|
||||
else {
|
||||
|
||||
final int finalPower = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenPower, sa);
|
||||
final int finalToughness = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(),
|
||||
this.tokenToughness, sa);
|
||||
final int finalAmount = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenAmount, sa);
|
||||
|
||||
final String substitutedName = this.tokenName.equals("ChosenType") ? host.getChosenType() : this.tokenName;
|
||||
|
||||
sb.append("Put (").append(finalAmount).append(") ").append(finalPower).append("/").append(finalToughness);
|
||||
sb.append(" ").append(substitutedName).append(" token");
|
||||
if (finalAmount != 1) {
|
||||
sb.append("s");
|
||||
}
|
||||
sb.append(" onto the battlefield");
|
||||
|
||||
if (this.tokenOwner.equals("Opponent")) {
|
||||
sb.append(" under your opponent's control.");
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
|
||||
if (sa.getSubAbility() != null) {
|
||||
sb.append(sa.getSubAbility().getStackDescription());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
private void doResolve(final SpellAbility sa) {
|
||||
final Card host = this.abilityFactory.getHostCard();
|
||||
String imageName = "";
|
||||
Player controller;
|
||||
String cost = "";
|
||||
// Construct colors
|
||||
final String[] substitutedColors = Arrays.copyOf(this.tokenColors, this.tokenColors.length);
|
||||
for (int i = 0; i < substitutedColors.length; i++) {
|
||||
if (substitutedColors[i].equals("ChosenColor")) {
|
||||
// this currently only supports 1 chosen color
|
||||
substitutedColors[i] = host.getChosenColor().get(0);
|
||||
}
|
||||
}
|
||||
String colorDesc = "";
|
||||
for (final String col : substitutedColors) {
|
||||
if (col.equalsIgnoreCase("White")) {
|
||||
colorDesc += "W ";
|
||||
} else if (col.equalsIgnoreCase("Blue")) {
|
||||
colorDesc += "U ";
|
||||
} else if (col.equalsIgnoreCase("Black")) {
|
||||
colorDesc += "B ";
|
||||
} else if (col.equalsIgnoreCase("Red")) {
|
||||
colorDesc += "R ";
|
||||
} else if (col.equalsIgnoreCase("Green")) {
|
||||
colorDesc += "G ";
|
||||
} else if (col.equalsIgnoreCase("Colorless")) {
|
||||
colorDesc = "C";
|
||||
}
|
||||
}
|
||||
if (this.tokenImage.equals("")) {
|
||||
imageName += colorDesc.replace(" ", "") + " " + this.tokenPower + " " + this.tokenToughness + " " + this.tokenName;
|
||||
} else {
|
||||
imageName = this.tokenImage;
|
||||
}
|
||||
// System.out.println("AF_Token imageName = " + imageName);
|
||||
|
||||
for (final char c : colorDesc.toCharArray()) {
|
||||
cost += c + ' ';
|
||||
}
|
||||
|
||||
cost = colorDesc.replace('C', '1').trim();
|
||||
|
||||
controller = AbilityFactory.getDefinedPlayers(this.abilityFactory.getHostCard(), this.tokenOwner, sa).get(0);
|
||||
|
||||
final int finalPower = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenPower, sa);
|
||||
final int finalToughness = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(),
|
||||
this.tokenToughness, sa);
|
||||
final int finalAmount = AbilityFactory.calculateAmount(this.abilityFactory.getHostCard(), this.tokenAmount, sa);
|
||||
|
||||
final String[] substitutedTypes = Arrays.copyOf(this.tokenTypes, this.tokenTypes.length);
|
||||
for (int i = 0; i < substitutedTypes.length; i++) {
|
||||
if (substitutedTypes[i].equals("ChosenType")) {
|
||||
substitutedTypes[i] = host.getChosenType();
|
||||
}
|
||||
}
|
||||
final String substitutedName = this.tokenName.equals("ChosenType") ? host.getChosenType() : this.tokenName;
|
||||
|
||||
final String remember = this.abilityFactory.getMapParams().get("RememberTokens");
|
||||
for (int i = 0; i < finalAmount; i++) {
|
||||
final List<Card> tokens = CardFactoryUtil.makeToken(substitutedName, imageName, controller, cost,
|
||||
substitutedTypes, finalPower, finalToughness, this.tokenKeywords);
|
||||
|
||||
// Grant abilities
|
||||
if (this.tokenAbilities != null) {
|
||||
final AbilityFactory af = new AbilityFactory();
|
||||
for (final String s : this.tokenAbilities) {
|
||||
final String actualAbility = this.abilityFactory.getHostCard().getSVar(s);
|
||||
for (final Card c : tokens) {
|
||||
final SpellAbility grantedAbility = af.getAbility(actualAbility, c);
|
||||
c.addSpellAbility(grantedAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant triggers
|
||||
if (this.tokenTriggers != null) {
|
||||
|
||||
for (final String s : this.tokenTriggers) {
|
||||
final String actualTrigger = this.abilityFactory.getHostCard().getSVar(s);
|
||||
|
||||
for (final Card c : tokens) {
|
||||
|
||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c, true);
|
||||
final String ability = this.abilityFactory.getHostCard().getSVar(
|
||||
parsedTrigger.getMapParams().get("Execute"));
|
||||
parsedTrigger.setOverridingAbility(new AbilityFactory().getAbility(ability, c));
|
||||
c.addTrigger(parsedTrigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant SVars
|
||||
if (this.tokenSVars != null) {
|
||||
for (final String s : this.tokenSVars) {
|
||||
String actualSVar = this.abilityFactory.getHostCard().getSVar(s);
|
||||
String name = s;
|
||||
if (actualSVar.startsWith("SVar")) {
|
||||
actualSVar = actualSVar.split("SVar:")[1];
|
||||
name = actualSVar.split(":")[0];
|
||||
actualSVar = actualSVar.split(":")[1];
|
||||
}
|
||||
for (final Card c : tokens) {
|
||||
c.setSVar(name, actualSVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant static abilities
|
||||
if (this.tokenStaticAbilities != null) {
|
||||
for (final String s : this.tokenStaticAbilities) {
|
||||
final String actualAbility = this.abilityFactory.getHostCard().getSVar(s);
|
||||
for (final Card c : tokens) {
|
||||
c.addStaticAbility(actualAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final Card c : tokens) {
|
||||
if (this.tokenTapped) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
if (this.tokenAttacking) {
|
||||
Singletons.getModel().getGame().getCombat().addAttacker(c);
|
||||
}
|
||||
if (remember != null) {
|
||||
Singletons.getModel().getGame().getCardState(sa.getSourceCard()).addRemembered(c);
|
||||
}
|
||||
if (this.abilityFactory.getMapParams().get("RememberSource") != null) {
|
||||
Singletons.getModel().getGame().getCardState(c).addRemembered(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
226
src/main/java/forge/card/abilityfactory/ai/TokenAi.java
Normal file
226
src/main/java/forge/card/abilityfactory/ai/TokenAi.java
Normal file
@@ -0,0 +1,226 @@
|
||||
package forge.card.abilityfactory.ai;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
import forge.Card;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellAiLogic;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostUtil;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.phase.PhaseHandler;
|
||||
import forge.game.phase.PhaseType;
|
||||
import forge.game.player.ComputerUtil;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
import forge.util.MyRandom;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* AbilityFactory_Token class.
|
||||
* </p>
|
||||
*
|
||||
* @author Forge
|
||||
* @version $Id: AbilityFactoryToken.java 17656 2012-10-22 19:32:56Z Max mtg $
|
||||
*/
|
||||
public class TokenAi extends SpellAiLogic {
|
||||
|
||||
|
||||
private String tokenAmount;
|
||||
private String tokenName;
|
||||
private String[] tokenTypes;
|
||||
private String[] tokenKeywords;
|
||||
private String tokenPower;
|
||||
private String tokenToughness;
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for AbilityFactory_Token.
|
||||
* </p>
|
||||
*
|
||||
* @param af
|
||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||
*/
|
||||
private void readParameters(final Map<String, String> mapParams ) {
|
||||
String[] keywords;
|
||||
|
||||
if (mapParams.containsKey("TokenKeywords")) {
|
||||
// TODO: Change this Split to a semicolon or something else
|
||||
keywords = mapParams.get("TokenKeywords").split("<>");
|
||||
} else {
|
||||
keywords = new String[0];
|
||||
}
|
||||
|
||||
|
||||
this.tokenAmount = mapParams.get("TokenAmount");
|
||||
this.tokenPower = mapParams.get("TokenPower");
|
||||
this.tokenToughness = mapParams.get("TokenToughness");
|
||||
this.tokenName = mapParams.get("TokenName");
|
||||
this.tokenTypes = mapParams.get("TokenTypes").split(",");
|
||||
this.tokenKeywords = keywords;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tokenCanPlayAI.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean canPlayAI(Player ai, java.util.Map<String,String> params, SpellAbility sa) {
|
||||
final Cost cost = sa.getPayCosts();
|
||||
readParameters(params);
|
||||
|
||||
if (ComputerUtil.preventRunAwayActivations(sa)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Player opp = ai.getOpponent();
|
||||
for (final String type : this.tokenTypes) {
|
||||
if (type.equals("Legendary")) {
|
||||
// Don't kill AIs Legendary tokens
|
||||
if (ai.getCardsIn(ZoneType.Battlefield, this.tokenName).size() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean haste = false;
|
||||
boolean oneShot = false;
|
||||
for (final String kw : this.tokenKeywords) {
|
||||
if (kw.equals("Haste")) {
|
||||
haste = true;
|
||||
}
|
||||
if (kw.equals("At the beginning of the end step, exile CARDNAME.")
|
||||
|| kw.equals("At the beginning of the end step, sacrifice CARDNAME.")) {
|
||||
oneShot = true;
|
||||
}
|
||||
}
|
||||
|
||||
PhaseHandler ph = Singletons.getModel().getGame().getPhaseHandler();
|
||||
// Don't generate tokens without haste before main 2 if possible
|
||||
if (ph.getPhase().isBefore(PhaseType.MAIN2)
|
||||
&& ph.isPlayerTurn(ai) && !haste
|
||||
&& !params.containsKey("ActivationPhases")) {
|
||||
return false;
|
||||
}
|
||||
if ((ph.isPlayerTurn(ai)
|
||||
|| ph.getPhase().isBefore(
|
||||
PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY))
|
||||
&& !params.containsKey("ActivationPhases") && !params.containsKey("PlayerTurn")
|
||||
&& !AbilityFactory.isSorcerySpeed(sa) && !haste) {
|
||||
return false;
|
||||
}
|
||||
if ((ph.getPhase().isAfter(PhaseType.COMBAT_BEGIN) || Singletons.getModel().getGame().getPhaseHandler().isPlayerTurn(
|
||||
opp))
|
||||
&& oneShot) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// prevent run-away activations - first time will always return true
|
||||
final Random r = MyRandom.getRandom();
|
||||
final Card source = sa.getSourceCard();
|
||||
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
if (tgt.canOnlyTgtOpponent()) {
|
||||
tgt.addTarget(opp);
|
||||
} else {
|
||||
tgt.addTarget(ai);
|
||||
}
|
||||
}
|
||||
|
||||
if (cost != null) {
|
||||
if (!CostUtil.checkLifeCost(ai, cost, source, 4, null)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkDiscardCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkSacrificeCost(ai, cost, source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CostUtil.checkRemoveCounterCost(cost, source)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.tokenAmount.equals("X") || this.tokenPower.equals("X") || this.tokenToughness.equals("X")) {
|
||||
int x = AbilityFactory.calculateAmount(sa.getSourceCard(), this.tokenAmount, sa);
|
||||
if (source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
x = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(x));
|
||||
}
|
||||
if (x <= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (AbilityFactory.playReusable(ai, sa)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY)) {
|
||||
return true;
|
||||
}
|
||||
if (sa.isAbility()) {
|
||||
return (r.nextFloat() < .9);
|
||||
}
|
||||
|
||||
return (r.nextFloat() < .8);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* tokenDoTriggerAINoCost.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
* @param mandatory
|
||||
* a boolean.
|
||||
* @return a boolean.
|
||||
*/
|
||||
@Override
|
||||
public boolean doTriggerAINoCost(Player ai, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||
readParameters(params);
|
||||
final Card source = sa.getSourceCard();
|
||||
final Target tgt = sa.getTarget();
|
||||
if (tgt != null) {
|
||||
tgt.resetTargets();
|
||||
if (tgt.canOnlyTgtOpponent()) {
|
||||
tgt.addTarget(ai.getOpponent());
|
||||
} else {
|
||||
tgt.addTarget(ai);
|
||||
}
|
||||
}
|
||||
if (this.tokenAmount.equals("X") || this.tokenPower.equals("X") || this.tokenToughness.equals("X")) {
|
||||
int x = AbilityFactory.calculateAmount(source, this.tokenAmount, sa);
|
||||
if (source.getSVar("X").equals("Count$xPaid")) {
|
||||
// Set PayX here to maximum value.
|
||||
x = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||
source.setSVar("PayX", Integer.toString(x));
|
||||
}
|
||||
if (x <= 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
300
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java
Normal file
300
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* Forge: Play Magic: the Gathering.
|
||||
* Copyright (C) 2011 Forge Team
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package forge.card.abilityfactory.effects;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.abilityfactory.SpellEffect;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.trigger.Trigger;
|
||||
import forge.card.trigger.TriggerHandler;
|
||||
import forge.game.player.Player;
|
||||
|
||||
public class TokenEffect extends SpellEffect {
|
||||
|
||||
private String tokenOwner;
|
||||
private String[] tokenColors;
|
||||
private String tokenImage;
|
||||
private String[] tokenAbilities;
|
||||
private String[] tokenTriggers;
|
||||
private String[] tokenSVars;
|
||||
private String[] tokenStaticAbilities;
|
||||
private boolean tokenTapped;
|
||||
private boolean tokenAttacking;
|
||||
private String tokenAmount;
|
||||
private String tokenToughness;
|
||||
private String tokenPower;
|
||||
private String[] tokenTypes;
|
||||
private String tokenName;
|
||||
private String[] tokenKeywords;
|
||||
|
||||
private void readParameters(final Map<String, String> mapParams) {
|
||||
String image;
|
||||
String[] keywords;
|
||||
|
||||
if (mapParams.containsKey("TokenKeywords")) {
|
||||
// TODO: Change this Split to a semicolon or something else
|
||||
keywords = mapParams.get("TokenKeywords").split("<>");
|
||||
} else {
|
||||
keywords = new String[0];
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("TokenImage")) {
|
||||
image = mapParams.get("TokenImage");
|
||||
} else {
|
||||
image = "";
|
||||
}
|
||||
|
||||
this.tokenTapped = mapParams.containsKey("TokenTapped") && mapParams.get("TokenTapped").equals("True");
|
||||
this.tokenAttacking = mapParams.containsKey("TokenAttacking") && mapParams.get("TokenAttacking").equals("True");
|
||||
|
||||
if (mapParams.containsKey("TokenAbilities")) {
|
||||
this.tokenAbilities = mapParams.get("TokenAbilities").split(",");
|
||||
} else {
|
||||
this.tokenAbilities = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenTriggers")) {
|
||||
this.tokenTriggers = mapParams.get("TokenTriggers").split(",");
|
||||
} else {
|
||||
this.tokenTriggers = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenSVars")) {
|
||||
this.tokenSVars = mapParams.get("TokenSVars").split(",");
|
||||
} else {
|
||||
this.tokenSVars = null;
|
||||
}
|
||||
if (mapParams.containsKey("TokenStaticAbilities")) {
|
||||
this.tokenStaticAbilities = mapParams.get("TokenStaticAbilities").split(",");
|
||||
} else {
|
||||
this.tokenStaticAbilities = null;
|
||||
}
|
||||
|
||||
this.tokenAmount = mapParams.get("TokenAmount");
|
||||
this.tokenPower = mapParams.get("TokenPower");
|
||||
this.tokenToughness = mapParams.get("TokenToughness");
|
||||
this.tokenName = mapParams.get("TokenName");
|
||||
this.tokenTypes = mapParams.get("TokenTypes").split(",");
|
||||
this.tokenColors = mapParams.get("TokenColors").split(",");
|
||||
this.tokenKeywords = keywords;
|
||||
this.tokenImage = image;
|
||||
if (mapParams.containsKey("TokenOwner")) {
|
||||
this.tokenOwner = mapParams.get("TokenOwner");
|
||||
} else {
|
||||
this.tokenOwner = "You";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
final Card host = sa.getSourceCard();
|
||||
|
||||
readParameters(params);
|
||||
|
||||
if (sa instanceof AbilitySub) {
|
||||
sb.append(" ");
|
||||
} else {
|
||||
sb.append(host.getName()).append(" - ");
|
||||
}
|
||||
|
||||
if (params.containsKey("StackDescription")) {
|
||||
sb.append(params.get("StackDescription"));
|
||||
}
|
||||
else {
|
||||
|
||||
final int finalPower = AbilityFactory.calculateAmount(host, this.tokenPower, sa);
|
||||
final int finalToughness = AbilityFactory.calculateAmount(host, this.tokenToughness, sa);
|
||||
final int finalAmount = AbilityFactory.calculateAmount(host, this.tokenAmount, sa);
|
||||
|
||||
final String substitutedName = this.tokenName.equals("ChosenType") ? host.getChosenType() : this.tokenName;
|
||||
|
||||
sb.append("Put (").append(finalAmount).append(") ").append(finalPower).append("/").append(finalToughness);
|
||||
sb.append(" ").append(substitutedName).append(" token");
|
||||
if (finalAmount != 1) {
|
||||
sb.append("s");
|
||||
}
|
||||
sb.append(" onto the battlefield");
|
||||
|
||||
if (this.tokenOwner.equals("Opponent")) {
|
||||
sb.append(" under your opponent's control.");
|
||||
} else {
|
||||
sb.append(".");
|
||||
}
|
||||
}
|
||||
|
||||
if (sa.getSubAbility() != null) {
|
||||
sb.append(sa.getSubAbility().getStackDescription());
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* doResolve.
|
||||
* </p>
|
||||
*
|
||||
* @param sa
|
||||
* a {@link forge.card.spellability.SpellAbility} object.
|
||||
*/
|
||||
@Override
|
||||
public void resolve(java.util.Map<String,String> params, SpellAbility sa) {
|
||||
final Card host = sa.getSourceCard();
|
||||
readParameters(params);
|
||||
|
||||
String imageName = "";
|
||||
Player controller;
|
||||
String cost = "";
|
||||
// Construct colors
|
||||
final String[] substitutedColors = Arrays.copyOf(this.tokenColors, this.tokenColors.length);
|
||||
for (int i = 0; i < substitutedColors.length; i++) {
|
||||
if (substitutedColors[i].equals("ChosenColor")) {
|
||||
// this currently only supports 1 chosen color
|
||||
substitutedColors[i] = host.getChosenColor().get(0);
|
||||
}
|
||||
}
|
||||
String colorDesc = "";
|
||||
for (final String col : substitutedColors) {
|
||||
if (col.equalsIgnoreCase("White")) {
|
||||
colorDesc += "W ";
|
||||
} else if (col.equalsIgnoreCase("Blue")) {
|
||||
colorDesc += "U ";
|
||||
} else if (col.equalsIgnoreCase("Black")) {
|
||||
colorDesc += "B ";
|
||||
} else if (col.equalsIgnoreCase("Red")) {
|
||||
colorDesc += "R ";
|
||||
} else if (col.equalsIgnoreCase("Green")) {
|
||||
colorDesc += "G ";
|
||||
} else if (col.equalsIgnoreCase("Colorless")) {
|
||||
colorDesc = "C";
|
||||
}
|
||||
}
|
||||
if (this.tokenImage.equals("")) {
|
||||
imageName += colorDesc.replace(" ", "") + " " + this.tokenPower + " " + this.tokenToughness + " " + this.tokenName;
|
||||
} else {
|
||||
imageName = this.tokenImage;
|
||||
}
|
||||
// System.out.println("AF_Token imageName = " + imageName);
|
||||
|
||||
for (final char c : colorDesc.toCharArray()) {
|
||||
cost += c + ' ';
|
||||
}
|
||||
|
||||
cost = colorDesc.replace('C', '1').trim();
|
||||
|
||||
controller = AbilityFactory.getDefinedPlayers(host, this.tokenOwner, sa).get(0);
|
||||
|
||||
final int finalPower = AbilityFactory.calculateAmount(host, this.tokenPower, sa);
|
||||
final int finalToughness = AbilityFactory.calculateAmount(host, this.tokenToughness, sa);
|
||||
final int finalAmount = AbilityFactory.calculateAmount(host, this.tokenAmount, sa);
|
||||
|
||||
final String[] substitutedTypes = Arrays.copyOf(this.tokenTypes, this.tokenTypes.length);
|
||||
for (int i = 0; i < substitutedTypes.length; i++) {
|
||||
if (substitutedTypes[i].equals("ChosenType")) {
|
||||
substitutedTypes[i] = host.getChosenType();
|
||||
}
|
||||
}
|
||||
final String substitutedName = this.tokenName.equals("ChosenType") ? host.getChosenType() : this.tokenName;
|
||||
|
||||
final String remember = params.get("RememberTokens");
|
||||
for (int i = 0; i < finalAmount; i++) {
|
||||
final List<Card> tokens = CardFactoryUtil.makeToken(substitutedName, imageName, controller, cost,
|
||||
substitutedTypes, finalPower, finalToughness, this.tokenKeywords);
|
||||
|
||||
// Grant abilities
|
||||
if (this.tokenAbilities != null) {
|
||||
final AbilityFactory af = new AbilityFactory();
|
||||
for (final String s : this.tokenAbilities) {
|
||||
final String actualAbility = host.getSVar(s);
|
||||
for (final Card c : tokens) {
|
||||
final SpellAbility grantedAbility = af.getAbility(actualAbility, c);
|
||||
c.addSpellAbility(grantedAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant triggers
|
||||
if (this.tokenTriggers != null) {
|
||||
|
||||
for (final String s : this.tokenTriggers) {
|
||||
final String actualTrigger = host.getSVar(s);
|
||||
|
||||
for (final Card c : tokens) {
|
||||
|
||||
final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c, true);
|
||||
final String ability = host.getSVar(parsedTrigger.getMapParams().get("Execute"));
|
||||
parsedTrigger.setOverridingAbility(new AbilityFactory().getAbility(ability, c));
|
||||
c.addTrigger(parsedTrigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant SVars
|
||||
if (this.tokenSVars != null) {
|
||||
for (final String s : this.tokenSVars) {
|
||||
String actualSVar = host.getSVar(s);
|
||||
String name = s;
|
||||
if (actualSVar.startsWith("SVar")) {
|
||||
actualSVar = actualSVar.split("SVar:")[1];
|
||||
name = actualSVar.split(":")[0];
|
||||
actualSVar = actualSVar.split(":")[1];
|
||||
}
|
||||
for (final Card c : tokens) {
|
||||
c.setSVar(name, actualSVar);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Grant static abilities
|
||||
if (this.tokenStaticAbilities != null) {
|
||||
for (final String s : this.tokenStaticAbilities) {
|
||||
final String actualAbility = host.getSVar(s);
|
||||
for (final Card c : tokens) {
|
||||
c.addStaticAbility(actualAbility);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (final Card c : tokens) {
|
||||
if (this.tokenTapped) {
|
||||
c.setTapped(true);
|
||||
}
|
||||
if (this.tokenAttacking) {
|
||||
Singletons.getModel().getGame().getCombat().addAttacker(c);
|
||||
}
|
||||
if (remember != null) {
|
||||
Singletons.getModel().getGame().getCardState(sa.getSourceCard()).addRemembered(c);
|
||||
}
|
||||
if (params.get("RememberSource") != null) {
|
||||
Singletons.getModel().getGame().getCardState(c).addRemembered(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user