package forge.card.abilityFactory;
import forge.*;
import forge.card.spellability.*;
import forge.card.staticAbility.StaticAbility;
import forge.card.trigger.Trigger;
import forge.card.trigger.TriggerHandler;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* <p>AbilityFactory_Animate class.</p>
*
* @author Forge
* @version $Id: $
*/
public class AbilityFactory_Animate {
//**************************************************************
//************************** Animate ***************************
//**************************************************************
/**
* <p>createAbilityAnimate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityAnimate(final AbilityFactory af) {
final SpellAbility abAnimate = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 1938171749867735155L;
@Override
public boolean canPlayAI() {
return animateCanPlayAI(af, this);
}
@Override
public void resolve() {
animateResolve(af, this);
}
@Override
public String getStackDescription() {
return animateStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return animateTriggerAI(af, this, mandatory);
}
};
return abAnimate;
}
/**
* <p>createSpellAnimate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellAnimate(final AbilityFactory af) {
final SpellAbility spAnimate = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -4047747186919390147L;
@Override
public boolean canPlayAI() {
return animateCanPlayAI(af, this);
}
@Override
public void resolve() {
animateResolve(af, this);
}
@Override
public String getStackDescription() {
return animateStackDescription(af, this);
}
};
return spAnimate;
}
/**
* <p>createDrawbackAnimate.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackAnimate(final AbilityFactory af) {
final SpellAbility dbAnimate = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = -8659938411460952874L;
@Override
public void resolve() {
animateResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return animatePlayDrawbackAI(af, this);
}
@Override
public String getStackDescription() {
return animateStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return animateTriggerAI(af, this, mandatory);
}
};
return dbAnimate;
}
/**
* <p>animateStackDescription.</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 animateStackDescription(final AbilityFactory af, SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
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);
boolean permanent = params.containsKey("Permanent") ? true : false;
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++) {
String k = keywords.get(i);
if (svars.containsKey(k)) {
keywords.add("\"" + k + "\"");
keywords.remove(k);
}
}
ArrayList<String> colors = new ArrayList<String>();
if (params.containsKey("Colors")) colors.addAll(Arrays.asList(params.get("Colors").split(",")));
StringBuilder sb = new StringBuilder();
if (sa instanceof Ability_Sub)
sb.append(" ");
else
sb.append(sa.getSourceCard().getName()).append(" - ");
Target tgt = af.getAbTgt();
ArrayList<Card> tgts;
if (tgt != null)
tgts = tgt.getTargetCards();
else
tgts = AbilityFactory.getDefinedCards(sa.getSourceCard(), params.get("Defined"), sa);
for (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(" ");
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 sb.append(" until end of turn.");
} else sb.append(".");
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null)
sb.append(abSub.getStackDescription());
return sb.toString();
}//end animateStackDescription()
/**
* <p>animateCanPlayAI.</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 animateCanPlayAI(final AbilityFactory af, SpellAbility sa) {
if (!ComputerUtil.canPayCost(sa))
return false;
HashMap<String, String> params = af.getMapParams();
Target tgt = af.getAbTgt();
Card source = sa.getSourceCard();
boolean useAbility = true;
//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 animate abilities outside computers Combat_Begin step
if (!AllZone.getPhase().is(Constant.Phase.Combat_Begin) && AllZone.getPhase().isPlayerTurn(AllZone.getComputerPlayer())
&& !AbilityFactory.isSorcerySpeed(sa) && !params.containsKey("ActivatingPhases")
&& !params.containsKey("Permanent"))
return false;
//don't use instant speed animate abilities outside humans Combat_Declare_Attackers_InstantAbility step
if ((!AllZone.getPhase().is(Constant.Phase.Combat_Declare_Attackers_InstantAbility)
|| AllZone.getCombat().getAttackers().length == 0)
&& AllZone.getPhase().isPlayerTurn(AllZone.getHumanPlayer()))
return false;
//don't activate during main2 unless this effect is permanent
if (AllZone.getPhase().is(Constant.Phase.Main2) && !params.containsKey("Permanent"))
return false;
if (null == tgt) {
ArrayList<Card> defined = AbilityFactory.getDefinedCards(source, params.get("Defined"), sa);
boolean bFlag = false;
for (Card c : defined) {
bFlag |= (!c.isCreature() && !c.isTapped() && !(c.getTurnInZone() == AllZone.getPhase().getTurn()));
}
if (!bFlag) // All of the defined stuff is animated, not very useful
return false;
} else {
tgt.resetTargets();
useAbility &= animateTgtAI(af, sa);
}
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
useAbility &= subAb.chkAI_Drawback();
return useAbility;
}// end animateCanPlayAI()
/**
* <p>animatePlayDrawbackAI.</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 animatePlayDrawbackAI(final AbilityFactory af, SpellAbility sa) {
// AI should only activate this during Human's turn
boolean chance = animateTgtAI(af, sa);
// TODO: restrict the subAbility a bit
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance;
}
/**
* <p>animateTriggerAI.</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 animateTriggerAI(final AbilityFactory af, SpellAbility sa, boolean mandatory) {
if (!ComputerUtil.canPayCost(sa)) // If there is a cost payment
return false;
boolean chance = animateTgtAI(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
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance || mandatory;
}
/**
* <p>animateTgtAI.</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 animateTgtAI(AbilityFactory af, SpellAbility sa) {
//This is reasonable for now. Kamahl, Fist of Krosa and a sorcery or two are the only things
//that animate 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>animateResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void animateResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card source = sa.getSourceCard();
Card host = af.getHostCard();
Map<String, String> svars = host.getSVars();
long timest = -1;
//AF specific params
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);
if (power != -1 || toughness != -1)
timest = AllZone.getNextTimestamp();
final long timestamp = timest;
boolean permanent = params.containsKey("Permanent") ? true : false;
final ArrayList<String> types = new ArrayList<String>();
if (params.containsKey("Types")) types.addAll(Arrays.asList(params.get("Types").split(",")));
//allow ChosenType - overrides anything else specified
if (types.contains("ChosenType")) {
types.clear();
types.add(host.getChosenType());
}
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++) {
String k = keywords.get(i);
if (svars.containsKey(k)) {
keywords.add(svars.get(k));
keywords.remove(k);
}
}
//colors to be added or changed to
String tmpDesc = "";
if (params.containsKey("Colors")) {
String colors = params.get("Colors");
if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(host.getChosenColor().split(","))));
} else {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(","))));
}
}
final String finalDesc = tmpDesc;
//abilities to add to the animated being
ArrayList<String> abilities = new ArrayList<String>();
if (params.containsKey("Abilities")) abilities.addAll(Arrays.asList(params.get("Abilities").split(",")));
//triggers to add to the animated being
ArrayList<String> triggers = new ArrayList<String>();
if (params.containsKey("Triggers")) triggers.addAll(Arrays.asList(params.get("Triggers").split(",")));
//static abilities to add to the animated being
ArrayList<String> stAbs = new ArrayList<String>();
if (params.containsKey("staticAbilities")) stAbs.addAll(Arrays.asList(params.get("staticAbilities").split(",")));
Target tgt = af.getAbTgt();
ArrayList<Card> tgts;
if (tgt != null)
tgts = tgt.getTargetCards();
else
tgts = AbilityFactory.getDefinedCards(source, params.get("Defined"), sa);
for (final Card c : tgts) {
//final ArrayList<Card_Color> originalColors = c.getColor();
final ArrayList<String> originalTypes = c.getType();
final long colorTimestamp = doAnimate(c, af, power, toughness, types, finalDesc, keywords, timestamp);
//give abilities
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
if (abilities.size() > 0) {
for (String s : abilities) {
AbilityFactory newAF = new AbilityFactory();
String actualAbility = host.getSVar(s);
SpellAbility grantedAbility = newAF.getAbility(actualAbility, c);
addedAbilities.add(grantedAbility);
c.addSpellAbility(grantedAbility);
}
}
//Grant triggers
final ArrayList<Trigger> addedTriggers = new ArrayList<Trigger>();
if (triggers.size() > 0) {
for (String s : triggers) {
String actualTrigger = host.getSVar(s);
Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c);
addedTriggers.add(c.addTrigger(parsedTrigger));
AllZone.getTriggerHandler().registerTrigger(parsedTrigger);
}
}
//give static abilities (should only be used by cards to give itself a static ability)
if (stAbs.size() > 0) {
for (String s : stAbs) {
String actualAbility = host.getSVar(s);
c.addStaticAbility(actualAbility);
}
}
final boolean givesStAbs = (stAbs.size() > 0);
final Command unanimate = new Command() {
private static final long serialVersionUID = -5861759814760561373L;
public void execute() {
doUnanimate(c, af, originalTypes, finalDesc, keywords, addedAbilities, addedTriggers, colorTimestamp, givesStAbs, timestamp);
}
};
if (!permanent) {
if (params.containsKey("UntilEndOfCombat")) AllZone.getEndOfCombat().addUntil(unanimate);
else if(params.containsKey("UntilHostLeavesPlay")) {
host.addLeavesPlayCommand(unanimate);
}
else AllZone.getEndOfTurn().addUntil(unanimate);
}
}
}//animateResolve
/**
* <p>doAnimate.</p>
*
* @param c a {@link forge.Card} object.
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param power a int.
* @param toughness a int.
* @param types a {@link java.util.ArrayList} object.
* @param colors a {@link java.lang.String} object.
* @param keywords a {@link java.util.ArrayList} object.
* @return a long.
*/
private static long doAnimate(Card c, AbilityFactory af, int power, int toughness, ArrayList<String> types, String colors,
ArrayList<String> keywords, long timestamp) {
HashMap<String, String> params = af.getMapParams();
if (power != -1 || toughness != -1)
c.addNewPT(power, toughness, timestamp);
if (power != -1) c.setBaseAttack(power);
if (toughness != -1) c.setBaseDefense(toughness);
ArrayList<String> supertypes = new ArrayList<String>();
if (params.containsKey("KeepSupertypes")) {
for (String t : c.getType()) {
if (CardUtil.isASuperType(t)) supertypes.add(t);
}
}
ArrayList<String> cardtypes = new ArrayList<String>();
if (params.containsKey("KeepCardTypes")) {
for (String t : c.getType()) {
if (CardUtil.isACardType(t)) cardtypes.add(t);
}
}
if (params.containsKey("OverwriteTypes")) c.clearAllTypes();
types.addAll(supertypes);
types.addAll(cardtypes);
for (String r : types) {
// if the card doesn't have that type, add it
if (!c.isType(r))
c.addType(r);
}
for (String k : keywords) {
if (k.startsWith("HIDDEN"))
c.addExtrinsicKeyword(k);
//this maybe should just blindly add since multiple instances of a keyword sometimes have effects
//practically, this shouldn't matter though, and will display more cleanly
else if (!c.getIntrinsicKeyword().contains(k) || CardUtil.isStackingKeyword(k))
c.addIntrinsicKeyword(k);
}
long colorTimestamp = c.addColor(colors, c, !params.containsKey("OverwriteColors"), true);
return colorTimestamp;
}
/**
* <p>doUnanimate.</p>
*
* @param c a {@link forge.Card} object.
* @param originalPower a int.
* @param originalToughness a int.
* @param originalTypes a {@link java.util.ArrayList} object.
* @param colorDesc a {@link java.lang.String} object.
* @param originalKeywords a {@link java.util.ArrayList} object.
* @param addedAbilities a {@link java.util.ArrayList} object.
* @param addedTriggers a {@link java.util.ArrayList} object.
* @param timestamp a long.
*/
private static void doUnanimate(Card c, AbilityFactory af, ArrayList<String> originalTypes, String colorDesc,
ArrayList<String> originalKeywords, ArrayList<SpellAbility> addedAbilities, ArrayList<Trigger> addedTriggers,
long colorTimestamp, boolean givesStAbs, long timestamp) {
HashMap<String, String> params = af.getMapParams();
c.removeNewPT(timestamp);
c.clearAllTypes();
//remove all static abilities
if (givesStAbs)
c.setStaticAbilities(new ArrayList<StaticAbility>());
for (String type : originalTypes) {
c.addType(type);
}
c.removeColor(colorDesc, c, !params.containsKey("OverwriteColors"), colorTimestamp);
for (String k : originalKeywords) {
if (k.startsWith("HIDDEN"))
c.removeExtrinsicKeyword(k);
//TODO - may want to look at saving off intrinsic and extrinsic separately and add back that way
c.removeIntrinsicKeyword(k);
}
for (SpellAbility sa : addedAbilities) {
c.removeSpellAbility(sa);
}
for (Trigger t : addedTriggers) {
AllZone.getTriggerHandler().removeRegisteredTrigger(t);
c.removeTrigger(t);
}
//any other unanimate cleanup
if (!c.isCreature()) c.unEquipAllCards();
}
//**************************************************************
// ************************ AnimateAll *************************
//**************************************************************
/**
* <p>createAbilityAnimateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createAbilityAnimateAll(final AbilityFactory af) {
final SpellAbility abAnimateAll = new Ability_Activated(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = -4969632476557290609L;
@Override
public boolean canPlayAI() {
return animateAllCanPlayAI(af, this);
}
@Override
public void resolve() {
animateAllResolve(af, this);
}
@Override
public String getStackDescription() {
return animateAllStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return animateAllTriggerAI(af, this, mandatory);
}
};
return abAnimateAll;
}
/**
* <p>createSpellAnimateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createSpellAnimateAll(final AbilityFactory af) {
final SpellAbility spAnimateAll = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
private static final long serialVersionUID = 2946847609068706237L;
@Override
public boolean canPlayAI() {
return animateAllCanPlayAI(af, this);
}
@Override
public void resolve() {
animateAllResolve(af, this);
}
@Override
public String getStackDescription() {
return animateAllStackDescription(af, this);
}
};
return spAnimateAll;
}
/**
* <p>createDrawbackAnimateAll.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @return a {@link forge.card.spellability.SpellAbility} object.
*/
public static SpellAbility createDrawbackAnimateAll(final AbilityFactory af) {
final SpellAbility dbAnimateAll = new Ability_Sub(af.getHostCard(), af.getAbTgt()) {
private static final long serialVersionUID = 2056843302051205632L;
@Override
public void resolve() {
animateAllResolve(af, this);
}
@Override
public boolean chkAI_Drawback() {
return animateAllPlayDrawbackAI(af, this);
}
@Override
public String getStackDescription() {
return animateAllStackDescription(af, this);
}
@Override
public boolean doTrigger(boolean mandatory) {
return animateAllTriggerAI(af, this, mandatory);
}
};
return dbAnimateAll;
}
/**
* <p>animateAllStackDescription.</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 animateAllStackDescription(final AbilityFactory af, SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
StringBuilder sb = new StringBuilder();
if (sa instanceof Ability_Sub)
sb.append(" ");
else
sb.append(sa.getSourceCard()).append(" - ");
String desc = "";
if (params.containsKey("SpellDescription")) {
desc = params.get("SpellDescription");
} else {
desc = "Animate all valid cards.";
}
sb.append(desc);
Ability_Sub abSub = sa.getSubAbility();
if (abSub != null)
sb.append(abSub.getStackDescription());
return sb.toString();
}
/**
* <p>animateAllCanPlayAI.</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 animateAllCanPlayAI(final AbilityFactory af, SpellAbility sa) {
boolean useAbility = false;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
useAbility &= subAb.chkAI_Drawback();
return useAbility;
}// end animateAllCanPlayAI()
/**
* <p>animateAllPlayDrawbackAI.</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 animateAllPlayDrawbackAI(final AbilityFactory af, SpellAbility sa) {
boolean chance = false;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance;
}
/**
* <p>animateAllTriggerAI.</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 animateAllTriggerAI(final AbilityFactory af, SpellAbility sa, boolean mandatory) {
if (!ComputerUtil.canPayCost(sa)) // If there is a cost payment
return false;
boolean chance = false;
Ability_Sub subAb = sa.getSubAbility();
if (subAb != null)
chance &= subAb.chkAI_Drawback();
return chance || mandatory;
}
/**
* <p>animateAllResolve.</p>
*
* @param af a {@link forge.card.abilityFactory.AbilityFactory} object.
* @param sa a {@link forge.card.spellability.SpellAbility} object.
*/
private static void animateAllResolve(final AbilityFactory af, final SpellAbility sa) {
HashMap<String, String> params = af.getMapParams();
Card host = af.getHostCard();
Map<String, String> svars = host.getSVars();
long timest = -1;
//AF specific params
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);
if (power != -1 || toughness != -1)
timest = AllZone.getNextTimestamp();
final long timestamp = timest;
boolean permanent = params.containsKey("Permanent") ? true : false;
final ArrayList<String> types = new ArrayList<String>();
if (params.containsKey("Types")) types.addAll(Arrays.asList(params.get("Types").split(",")));
//allow ChosenType - overrides anything else specified
if (types.contains("ChosenType")) {
types.clear();
types.add(host.getChosenType());
}
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++) {
String k = keywords.get(i);
if (svars.containsKey(k)) {
keywords.add(svars.get(k));
keywords.remove(k);
}
}
//colors to be added or changed to
String tmpDesc = "";
if (params.containsKey("Colors")) {
String colors = params.get("Colors");
if (colors.equals("ChosenColor")) {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(host.getChosenColor().split(","))));
} else {
tmpDesc = CardUtil.getShortColorsString(new ArrayList<String>(Arrays.asList(colors.split(","))));
}
}
final String finalDesc = tmpDesc;
//abilities to add to the animated being
ArrayList<String> abilities = new ArrayList<String>();
if (params.containsKey("Abilities")) abilities.addAll(Arrays.asList(params.get("Abilities").split(",")));
//triggers to add to the animated being
ArrayList<String> triggers = new ArrayList<String>();
if (params.containsKey("Triggers")) triggers.addAll(Arrays.asList(params.get("Triggers").split(",")));
String valid = "";
if (params.containsKey("ValidCards"))
valid = params.get("ValidCards");
CardList list = AllZoneUtil.getCardsInPlay();
list = list.getValidCards(valid.split(","), host.getController(), host);
for (final Card c : list) {
final ArrayList<String> originalTypes = c.getType();
final long colorTimestamp = doAnimate(c, af, power, toughness, types, finalDesc, keywords, timestamp);
//give abilities
final ArrayList<SpellAbility> addedAbilities = new ArrayList<SpellAbility>();
if (abilities.size() > 0) {
for (String s : abilities) {
AbilityFactory newAF = new AbilityFactory();
String actualAbility = host.getSVar(s);
SpellAbility grantedAbility = newAF.getAbility(actualAbility, c);
addedAbilities.add(grantedAbility);
c.addSpellAbility(grantedAbility);
}
}
//Grant triggers
final ArrayList<Trigger> addedTriggers = new ArrayList<Trigger>();
if (triggers.size() > 0) {
for (String s : triggers) {
String actualTrigger = host.getSVar(s);
Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, c);
addedTriggers.add(c.addTrigger(parsedTrigger));
AllZone.getTriggerHandler().registerTrigger(parsedTrigger);
}
}
final Command unanimate = new Command() {
private static final long serialVersionUID = -5861759814760561373L;
public void execute() {
doUnanimate(c, af, originalTypes, finalDesc, keywords, addedAbilities, addedTriggers, colorTimestamp, false, timestamp);
}
};
if (!permanent) {
if (params.containsKey("UntilEndOfCombat")) AllZone.getEndOfCombat().addUntil(unanimate);
else AllZone.getEndOfTurn().addUntil(unanimate);
}
}
}//animateAllResolve
}//end class AbilityFactory_Animate