diff --git a/.gitattributes b/.gitattributes
index 1a49bfdc94f..af3972c64a1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -12474,7 +12474,6 @@ src/main/java/forge/card/abilityfactory/AbilityFactoryDealDamage.java svneol=nat
src/main/java/forge/card/abilityfactory/AbilityFactoryDebuff.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryDelayedTrigger.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryDestroy.java svneol=native#text/plain
-src/main/java/forge/card/abilityfactory/AbilityFactoryEffect.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryEndGameCondition.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryGainControl.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/AbilityFactoryMana.java svneol=native#text/plain
@@ -12507,6 +12506,7 @@ src/main/java/forge/card/abilityfactory/ai/DamagePreventAllAi.java -text
src/main/java/forge/card/abilityfactory/ai/DiscardAi.java -text
src/main/java/forge/card/abilityfactory/ai/DrainManaAi.java -text
src/main/java/forge/card/abilityfactory/ai/DrawAi.java svneol=native#text/plain
+src/main/java/forge/card/abilityfactory/ai/EffectAi.java -text
src/main/java/forge/card/abilityfactory/ai/EndTurnAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeExchangeAi.java -text
src/main/java/forge/card/abilityfactory/ai/LifeGainAi.java -text
@@ -12534,6 +12534,7 @@ src/main/java/forge/card/abilityfactory/effects/DamagePreventEffect.java -text
src/main/java/forge/card/abilityfactory/effects/DiscardEffect.java -text
src/main/java/forge/card/abilityfactory/effects/DrainManaEffect.java -text
src/main/java/forge/card/abilityfactory/effects/DrawEffect.java -text
+src/main/java/forge/card/abilityfactory/effects/EffectEffect.java -text
src/main/java/forge/card/abilityfactory/effects/EndTurnEffect.java -text
src/main/java/forge/card/abilityfactory/effects/HelperAnimate.java svneol=native#text/plain
src/main/java/forge/card/abilityfactory/effects/LifeExchangeEffect.java -text
diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactory.java b/src/main/java/forge/card/abilityfactory/AbilityFactory.java
index f86b11c3746..7b65a41003d 100644
--- a/src/main/java/forge/card/abilityfactory/AbilityFactory.java
+++ b/src/main/java/forge/card/abilityfactory/AbilityFactory.java
@@ -723,13 +723,8 @@ public class AbilityFactory {
}
else if (this.api.equals("Effect")) {
- if (this.isAb) {
- spellAbility = AbilityFactoryEffect.createAbilityEffect(this);
- } else if (this.isSp) {
- spellAbility = AbilityFactoryEffect.createSpellEffect(this);
- } else if (this.isDb) {
- spellAbility = AbilityFactoryEffect.createDrawbackEffect(this);
- }
+ ai = new EffectAi();
+ se = new EffectEffect();
}
else if (this.api.equals("EndTurn")) {
diff --git a/src/main/java/forge/card/abilityfactory/AbilityFactoryEffect.java b/src/main/java/forge/card/abilityfactory/AbilityFactoryEffect.java
deleted file mode 100644
index 45c20d8c5ff..00000000000
--- a/src/main/java/forge/card/abilityfactory/AbilityFactoryEffect.java
+++ /dev/null
@@ -1,594 +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 .
- */
-package forge.card.abilityfactory;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Random;
-
-import com.google.common.base.Predicate;
-
-import forge.Card;
-
-import forge.CardLists;
-import forge.Command;
-import forge.Singletons;
-import forge.card.cardfactory.CardFactoryUtil;
-import forge.card.cost.Cost;
-import forge.card.replacement.ReplacementEffect;
-import forge.card.replacement.ReplacementHandler;
-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.card.trigger.TriggerType;
-import forge.game.GameState;
-import forge.game.phase.CombatUtil;
-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;
-
-
-/**
- *
- * AbilityFactoryEffect class.
- *
- *
- * @author Forge
- * @version $Id$
- */
-public class AbilityFactoryEffect {
- /**
- *
- * createAbilityEffect.
- *
- *
- * @param abilityFactory
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createAbilityEffect(final AbilityFactory abilityFactory) {
- class AbilityEffect extends AbilityActivated {
- public AbilityEffect(final Card ca, final Cost co, final Target t) {
- super(ca, co, t);
- }
-
- @Override
- public AbilityActivated getCopy() {
- AbilityActivated res = new AbilityEffect(getSourceCard(),
- getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 8869422603616247307L;
-
- private final AbilityFactory af = abilityFactory;
-
- @Override
- public String getStackDescription() {
- // when getStackDesc is called, just build exactly what is
- // happening
- return AbilityFactoryEffect.effectStackDescription(this.af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryEffect.effectCanPlayAI(getActivatingPlayer(), this.af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryEffect.effectResolve(this.af, this);
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryEffect.effectDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
- }
- }
- final SpellAbility abEffect = new AbilityEffect(abilityFactory.getHostCard(), abilityFactory.getAbCost(),
- abilityFactory.getAbTgt());
-
- return abEffect;
- }
-
- /**
- *
- * createSpellEffect.
- *
- *
- * @param abilityFactory
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createSpellEffect(final AbilityFactory abilityFactory) {
- final SpellAbility spEffect = new Spell(abilityFactory.getHostCard(), abilityFactory.getAbCost(),
- abilityFactory.getAbTgt()) {
- private static final long serialVersionUID = 6631124959690157874L;
-
- private final AbilityFactory af = abilityFactory;
-
- @Override
- public String getStackDescription() {
- // when getStackDesc is called, just build exactly what is
- // happening
- return AbilityFactoryEffect.effectStackDescription(this.af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryEffect.effectCanPlayAI(getActivatingPlayer(), this.af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryEffect.effectResolve(this.af, this);
- }
-
- };
- return spEffect;
- }
-
- /**
- *
- * createDrawbackEffect.
- *
- *
- * @param abilityFactory
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @return a {@link forge.card.spellability.SpellAbility} object.
- */
- public static SpellAbility createDrawbackEffect(final AbilityFactory abilityFactory) {
- class DrawbackEffect extends AbilitySub {
- public DrawbackEffect(final Card ca, final Target t) {
- super(ca, t);
- }
-
- @Override
- public AbilitySub getCopy() {
- AbilitySub res = new DrawbackEffect(getSourceCard(),
- getTarget() == null ? null : new Target(getTarget()));
- CardFactoryUtil.copySpellAbility(this, res);
- return res;
- }
-
- private static final long serialVersionUID = 6631124959690157874L;
-
- private final AbilityFactory af = abilityFactory;
-
- @Override
- public String getStackDescription() {
- // when getStackDesc is called, just build exactly what is
- // happening
- return AbilityFactoryEffect.effectStackDescription(this.af, this);
- }
-
- @Override
- public boolean canPlayAI() {
- return AbilityFactoryEffect.effectCanPlayAI(getActivatingPlayer(), this.af, this);
- }
-
- @Override
- public void resolve() {
- AbilityFactoryEffect.effectResolve(this.af, this);
- }
-
- @Override
- public boolean chkAIDrawback() {
- return true;
- }
-
- @Override
- public boolean doTrigger(final boolean mandatory) {
- return AbilityFactoryEffect.effectDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
- }
- }
- final SpellAbility dbEffect = new DrawbackEffect(abilityFactory.getHostCard(), abilityFactory.getAbTgt());
-
- return dbEffect;
- }
-
- /**
- *
- * effectStackDescription.
- *
- *
- * @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.
- */
- public static String effectStackDescription(final AbilityFactory af, final SpellAbility sa) {
- final StringBuilder sb = new StringBuilder();
-
- if (sa instanceof AbilitySub) {
- sb.append(" ");
- } else {
- sb.append(sa.getSourceCard().getName()).append(" - ");
- }
-
- sb.append(sa.getDescription());
-
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- sb.append(abSub.getStackDescription());
- }
-
- return sb.toString();
- }
-
- /**
- *
- * effectCanPlayAI.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @param sa
- * a {@link forge.card.spellability.SpellAbility} object.
- * @return a boolean.
- */
- public static boolean effectCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
- final GameState game = Singletons.getModel().getGame();
- final Random r = MyRandom.getRandom();
- final HashMap params = af.getMapParams();
- boolean randomReturn = r.nextFloat() <= .6667;
- final Player opp = ai.getOpponent();
- String logic = "";
-
- if (params.containsKey("AILogic")) {
- logic = params.get("AILogic");
- final PhaseHandler phase = game.getPhaseHandler();
- if (logic.equals("BeginningOfOppTurn")) {
- if (phase.isPlayerTurn(ai.getOpponent()) || phase.getPhase().isAfter(PhaseType.DRAW)) {
- return false;
- }
- randomReturn = true;
- } else if (logic.equals("Fog")) {
- if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
- return false;
- }
- if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
- return false;
- }
- if (game.getStack().size() != 0) {
- return false;
- }
- if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
- return false;
- }
- if (!CombatUtil.lifeInDanger(ai, game.getCombat())) {
- return false;
- }
- final Target tgt = sa.getTarget();
- if (tgt != null) {
- tgt.resetTargets();
- List list = game.getCombat().getAttackerList();
- list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
- list = CardLists.getTargetableCards(list, sa);
- Card target = CardFactoryUtil.getBestCreatureAI(list);
- if (target == null) {
- return false;
- }
- tgt.addTarget(target);
- }
- randomReturn = true;
- } else if (logic.equals("Always")) {
- randomReturn = true;
- } else if (logic.equals("Evasion")) {
- List comp = ai.getCreaturesInPlay();
- List human = opp.getCreaturesInPlay();
-
- // only count creatures that can attack or block
- comp = CardLists.filter(comp, new Predicate() {
- @Override
- public boolean apply(final Card c) {
- return CombatUtil.canAttack(c, opp);
- }
- });
- human = CardLists.filter(human, new Predicate() {
- @Override
- public boolean apply(final Card c) {
- return CombatUtil.canBlock(c);
- }
- });
- if (comp.size() < 2 || human.size() < 1) {
- randomReturn = false;
- }
- }
- } else { //no AILogic
- return false;
- }
-
- final String stackable = params.get("Stackable");
-
- if ((stackable != null) && stackable.equals("False")) {
- String name = params.get("Name");
- if (name == null) {
- name = sa.getSourceCard().getName() + "'s Effect";
- }
- final List list = sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield, name);
- if (list.size() != 0) {
- return false;
- }
- }
-
- final Target tgt = sa.getTarget();
- if (tgt != null && tgt.canTgtPlayer()) {
- tgt.resetTargets();
- if (tgt.canOnlyTgtOpponent() || logic.equals("BeginningOfOppTurn")) {
- tgt.addTarget(ai.getOpponent());
- } else {
- tgt.addTarget(ai);
- }
- }
-
- final AbilitySub subAb = sa.getSubAbility();
- if (subAb != null) {
- randomReturn &= subAb.chkAIDrawback();
- }
-
- return randomReturn;
- }
-
- /**
- *
- * effectDoTriggerAI.
- *
- *
- * @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.
- */
- public static boolean effectDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
- if (!ComputerUtil.canPayCost(sa, ai) && !mandatory) {
- // payment it's usually
- // not mandatory
- return false;
- }
-
- // TODO: Add targeting effects
-
- // check SubAbilities DoTrigger?
- final AbilitySub abSub = sa.getSubAbility();
- if (abSub != null) {
- return abSub.doTrigger(mandatory);
- }
-
- return true;
- }
-
- /**
- *
- * effectResolve.
- *
- *
- * @param af
- * a {@link forge.card.abilityfactory.AbilityFactory} object.
- * @param sa
- * a {@link forge.card.spellability.SpellAbility} object.
- */
- public static void effectResolve(final AbilityFactory af, final SpellAbility sa) {
- final HashMap params = af.getMapParams();
- final Card card = af.getHostCard();
-
- String[] effectAbilities = null;
- String[] effectTriggers = null;
- String[] effectSVars = null;
- String[] effectKeywords = null;
- String[] effectStaticAbilities = null;
- String[] effectReplacementEffects = null;
- String effectRemembered = null;
- String effectImprinted = null;
- Player ownerEff = null;
-
- if (params.containsKey("Abilities")) {
- effectAbilities = params.get("Abilities").split(",");
- }
-
- if (params.containsKey("Triggers")) {
- effectTriggers = params.get("Triggers").split(",");
- }
-
- if (params.containsKey("StaticAbilities")) {
- effectStaticAbilities = params.get("StaticAbilities").split(",");
- }
-
- if (params.containsKey("ReplacementEffects")) {
- effectReplacementEffects = params.get("ReplacementEffects").split(",");
- }
-
- if (params.containsKey("SVars")) {
- effectSVars = params.get("SVars").split(",");
- }
-
- if (params.containsKey("Keywords")) {
- effectKeywords = params.get("Keywords").split(",");
- }
-
- if (params.containsKey("RememberObjects")) {
- effectRemembered = params.get("RememberObjects");
- }
-
- if (params.containsKey("ImprintCards")) {
- effectImprinted = params.get("ImprintCards");
- }
-
- // Effect eff = new Effect();
- String name = params.get("Name");
- if (name == null) {
- name = sa.getSourceCard().getName() + "'s Effect";
- }
-
- // Unique Effects shouldn't be duplicated
- if (params.containsKey("Unique") && Singletons.getModel().getGame().isCardInPlay(name)) {
- return;
- }
-
- if (params.containsKey("EffectOwner")) {
- ArrayList effectOwner;
- effectOwner = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("EffectOwner"), sa);
- ownerEff = effectOwner.get(0);
- }
-
- final Player controller = params.containsKey("EffectOwner") ? ownerEff : sa.getActivatingPlayer();
- final Card eff = new Card();
- eff.setName(name);
- eff.addType("Effect"); // Or Emblem
- eff.setToken(true); // Set token to true, so when leaving play it gets
- // nuked
- eff.addController(controller);
- eff.setOwner(controller);
- eff.setImageName(card.getImageName());
- eff.setColor(card.getColor());
- eff.setImmutable(true);
- eff.setEffectSource(card);
- if (params.containsKey("Image")) {
- eff.setImageName(params.get("Image"));
- }
-
- // Effects should be Orange or something probably
-
- final Card e = eff;
-
- // Abilities, triggers and SVars work the same as they do for Token
- // Grant abilities
- if (effectAbilities != null) {
- for (final String s : effectAbilities) {
- final AbilityFactory abFactory = new AbilityFactory();
- final String actualAbility = af.getHostCard().getSVar(s);
-
- final SpellAbility grantedAbility = abFactory.getAbility(actualAbility, eff);
- eff.addSpellAbility(grantedAbility);
- }
- }
-
- // Grant triggers
- if (effectTriggers != null) {
- for (final String s : effectTriggers) {
- final String actualTrigger = af.getHostCard().getSVar(s);
-
- final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, eff, true);
- eff.addTrigger(parsedTrigger);
- }
- }
-
- // Grant static abilities
- if (effectStaticAbilities != null) {
- for (final String s : effectStaticAbilities) {
- eff.addStaticAbility(af.getHostCard().getSVar(s));
- }
- }
-
- // Grant replacement effects
- if (effectReplacementEffects != null) {
- for (final String s : effectReplacementEffects) {
- final String actualReplacement = af.getHostCard().getSVar(s);
-
- final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, eff);
- eff.addReplacementEffect(parsedReplacement);
- }
- }
-
- // Grant SVars
- if (effectSVars != null) {
- for (final String s : effectSVars) {
- final String actualSVar = af.getHostCard().getSVar(s);
- eff.setSVar(s, actualSVar);
- }
- }
-
- // Grant Keywords
- if (effectKeywords != null) {
- for (final String s : effectKeywords) {
- final String actualKeyword = af.getHostCard().getSVar(s);
- eff.addIntrinsicKeyword(actualKeyword);
- }
- }
-
- // Set Remembered
- if (effectRemembered != null) {
- for (final Object o : AbilityFactory.getDefinedObjects(card, effectRemembered, sa)) {
- eff.addRemembered(o);
- }
- }
-
- // Set Imprinted
- if (effectImprinted != null) {
- for (final Card c : AbilityFactory.getDefinedCards(card, effectImprinted, sa)) {
- eff.addImprinted(c);
- }
- }
-
- // Set Chosen Color(s)
- if (!card.getChosenColor().isEmpty()) {
- eff.setChosenColor(card.getChosenColor());
- }
-
- // Remember created effect
- if (params.containsKey("RememberEffect")) {
- Singletons.getModel().getGame().getCardState(card).addRemembered(eff);
- }
-
- // Duration
- final String duration = params.get("Duration");
- if ((duration == null) || !duration.equals("Permanent")) {
- final Command endEffect = new Command() {
- private static final long serialVersionUID = -5861759814760561373L;
-
- @Override
- public void execute() {
- Singletons.getModel().getGame().getAction().exile(e);
- }
- };
-
- if ((duration == null) || duration.equals("EndOfTurn")) {
- Singletons.getModel().getGame().getEndOfTurn().addUntil(endEffect);
- }
- else if (duration.equals("UntilHostLeavesPlay")) {
- card.addLeavesPlayCommand(endEffect);
- }
- else if (duration.equals("HostLeavesOrEOT")) {
- Singletons.getModel().getGame().getEndOfTurn().addUntil(endEffect);
- card.addLeavesPlayCommand(endEffect);
- }
- else if (duration.equals("UntilYourNextTurn")) {
- Singletons.getModel().getGame().getCleanup().addUntilYourNextTurn(controller, endEffect);
- }
- }
-
- // TODO: Add targeting to the effect so it knows who it's dealing with
- Singletons.getModel().getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone);
- Singletons.getModel().getGame().getAction().moveToPlay(eff);
- Singletons.getModel().getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
- }
-
-} // end class AbilityFactoryEffect
diff --git a/src/main/java/forge/card/abilityfactory/ai/EffectAi.java b/src/main/java/forge/card/abilityfactory/ai/EffectAi.java
new file mode 100644
index 00000000000..cc488a6da8f
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/ai/EffectAi.java
@@ -0,0 +1,164 @@
+package forge.card.abilityfactory.ai;
+
+import java.util.List;
+import java.util.Random;
+
+import com.google.common.base.Predicate;
+
+import forge.Card;
+import forge.CardLists;
+import forge.Singletons;
+import forge.card.abilityfactory.SpellAiLogic;
+import forge.card.cardfactory.CardFactoryUtil;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.spellability.Target;
+import forge.game.GameState;
+import forge.game.phase.CombatUtil;
+import forge.game.phase.PhaseHandler;
+import forge.game.phase.PhaseType;
+import forge.game.player.Player;
+import forge.game.zone.ZoneType;
+import forge.util.MyRandom;
+
+public class EffectAi extends SpellAiLogic {
+ /**
+ *
+ * effectCanPlayAI.
+ *
+ *
+ * @param af
+ * a {@link forge.card.abilityfactory.AbilityFactory} object.
+ * @param sa
+ * a {@link forge.card.spellability.SpellAbility} object.
+ * @return a boolean.
+ */
+ @Override
+ public boolean canPlayAI(Player ai, java.util.Map params, SpellAbility sa) {
+ final GameState game = Singletons.getModel().getGame();
+ final Random r = MyRandom.getRandom();
+ boolean randomReturn = r.nextFloat() <= .6667;
+ final Player opp = ai.getOpponent();
+ String logic = "";
+
+ if (params.containsKey("AILogic")) {
+ logic = params.get("AILogic");
+ final PhaseHandler phase = game.getPhaseHandler();
+ if (logic.equals("BeginningOfOppTurn")) {
+ if (phase.isPlayerTurn(ai.getOpponent()) || phase.getPhase().isAfter(PhaseType.DRAW)) {
+ return false;
+ }
+ randomReturn = true;
+ } else if (logic.equals("Fog")) {
+ if (game.getPhaseHandler().isPlayerTurn(sa.getActivatingPlayer())) {
+ return false;
+ }
+ if (!game.getPhaseHandler().is(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)) {
+ return false;
+ }
+ if (game.getStack().size() != 0) {
+ return false;
+ }
+ if (game.getPhaseHandler().isPreventCombatDamageThisTurn()) {
+ return false;
+ }
+ if (!CombatUtil.lifeInDanger(ai, game.getCombat())) {
+ return false;
+ }
+ final Target tgt = sa.getTarget();
+ if (tgt != null) {
+ tgt.resetTargets();
+ List list = game.getCombat().getAttackerList();
+ list = CardLists.getValidCards(list, tgt.getValidTgts(), sa.getActivatingPlayer(), sa.getSourceCard());
+ list = CardLists.getTargetableCards(list, sa);
+ Card target = CardFactoryUtil.getBestCreatureAI(list);
+ if (target == null) {
+ return false;
+ }
+ tgt.addTarget(target);
+ }
+ randomReturn = true;
+ } else if (logic.equals("Always")) {
+ randomReturn = true;
+ } else if (logic.equals("Evasion")) {
+ List comp = ai.getCreaturesInPlay();
+ List human = opp.getCreaturesInPlay();
+
+ // only count creatures that can attack or block
+ comp = CardLists.filter(comp, new Predicate() {
+ @Override
+ public boolean apply(final Card c) {
+ return CombatUtil.canAttack(c, opp);
+ }
+ });
+ human = CardLists.filter(human, new Predicate() {
+ @Override
+ public boolean apply(final Card c) {
+ return CombatUtil.canBlock(c);
+ }
+ });
+ if (comp.size() < 2 || human.size() < 1) {
+ randomReturn = false;
+ }
+ }
+ } else { //no AILogic
+ return false;
+ }
+
+ final String stackable = params.get("Stackable");
+
+ if ((stackable != null) && stackable.equals("False")) {
+ String name = params.get("Name");
+ if (name == null) {
+ name = sa.getSourceCard().getName() + "'s Effect";
+ }
+ final List list = sa.getActivatingPlayer().getCardsIn(ZoneType.Battlefield, name);
+ if (list.size() != 0) {
+ return false;
+ }
+ }
+
+ final Target tgt = sa.getTarget();
+ if (tgt != null && tgt.canTgtPlayer()) {
+ tgt.resetTargets();
+ if (tgt.canOnlyTgtOpponent() || logic.equals("BeginningOfOppTurn")) {
+ tgt.addTarget(ai.getOpponent());
+ } else {
+ tgt.addTarget(ai);
+ }
+ }
+
+ final AbilitySub subAb = sa.getSubAbility();
+ if (subAb != null) {
+ randomReturn &= subAb.chkAIDrawback();
+ }
+
+ return randomReturn;
+ }
+
+ /**
+ *
+ * effectDoTriggerAI.
+ *
+ *
+ * @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.
+ */
+ @Override
+ public boolean doTriggerAINoCost(Player aiPlayer, java.util.Map params, SpellAbility sa, boolean mandatory) {
+ // TODO: Add targeting effects
+
+ // check SubAbilities DoTrigger?
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ return abSub.doTrigger(mandatory);
+ }
+
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/forge/card/abilityfactory/effects/EffectEffect.java b/src/main/java/forge/card/abilityfactory/effects/EffectEffect.java
new file mode 100644
index 00000000000..e4d1dcb350f
--- /dev/null
+++ b/src/main/java/forge/card/abilityfactory/effects/EffectEffect.java
@@ -0,0 +1,258 @@
+package forge.card.abilityfactory.effects;
+
+import java.util.ArrayList;
+
+import forge.Card;
+import forge.Command;
+import forge.Singletons;
+import forge.card.abilityfactory.AbilityFactory;
+import forge.card.abilityfactory.SpellEffect;
+import forge.card.replacement.ReplacementEffect;
+import forge.card.replacement.ReplacementHandler;
+import forge.card.spellability.AbilitySub;
+import forge.card.spellability.SpellAbility;
+import forge.card.trigger.Trigger;
+import forge.card.trigger.TriggerHandler;
+import forge.card.trigger.TriggerType;
+import forge.game.player.Player;
+
+public class EffectEffect extends SpellEffect {
+
+ /**
+ *
+ * effectStackDescription.
+ *
+ *
+ * @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.
+ */
+ @Override
+ public String getStackDescription(java.util.Map params, SpellAbility sa) {
+ final StringBuilder sb = new StringBuilder();
+
+ if (sa instanceof AbilitySub) {
+ sb.append(" ");
+ } else {
+ sb.append(sa.getSourceCard().getName()).append(" - ");
+ }
+
+ sb.append(sa.getDescription());
+
+ final AbilitySub abSub = sa.getSubAbility();
+ if (abSub != null) {
+ sb.append(abSub.getStackDescription());
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ *
+ * effectResolve.
+ *
+ *
+ * @param af
+ * a {@link forge.card.abilityfactory.AbilityFactory} object.
+ * @param sa
+ * a {@link forge.card.spellability.SpellAbility} object.
+ */
+
+ @Override
+ public void resolve(java.util.Map params, SpellAbility sa) {
+ final Card hostCard = sa.getAbilityFactory().getHostCard();
+
+ String[] effectAbilities = null;
+ String[] effectTriggers = null;
+ String[] effectSVars = null;
+ String[] effectKeywords = null;
+ String[] effectStaticAbilities = null;
+ String[] effectReplacementEffects = null;
+ String effectRemembered = null;
+ String effectImprinted = null;
+ Player ownerEff = null;
+
+ if (params.containsKey("Abilities")) {
+ effectAbilities = params.get("Abilities").split(",");
+ }
+
+ if (params.containsKey("Triggers")) {
+ effectTriggers = params.get("Triggers").split(",");
+ }
+
+ if (params.containsKey("StaticAbilities")) {
+ effectStaticAbilities = params.get("StaticAbilities").split(",");
+ }
+
+ if (params.containsKey("ReplacementEffects")) {
+ effectReplacementEffects = params.get("ReplacementEffects").split(",");
+ }
+
+ if (params.containsKey("SVars")) {
+ effectSVars = params.get("SVars").split(",");
+ }
+
+ if (params.containsKey("Keywords")) {
+ effectKeywords = params.get("Keywords").split(",");
+ }
+
+ if (params.containsKey("RememberObjects")) {
+ effectRemembered = params.get("RememberObjects");
+ }
+
+ if (params.containsKey("ImprintCards")) {
+ effectImprinted = params.get("ImprintCards");
+ }
+
+ // Effect eff = new Effect();
+ String name = params.get("Name");
+ if (name == null) {
+ name = sa.getSourceCard().getName() + "'s Effect";
+ }
+
+ // Unique Effects shouldn't be duplicated
+ if (params.containsKey("Unique") && Singletons.getModel().getGame().isCardInPlay(name)) {
+ return;
+ }
+
+ if (params.containsKey("EffectOwner")) {
+ ArrayList effectOwner;
+ effectOwner = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("EffectOwner"), sa);
+ ownerEff = effectOwner.get(0);
+ }
+
+ final Player controller = params.containsKey("EffectOwner") ? ownerEff : sa.getActivatingPlayer();
+ final Card eff = new Card();
+ eff.setName(name);
+ eff.addType("Effect"); // Or Emblem
+ eff.setToken(true); // Set token to true, so when leaving play it gets
+ // nuked
+ eff.addController(controller);
+ eff.setOwner(controller);
+ eff.setImageName(hostCard.getImageName());
+ eff.setColor(hostCard.getColor());
+ eff.setImmutable(true);
+ eff.setEffectSource(hostCard);
+ if (params.containsKey("Image")) {
+ eff.setImageName(params.get("Image"));
+ }
+
+ // Effects should be Orange or something probably
+
+ final Card e = eff;
+
+ // Abilities, triggers and SVars work the same as they do for Token
+ // Grant abilities
+ if (effectAbilities != null) {
+ for (final String s : effectAbilities) {
+ final AbilityFactory abFactory = new AbilityFactory();
+ final String actualAbility = hostCard.getSVar(s);
+
+ final SpellAbility grantedAbility = abFactory.getAbility(actualAbility, eff);
+ eff.addSpellAbility(grantedAbility);
+ }
+ }
+
+ // Grant triggers
+ if (effectTriggers != null) {
+ for (final String s : effectTriggers) {
+ final String actualTrigger = hostCard.getSVar(s);
+
+ final Trigger parsedTrigger = TriggerHandler.parseTrigger(actualTrigger, eff, true);
+ eff.addTrigger(parsedTrigger);
+ }
+ }
+
+ // Grant static abilities
+ if (effectStaticAbilities != null) {
+ for (final String s : effectStaticAbilities) {
+ eff.addStaticAbility(hostCard.getSVar(s));
+ }
+ }
+
+ // Grant replacement effects
+ if (effectReplacementEffects != null) {
+ for (final String s : effectReplacementEffects) {
+ final String actualReplacement = hostCard.getSVar(s);
+
+ final ReplacementEffect parsedReplacement = ReplacementHandler.parseReplacement(actualReplacement, eff);
+ eff.addReplacementEffect(parsedReplacement);
+ }
+ }
+
+ // Grant SVars
+ if (effectSVars != null) {
+ for (final String s : effectSVars) {
+ final String actualSVar = hostCard.getSVar(s);
+ eff.setSVar(s, actualSVar);
+ }
+ }
+
+ // Grant Keywords
+ if (effectKeywords != null) {
+ for (final String s : effectKeywords) {
+ final String actualKeyword = hostCard.getSVar(s);
+ eff.addIntrinsicKeyword(actualKeyword);
+ }
+ }
+
+ // Set Remembered
+ if (effectRemembered != null) {
+ for (final Object o : AbilityFactory.getDefinedObjects(hostCard, effectRemembered, sa)) {
+ eff.addRemembered(o);
+ }
+ }
+
+ // Set Imprinted
+ if (effectImprinted != null) {
+ for (final Card c : AbilityFactory.getDefinedCards(hostCard, effectImprinted, sa)) {
+ eff.addImprinted(c);
+ }
+ }
+
+ // Set Chosen Color(s)
+ if (!hostCard.getChosenColor().isEmpty()) {
+ eff.setChosenColor(hostCard.getChosenColor());
+ }
+
+ // Remember created effect
+ if (params.containsKey("RememberEffect")) {
+ Singletons.getModel().getGame().getCardState(hostCard).addRemembered(eff);
+ }
+
+ // Duration
+ final String duration = params.get("Duration");
+ if ((duration == null) || !duration.equals("Permanent")) {
+ final Command endEffect = new Command() {
+ private static final long serialVersionUID = -5861759814760561373L;
+
+ @Override
+ public void execute() {
+ Singletons.getModel().getGame().getAction().exile(e);
+ }
+ };
+
+ if ((duration == null) || duration.equals("EndOfTurn")) {
+ Singletons.getModel().getGame().getEndOfTurn().addUntil(endEffect);
+ }
+ else if (duration.equals("UntilHostLeavesPlay")) {
+ hostCard.addLeavesPlayCommand(endEffect);
+ }
+ else if (duration.equals("HostLeavesOrEOT")) {
+ Singletons.getModel().getGame().getEndOfTurn().addUntil(endEffect);
+ hostCard.addLeavesPlayCommand(endEffect);
+ }
+ else if (duration.equals("UntilYourNextTurn")) {
+ Singletons.getModel().getGame().getCleanup().addUntilYourNextTurn(controller, endEffect);
+ }
+ }
+
+ // TODO: Add targeting to the effect so it knows who it's dealing with
+ Singletons.getModel().getGame().getTriggerHandler().suppressMode(TriggerType.ChangesZone);
+ Singletons.getModel().getGame().getAction().moveToPlay(eff);
+ Singletons.getModel().getGame().getTriggerHandler().clearSuppression(TriggerType.ChangesZone);
+ }
+
+} // end class AbilityFactoryEffect
\ No newline at end of file