mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-17 11:18: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/AbilityFactoryClash.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/AbilityFactoryCopy.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/booster
|
||||
res/pics/icons
|
||||
res/pics/tokens
|
||||
res/pics_product/*.jpg
|
||||
res/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 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
|
||||
// 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.
|
||||
*/
|
||||
public final String getSVar(final String var) {
|
||||
if (this.sVars.containsKey(var)) {
|
||||
return this.sVars.get(var);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
return this.getCharacteristics().getSVar(var);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1476,11 +1472,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* 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);
|
||||
this.getCharacteristics().setSVar(var, str);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1491,7 +1483,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* @return a Map object.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
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
|
||||
*/
|
||||
public final int getFoil() {
|
||||
if (this.sVars.containsKey("Foil")) {
|
||||
return Integer.parseInt(this.sVars.get("Foil"));
|
||||
final String foil = this.getCharacteristics().getSVar("Foil");
|
||||
if (!foil.isEmpty()) {
|
||||
return Integer.parseInt(foil);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -8417,7 +8410,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* an int
|
||||
*/
|
||||
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.List;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.CardColor;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
@@ -50,6 +52,7 @@ public class CardCharacteristics {
|
||||
private String imageFilename = "";
|
||||
private String imageName = "";
|
||||
private ArrayList<EditionInfo> sets = new ArrayList<EditionInfo>();
|
||||
private Map<String, String> sVars = new TreeMap<String, String>();
|
||||
|
||||
/**
|
||||
* Gets the name.
|
||||
@@ -388,4 +391,62 @@ public class CardCharacteristics {
|
||||
public void setReplacementEffects(ArrayList<ReplacementEffect> 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")) {
|
||||
if (this.isAb) {
|
||||
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