mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
added Clone AF and first steps in moving SVars to CardCharacteristics class
This commit is contained in:
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -11684,6 +11684,7 @@ src/main/java/forge/card/abilityfactory/AbilityFactoryCharm.java svneol=native#t
|
|||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryChoose.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryClash.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCleanup.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryCleanup.java svneol=native#text/plain
|
||||||
|
src/main/java/forge/card/abilityfactory/AbilityFactoryClone.java -text
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryCombat.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCopy.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryCopy.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCounterMagic.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryCounterMagic.java svneol=native#text/plain
|
||||||
|
|||||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -357,6 +357,7 @@ res/pics/WWK
|
|||||||
res/pics/ZEN
|
res/pics/ZEN
|
||||||
res/pics/booster
|
res/pics/booster
|
||||||
res/pics/icons
|
res/pics/icons
|
||||||
|
res/pics/tokens
|
||||||
res/pics_product/*.jpg
|
res/pics_product/*.jpg
|
||||||
res/preferences
|
res/preferences
|
||||||
res/preferences/forge.preferences
|
res/preferences/forge.preferences
|
||||||
|
|||||||
@@ -221,7 +221,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
private final ArrayList<Card> hauntedBy = new ArrayList<Card>();
|
private final ArrayList<Card> hauntedBy = new ArrayList<Card>();
|
||||||
private Card haunting = null;
|
private Card haunting = null;
|
||||||
|
|
||||||
private Map<String, String> sVars = new TreeMap<String, String>();
|
//private Map<String, String> sVars = new TreeMap<String, String>();
|
||||||
|
|
||||||
// hacky code below, used to limit the number of times an ability
|
// hacky code below, used to limit the number of times an ability
|
||||||
// can be used per turn like Vampire Bats
|
// can be used per turn like Vampire Bats
|
||||||
@@ -1458,11 +1458,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* @return a {@link java.lang.String} object.
|
* @return a {@link java.lang.String} object.
|
||||||
*/
|
*/
|
||||||
public final String getSVar(final String var) {
|
public final String getSVar(final String var) {
|
||||||
if (this.sVars.containsKey(var)) {
|
return this.getCharacteristics().getSVar(var);
|
||||||
return this.sVars.get(var);
|
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1476,11 +1472,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* a {@link java.lang.String} object.
|
* a {@link java.lang.String} object.
|
||||||
*/
|
*/
|
||||||
public final void setSVar(final String var, final String str) {
|
public final void setSVar(final String var, final String str) {
|
||||||
if (this.sVars.containsKey(var)) {
|
this.getCharacteristics().setSVar(var, str);
|
||||||
this.sVars.remove(var);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.sVars.put(var, str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1491,7 +1483,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* @return a Map object.
|
* @return a Map object.
|
||||||
*/
|
*/
|
||||||
public final Map<String, String> getSVars() {
|
public final Map<String, String> getSVars() {
|
||||||
return this.sVars;
|
return this.getCharacteristics().getSVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1503,7 +1495,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* a Map object.
|
* a Map object.
|
||||||
*/
|
*/
|
||||||
public final void setSVars(final Map<String, String> newSVars) {
|
public final void setSVars(final Map<String, String> newSVars) {
|
||||||
this.sVars = newSVars;
|
this.getCharacteristics().setSVars(newSVars);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -8403,8 +8395,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* @return an int
|
* @return an int
|
||||||
*/
|
*/
|
||||||
public final int getFoil() {
|
public final int getFoil() {
|
||||||
if (this.sVars.containsKey("Foil")) {
|
final String foil = this.getCharacteristics().getSVar("Foil");
|
||||||
return Integer.parseInt(this.sVars.get("Foil"));
|
if (!foil.isEmpty()) {
|
||||||
|
return Integer.parseInt(foil);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -8417,7 +8410,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
|||||||
* an int
|
* an int
|
||||||
*/
|
*/
|
||||||
public final void setFoil(final int f) {
|
public final void setFoil(final int f) {
|
||||||
this.sVars.put("Foil", Integer.toString(f));
|
this.getCharacteristics().setSVar("Foil", Integer.toString(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package forge.card;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
import forge.CardColor;
|
import forge.CardColor;
|
||||||
import forge.card.replacement.ReplacementEffect;
|
import forge.card.replacement.ReplacementEffect;
|
||||||
@@ -50,6 +52,7 @@ public class CardCharacteristics {
|
|||||||
private String imageFilename = "";
|
private String imageFilename = "";
|
||||||
private String imageName = "";
|
private String imageName = "";
|
||||||
private ArrayList<EditionInfo> sets = new ArrayList<EditionInfo>();
|
private ArrayList<EditionInfo> sets = new ArrayList<EditionInfo>();
|
||||||
|
private Map<String, String> sVars = new TreeMap<String, String>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name.
|
* Gets the name.
|
||||||
@@ -388,4 +391,62 @@ public class CardCharacteristics {
|
|||||||
public void setReplacementEffects(ArrayList<ReplacementEffect> replacementEffects0) {
|
public void setReplacementEffects(ArrayList<ReplacementEffect> replacementEffects0) {
|
||||||
this.replacementEffects = replacementEffects0;
|
this.replacementEffects = replacementEffects0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* getSVar.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param var
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
* @return a {@link java.lang.String} object.
|
||||||
|
*/
|
||||||
|
public final String getSVar(final String var) {
|
||||||
|
if (this.sVars.containsKey(var)) {
|
||||||
|
return this.sVars.get(var);
|
||||||
|
} else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* setSVar.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param var
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
* @param str
|
||||||
|
* a {@link java.lang.String} object.
|
||||||
|
*/
|
||||||
|
public final void setSVar(final String var, final String str) {
|
||||||
|
if (this.sVars.containsKey(var)) {
|
||||||
|
this.sVars.remove(var);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sVars.put(var, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* getSVars.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @return a Map object.
|
||||||
|
*/
|
||||||
|
public final Map<String, String> getSVars() {
|
||||||
|
return this.sVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* setSVars.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param newSVars
|
||||||
|
* a Map object.
|
||||||
|
*/
|
||||||
|
public final void setSVars(final Map<String, String> newSVars) {
|
||||||
|
this.sVars = newSVars;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -562,6 +562,12 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
else if (this.api.equals("Clone")) {
|
||||||
|
if (this.isDb) {
|
||||||
|
spellAbility = AbilityFactoryClone.createDrawbackClone(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
else if (this.api.equals("CopyPermanent")) {
|
else if (this.api.equals("CopyPermanent")) {
|
||||||
if (this.isAb) {
|
if (this.isAb) {
|
||||||
spellAbility = AbilityFactoryCopy.createAbilityCopyPermanent(this);
|
spellAbility = AbilityFactoryCopy.createAbilityCopyPermanent(this);
|
||||||
|
|||||||
576
src/main/java/forge/card/abilityfactory/AbilityFactoryClone.java
Normal file
576
src/main/java/forge/card/abilityfactory/AbilityFactoryClone.java
Normal file
@@ -0,0 +1,576 @@
|
|||||||
|
/*
|
||||||
|
* 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.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import forge.AllZone;
|
||||||
|
import forge.Card;
|
||||||
|
import forge.CardCharactersticName;
|
||||||
|
import forge.CardUtil;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.cardfactory.AbstractCardFactory;
|
||||||
|
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.spellability.Target;
|
||||||
|
import forge.card.trigger.TriggerType;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* AbilityFactoryClone class.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author Forge
|
||||||
|
* @version $Id: AbilityFactoryClone.java 15541 2012-05-14 11:47:16Z Sloth $
|
||||||
|
*/
|
||||||
|
public final class AbilityFactoryClone {
|
||||||
|
|
||||||
|
private AbilityFactoryClone() {
|
||||||
|
throw new AssertionError();
|
||||||
|
}
|
||||||
|
|
||||||
|
// **************************************************************
|
||||||
|
// *************************** Clone ****************************
|
||||||
|
// **************************************************************
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* createAbilityClone.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
public static SpellAbility createAbilityClone(final AbilityFactory af) {
|
||||||
|
final SpellAbility abClone = new AbilityActivated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = 1938171749867734123L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI() {
|
||||||
|
return AbilityFactoryClone.cloneCanPlayAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
AbilityFactoryClone.cloneResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return AbilityFactoryClone.cloneStackDescription(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTrigger(final boolean mandatory) {
|
||||||
|
return AbilityFactoryClone.cloneTriggerAI(af, this, mandatory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return abClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* createSpellClone.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
public static SpellAbility createSpellClone(final AbilityFactory af) {
|
||||||
|
final SpellAbility spClone = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = -4047747186919390520L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI() {
|
||||||
|
return AbilityFactoryClone.cloneCanPlayAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
AbilityFactoryClone.cloneResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return AbilityFactoryClone.cloneStackDescription(af, this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return spClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* createDrawbackClone.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @return a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
public static SpellAbility createDrawbackClone(final AbilityFactory af) {
|
||||||
|
final SpellAbility dbClone = new AbilitySub(af.getHostCard(), af.getAbTgt()) {
|
||||||
|
private static final long serialVersionUID = -8659938411435528741L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void resolve() {
|
||||||
|
AbilityFactoryClone.cloneResolve(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback() {
|
||||||
|
return AbilityFactoryClone.clonePlayDrawbackAI(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getStackDescription() {
|
||||||
|
return AbilityFactoryClone.cloneStackDescription(af, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTrigger(final boolean mandatory) {
|
||||||
|
return AbilityFactoryClone.cloneTriggerAI(af, this, mandatory);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return dbClone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* cloneStackDescription.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a {@link java.lang.String} object.
|
||||||
|
*/
|
||||||
|
private static String cloneStackDescription(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
final HashMap<String, String> params = af.getMapParams();
|
||||||
|
final Card host = sa.getSourceCard();
|
||||||
|
final Map<String, String> svars = host.getSVars();
|
||||||
|
|
||||||
|
int power = -1;
|
||||||
|
if (params.containsKey("Power")) {
|
||||||
|
power = AbilityFactory.calculateAmount(host, params.get("Power"), sa);
|
||||||
|
}
|
||||||
|
int toughness = -1;
|
||||||
|
if (params.containsKey("Toughness")) {
|
||||||
|
toughness = AbilityFactory.calculateAmount(host, params.get("Toughness"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
final boolean permanent = params.containsKey("Permanent");
|
||||||
|
final ArrayList<String> types = new ArrayList<String>();
|
||||||
|
if (params.containsKey("Types")) {
|
||||||
|
types.addAll(Arrays.asList(params.get("Types").split(",")));
|
||||||
|
}
|
||||||
|
final ArrayList<String> keywords = new ArrayList<String>();
|
||||||
|
if (params.containsKey("Keywords")) {
|
||||||
|
keywords.addAll(Arrays.asList(params.get("Keywords").split(" & ")));
|
||||||
|
}
|
||||||
|
// allow SVar substitution for keywords
|
||||||
|
for (int i = 0; i < keywords.size(); i++) {
|
||||||
|
final String k = keywords.get(i);
|
||||||
|
if (svars.containsKey(k)) {
|
||||||
|
keywords.add("\"" + k + "\"");
|
||||||
|
keywords.remove(k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final ArrayList<String> colors = new ArrayList<String>();
|
||||||
|
if (params.containsKey("Colors")) {
|
||||||
|
colors.addAll(Arrays.asList(params.get("Colors").split(",")));
|
||||||
|
}
|
||||||
|
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
if (sa instanceof AbilitySub) {
|
||||||
|
sb.append(" ");
|
||||||
|
} else {
|
||||||
|
sb.append(sa.getSourceCard().getName()).append(" - ");
|
||||||
|
}
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
ArrayList<Card> tgts;
|
||||||
|
if (tgt != null) {
|
||||||
|
tgts = tgt.getTargetCards();
|
||||||
|
} else {
|
||||||
|
tgts = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (final Card c : tgts) {
|
||||||
|
sb.append(c).append(" ");
|
||||||
|
}
|
||||||
|
sb.append("become");
|
||||||
|
if (tgts.size() == 1) {
|
||||||
|
sb.append("s a");
|
||||||
|
}
|
||||||
|
// if power is -1, we'll assume it's not just setting toughness
|
||||||
|
if (power != -1) {
|
||||||
|
sb.append(" ").append(power).append("/").append(toughness);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colors.size() > 0) {
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
if (colors.contains("ChosenColor")) {
|
||||||
|
sb.append("color of that player's choice");
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < colors.size(); i++) {
|
||||||
|
sb.append(colors.get(i));
|
||||||
|
if (i < (colors.size() - 1)) {
|
||||||
|
sb.append(" and ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(" ");
|
||||||
|
if (types.contains("ChosenType")) {
|
||||||
|
sb.append("type of player's choice ");
|
||||||
|
} else {
|
||||||
|
for (int i = types.size() - 1; i >= 0; i--) {
|
||||||
|
sb.append(types.get(i));
|
||||||
|
sb.append(" ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (keywords.size() > 0) {
|
||||||
|
sb.append("with ");
|
||||||
|
}
|
||||||
|
for (int i = 0; i < keywords.size(); i++) {
|
||||||
|
sb.append(keywords.get(i));
|
||||||
|
if (i < (keywords.size() - 1)) {
|
||||||
|
sb.append(" and ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// sb.append(abilities)
|
||||||
|
// sb.append(triggers)
|
||||||
|
if (!permanent) {
|
||||||
|
if (params.containsKey("UntilEndOfCombat")) {
|
||||||
|
sb.append(" until end of combat.");
|
||||||
|
} else if (params.containsKey("UntilHostLeavesPlay")) {
|
||||||
|
sb.append(" until ").append(host).append(" leaves the battlefield.");
|
||||||
|
} else if (params.containsKey("UntilYourNextUpkeep")) {
|
||||||
|
sb.append(" until your next upkeep.");
|
||||||
|
} else if (params.containsKey("UntilControllerNextUntap")) {
|
||||||
|
sb.append(" until its controller's next untap step.");
|
||||||
|
} else {
|
||||||
|
sb.append(" until end of turn.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sb.append(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
sb.append(abSub.getStackDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
} // end cloneStackDescription()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* cloneCanPlayAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
private static boolean cloneCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
|
||||||
|
final HashMap<String, String> params = af.getMapParams();
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
boolean useAbility = true;
|
||||||
|
|
||||||
|
// if (card.getController().isComputer()) {
|
||||||
|
// final CardList creatures = AllZoneUtil.getCreaturesInPlay();
|
||||||
|
// if (!creatures.isEmpty()) {
|
||||||
|
// cardToCopy = CardFactoryUtil.getBestCreatureAI(creatures);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO - add some kind of check to answer
|
||||||
|
// "Am I going to attack with this?"
|
||||||
|
// TODO - add some kind of check for during human turn to answer
|
||||||
|
// "Can I use this to block something?"
|
||||||
|
|
||||||
|
// don't use instant speed clone abilities outside computers
|
||||||
|
// Combat_Begin step
|
||||||
|
if (!Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.COMBAT_BEGIN)
|
||||||
|
&& Singletons.getModel().getGameState().getPhaseHandler().isPlayerTurn(AllZone.getComputerPlayer()) && !AbilityFactory.isSorcerySpeed(sa)
|
||||||
|
&& !params.containsKey("ActivationPhases") && !params.containsKey("Permanent")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't use instant speed clone abilities outside humans
|
||||||
|
// Combat_Declare_Attackers_InstantAbility step
|
||||||
|
if ((!Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) || (AllZone.getCombat()
|
||||||
|
.getAttackers().isEmpty())) && Singletons.getModel().getGameState().getPhaseHandler().isPlayerTurn(AllZone.getHumanPlayer())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't activate during main2 unless this effect is permanent
|
||||||
|
if (Singletons.getModel().getGameState().getPhaseHandler().is(PhaseType.MAIN2) && !params.containsKey("Permanent")) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (null == tgt) {
|
||||||
|
final ArrayList<Card> defined = AbilityFactory.getDefinedCards(source, params.get("Defined"), sa);
|
||||||
|
|
||||||
|
boolean bFlag = false;
|
||||||
|
for (final Card c : defined) {
|
||||||
|
bFlag |= (!c.isCreature() && !c.isTapped() && !(c.getTurnInZone() == Singletons.getModel().getGameState().getPhaseHandler().getTurn()));
|
||||||
|
|
||||||
|
// for creatures that could be improved (like Figure of Destiny)
|
||||||
|
if (c.isCreature() && (params.containsKey("Permanent") || (!c.isTapped() && !c.isSick()))) {
|
||||||
|
int power = -5;
|
||||||
|
if (params.containsKey("Power")) {
|
||||||
|
power = AbilityFactory.calculateAmount(source, params.get("Power"), sa);
|
||||||
|
}
|
||||||
|
int toughness = -5;
|
||||||
|
if (params.containsKey("Toughness")) {
|
||||||
|
toughness = AbilityFactory.calculateAmount(source, params.get("Toughness"), sa);
|
||||||
|
}
|
||||||
|
if ((power + toughness) > (c.getCurrentPower() + c.getCurrentToughness())) {
|
||||||
|
bFlag = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!bFlag) { // All of the defined stuff is cloned, not very
|
||||||
|
// useful
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tgt.resetTargets();
|
||||||
|
useAbility &= AbilityFactoryClone.cloneTgtAI(af, sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
useAbility &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return useAbility;
|
||||||
|
} // end cloneCanPlayAI()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* clonePlayDrawbackAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
private static boolean clonePlayDrawbackAI(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
// AI should only activate this during Human's turn
|
||||||
|
boolean chance = true;
|
||||||
|
|
||||||
|
if (sa.getTarget() != null) {
|
||||||
|
chance = AbilityFactoryClone.cloneTgtAI(af, sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
chance &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* cloneTriggerAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @param mandatory
|
||||||
|
* a boolean.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
private static boolean cloneTriggerAI(final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
|
||||||
|
if (!ComputerUtil.canPayCost(sa)) { // If there is a cost payment
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean chance = true;
|
||||||
|
|
||||||
|
if (sa.getTarget() != null) {
|
||||||
|
chance = AbilityFactoryClone.cloneTgtAI(af, sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Improve AI for triggers. If source is a creature with:
|
||||||
|
// When ETB, sacrifice a creature. Check to see if the AI has something
|
||||||
|
// to sacrifice
|
||||||
|
|
||||||
|
// Eventually, we can call the trigger of ETB abilities with
|
||||||
|
// not mandatory as part of the checks to cast something
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
chance &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return chance || mandatory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* cloneTgtAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
private static boolean cloneTgtAI(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
// This is reasonable for now. Kamahl, Fist of Krosa and a sorcery or
|
||||||
|
// two are the only things
|
||||||
|
// that clone a target. Those can just use SVar:RemAIDeck:True until
|
||||||
|
// this can do a reasonably
|
||||||
|
// good job of picking a good target
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* cloneResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
*/
|
||||||
|
private static void cloneResolve(final AbilityFactory af, final SpellAbility sa) {
|
||||||
|
final HashMap<String, String> params = af.getMapParams();
|
||||||
|
Card tgtCard;
|
||||||
|
final Card host = sa.getSourceCard();
|
||||||
|
|
||||||
|
|
||||||
|
// find target of cloning
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtCard = tgt.getTargetCards().get(0);
|
||||||
|
}
|
||||||
|
else if (params.containsKey("Defined")) {
|
||||||
|
tgtCard = AbilityFactory.getDefinedCards(host, params.get("Defined"), sa).get(0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tgtCard = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
// find cloning source i.e. thing to be copied
|
||||||
|
Card cardToCopy = AbilityFactory.getDefinedCards(host, params.get("CloneSource"), sa).get(0);
|
||||||
|
if (cardToCopy == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String imageFileName = host.getImageFilename();
|
||||||
|
|
||||||
|
Card cloned;
|
||||||
|
|
||||||
|
AllZone.getTriggerHandler().suppressMode(TriggerType.Transformed);
|
||||||
|
|
||||||
|
if (cardToCopy.isToken()) {
|
||||||
|
cloned = CardFactoryUtil.copyStats(cardToCopy);
|
||||||
|
|
||||||
|
cloned.setName(cardToCopy.getName());
|
||||||
|
cloned.setImageName(cardToCopy.getImageName());
|
||||||
|
|
||||||
|
cloned.setOwner(sa.getActivatingPlayer());
|
||||||
|
cloned.addController(sa.getActivatingPlayer());
|
||||||
|
|
||||||
|
cloned.setManaCost(cardToCopy.getManaCost());
|
||||||
|
cloned.setColor(cardToCopy.getColor());
|
||||||
|
cloned.setToken(true);
|
||||||
|
|
||||||
|
cloned.setType(cardToCopy.getType());
|
||||||
|
|
||||||
|
cloned.setBaseAttack(cardToCopy.getBaseAttack());
|
||||||
|
cloned.setBaseDefense(cardToCopy.getBaseDefense());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Card origin = cardToCopy;
|
||||||
|
// TODO: transform back before copying
|
||||||
|
cloned = AbstractCardFactory.getCard2(origin, tgtCard.getOwner());
|
||||||
|
// TODO: transform origin back to how it was (if needed)
|
||||||
|
}
|
||||||
|
tgtCard.addAlternateState(CardCharactersticName.Cloner);
|
||||||
|
tgtCard.switchStates(CardCharactersticName.Original, CardCharactersticName.Cloner);
|
||||||
|
tgtCard.setState(CardCharactersticName.Original);
|
||||||
|
|
||||||
|
if (cardToCopy.getCurState() == CardCharactersticName.Transformed && cardToCopy.isDoubleFaced()) {
|
||||||
|
cloned.setState(CardCharactersticName.Transformed);
|
||||||
|
}
|
||||||
|
|
||||||
|
CardFactoryUtil.copyCharacteristics(cloned, tgtCard);
|
||||||
|
CardFactoryUtil.addAbilityFactoryAbilities(tgtCard);
|
||||||
|
for (int i = 0; i < tgtCard.getStaticAbilityStrings().size(); i++) {
|
||||||
|
tgtCard.addStaticAbility(tgtCard.getStaticAbilityStrings().get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If target is a flipped card, also copy the flipped
|
||||||
|
// state.
|
||||||
|
if (cardToCopy.isFlip()) {
|
||||||
|
cloned.setState(CardCharactersticName.Flipped);
|
||||||
|
cloned.setImageFilename(CardUtil.buildFilename(cloned));
|
||||||
|
tgtCard.addAlternateState(CardCharactersticName.Flipped);
|
||||||
|
tgtCard.setState(CardCharactersticName.Flipped);
|
||||||
|
CardFactoryUtil.copyCharacteristics(cloned, tgtCard);
|
||||||
|
CardFactoryUtil.addAbilityFactoryAbilities(tgtCard);
|
||||||
|
for (int i = 0; i < tgtCard.getStaticAbilityStrings().size(); i++) {
|
||||||
|
tgtCard.addStaticAbility(tgtCard.getStaticAbilityStrings().get(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
tgtCard.setFlip(true);
|
||||||
|
|
||||||
|
tgtCard.setState(CardCharactersticName.Original);
|
||||||
|
} else {
|
||||||
|
tgtCard.setFlip(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
AllZone.getTriggerHandler().clearSuppression(TriggerType.Transformed);
|
||||||
|
|
||||||
|
//keep the Clone card image for the cloned card
|
||||||
|
tgtCard.setImageFilename(imageFileName);
|
||||||
|
} // cloneResolve
|
||||||
|
|
||||||
|
} // end class AbilityFactoryClone
|
||||||
Reference in New Issue
Block a user