mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-16 10:48:00 +00:00
AF: Cleanup, StoreSVar, Unattach
This commit is contained in:
9
.gitattributes
vendored
9
.gitattributes
vendored
@@ -12463,8 +12463,7 @@ src/main/java/forge/card/abilityfactory/AbilityFactory.java svneol=native#text/p
|
|||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryAttach.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryAttach.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryChangeZone.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryChangeZone.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCharm.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/AbilityFactoryCharm.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryCleanup.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/CleanUpEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/AbilityFactoryStoreSVar.java -text
|
|
||||||
src/main/java/forge/card/abilityfactory/CommonAbility.java -text
|
src/main/java/forge/card/abilityfactory/CommonAbility.java -text
|
||||||
src/main/java/forge/card/abilityfactory/CommonDrawback.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/CommonDrawback.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/CommonSpell.java -text
|
src/main/java/forge/card/abilityfactory/CommonSpell.java -text
|
||||||
@@ -12477,6 +12476,7 @@ src/main/java/forge/card/abilityfactory/ai/AnimateAllAi.java -text
|
|||||||
src/main/java/forge/card/abilityfactory/ai/BondAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/BondAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/CanPlayAsDrawbackAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/CanPlayAsDrawbackAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/CannotPlayAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/CannotPlayAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/ChooseCardAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/ChooseCardAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/ChooseCardNameAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/ChooseCardNameAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/ChooseColorAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/ChooseColorAi.java -text
|
||||||
@@ -12544,12 +12544,14 @@ src/main/java/forge/card/abilityfactory/ai/ScryAi.java -text
|
|||||||
src/main/java/forge/card/abilityfactory/ai/SetStateAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/SetStateAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/SetStateAllAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/SetStateAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/ShuffleAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TapAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TapAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TapAiBase.java -text
|
src/main/java/forge/card/abilityfactory/ai/TapAiBase.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TapAllAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TapAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TapOrUntapAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TapOrUntapAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TokenAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/TwoPilesAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/TwoPilesAi.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/UntapAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/UntapAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/ai/UntapAllAi.java -text
|
src/main/java/forge/card/abilityfactory/ai/UntapAllAi.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/AddTurnEffect.java -text
|
||||||
@@ -12557,6 +12559,7 @@ src/main/java/forge/card/abilityfactory/effects/AnimateAllEffect.java -text
|
|||||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/AnimateEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/AnimateEffectBase.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/effects/AnimateEffectBase.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/BondEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/ChangeZoneAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/ChooseCardEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/ChooseCardEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/ChooseCardNameEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/ChooseCardNameEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/ChooseColorEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/ChooseColorEffect.java -text
|
||||||
@@ -12629,11 +12632,13 @@ src/main/java/forge/card/abilityfactory/effects/ScryEffect.java -text
|
|||||||
src/main/java/forge/card/abilityfactory/effects/SetStateAllEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/SetStateAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/SetStateEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/SetStateEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/ShuffleEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/ShuffleEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/StoreSVarEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/TapAllEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/TapAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/TapEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/TapEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/TapOrUntapEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/TapOrUntapEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/effects/TokenEffect.java svneol=native#text/plain
|
||||||
src/main/java/forge/card/abilityfactory/effects/TwoPilesEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/TwoPilesEffect.java -text
|
||||||
|
src/main/java/forge/card/abilityfactory/effects/UnattachAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/UntapAllEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/UntapAllEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/effects/UntapEffect.java -text
|
src/main/java/forge/card/abilityfactory/effects/UntapEffect.java -text
|
||||||
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
src/main/java/forge/card/abilityfactory/package-info.java svneol=native#text/plain
|
||||||
|
|||||||
@@ -471,9 +471,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Cleanup")) {
|
else if (this.api.equals("Cleanup")) {
|
||||||
if (this.isDb) {
|
ai = new AlwaysPlayAi();
|
||||||
spellAbility = AbilityFactoryCleanup.getDrawback(this);
|
se = new CleanUpEffect();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Clone")) {
|
else if (this.api.equals("Clone")) {
|
||||||
@@ -810,13 +809,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("StoreSVar")) {
|
else if (this.api.equals("StoreSVar")) {
|
||||||
if (this.isAb) {
|
ai = new StoreSVarAi();
|
||||||
spellAbility = AbilityFactoryStoreSVar.createAbilityStoreSVar(this);
|
se = new StoreSVarEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryStoreSVar.createSpellStoreSVar(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryStoreSVar.createDrawbackStoreSVar(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Tap")) {
|
else if (this.api.equals("Tap")) {
|
||||||
@@ -845,13 +839,8 @@ public class AbilityFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("UnattachAll")) {
|
else if (this.api.equals("UnattachAll")) {
|
||||||
if (this.isAb) {
|
ai = new UnattachAllAi();
|
||||||
spellAbility = AbilityFactoryAttach.createAbilityUnattachAll(this);
|
se = new UnattachAllEffect();
|
||||||
} else if (this.isSp) {
|
|
||||||
spellAbility = AbilityFactoryAttach.createSpellUnattachAll(this);
|
|
||||||
} else if (this.isDb) {
|
|
||||||
spellAbility = AbilityFactoryAttach.createDrawbackUnattachAll(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (this.api.equals("Untap")) {
|
else if (this.api.equals("Untap")) {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
|
||||||
@@ -1446,402 +1447,5 @@ public class AbilityFactoryAttach {
|
|||||||
// ************************ UnattachAll *************************
|
// ************************ UnattachAll *************************
|
||||||
// **************************************************************
|
// **************************************************************
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the ability unattachAll.
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* the aF
|
|
||||||
* @return the spell ability
|
|
||||||
*/
|
|
||||||
public static SpellAbility createAbilityUnattachAll(final AbilityFactory af) {
|
|
||||||
class AbilityUnattachAll extends AbilityActivated {
|
|
||||||
public AbilityUnattachAll(final Card ca, final Cost co, final Target t) {
|
|
||||||
super(ca, co, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbilityActivated getCopy() {
|
|
||||||
AbilityActivated res = new AbilityUnattachAll(getSourceCard(),
|
|
||||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
|
||||||
CardFactoryUtil.copySpellAbility(this, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 5946312226232487294L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayAI() {
|
|
||||||
return AbilityFactoryAttach.unattachAllCanPlayAI(getActivatingPlayer(), af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStackDescription() {
|
|
||||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doTrigger(final boolean mandatory) {
|
|
||||||
return AbilityFactoryAttach.unattachAllDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final SpellAbility abUnattachAll = new AbilityUnattachAll(af.getHostCard(), af.getAbCost(), af.getAbTgt());
|
|
||||||
|
|
||||||
return abUnattachAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates the spell unattachAll.
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* the AbilityFactory
|
|
||||||
* @return the spell ability
|
|
||||||
*/
|
|
||||||
public static SpellAbility createSpellUnattachAll(final AbilityFactory af) {
|
|
||||||
final SpellAbility spUnattachAll = new Spell(af.getHostCard(), af.getAbCost(), af.getAbTgt()) {
|
|
||||||
private static final long serialVersionUID = 5531073401713526341L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayAI() {
|
|
||||||
return AbilityFactoryAttach.unattachAllCanPlayAI(getActivatingPlayer(), af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStackDescription() {
|
|
||||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return spUnattachAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Attach Drawback
|
|
||||||
/**
|
|
||||||
* Creates the drawback unattachAll.
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* the aF
|
|
||||||
* @return the spell ability
|
|
||||||
*/
|
|
||||||
public static SpellAbility createDrawbackUnattachAll(final AbilityFactory af) {
|
|
||||||
class DrawbackUnattachAll extends AbilitySub {
|
|
||||||
public DrawbackUnattachAll(final Card ca, final Target t) {
|
|
||||||
super(ca, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbilitySub getCopy() {
|
|
||||||
AbilitySub res = new DrawbackUnattachAll(getSourceCard(),
|
|
||||||
getTarget() == null ? null : new Target(getTarget()));
|
|
||||||
CardFactoryUtil.copySpellAbility(this, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 9007743612927046143L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryAttach.unattachAllResolve(af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean chkAIDrawback() {
|
|
||||||
return AbilityFactoryAttach.unattachAllPlayDrawbackAI(getActivatingPlayer(), af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStackDescription() {
|
|
||||||
return AbilityFactoryAttach.unattachAllStackDescription(af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doTrigger(final boolean mandatory) {
|
|
||||||
return AbilityFactoryAttach.unattachAllDoTriggerAI(getActivatingPlayer(), af, this, mandatory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final SpellAbility dbUnattachAll = new DrawbackUnattachAll(af.getHostCard(), af.getAbTgt());
|
|
||||||
|
|
||||||
return dbUnattachAll;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* UnattachAll stack description.
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* the af
|
|
||||||
* @param sa
|
|
||||||
* the sa
|
|
||||||
* @return the string
|
|
||||||
*/
|
|
||||||
private static String unattachAllStackDescription(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
if (sa instanceof AbilitySub) {
|
|
||||||
sb.append(" ");
|
|
||||||
} else {
|
|
||||||
sb.append(sa.getSourceCard()).append(" - ");
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append("Unattach all valid Equipment and Auras from ");
|
|
||||||
|
|
||||||
ArrayList<Object> targets;
|
|
||||||
|
|
||||||
// Should never allow more than one Attachment per card
|
|
||||||
final Target tgt = sa.getTarget();
|
|
||||||
if (tgt != null) {
|
|
||||||
targets = tgt.getTargets();
|
|
||||||
} else {
|
|
||||||
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), af.getMapParams().get("Defined"), sa);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (final Object o : targets) {
|
|
||||||
sb.append(o).append(" ");
|
|
||||||
}
|
|
||||||
|
|
||||||
final AbilitySub abSub = sa.getSubAbility();
|
|
||||||
if (abSub != null) {
|
|
||||||
sb.append(abSub.getStackDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean unattachAllCanPlayAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
final Random r = MyRandom.getRandom();
|
|
||||||
final Cost abCost = sa.getPayCosts();
|
|
||||||
final Card source = sa.getSourceCard();
|
|
||||||
|
|
||||||
if (abCost != null) {
|
|
||||||
// No Aura spells have Additional Costs
|
|
||||||
}
|
|
||||||
|
|
||||||
// prevent run-away activations - first time will always return true
|
|
||||||
boolean chance = r.nextFloat() <= .9;
|
|
||||||
|
|
||||||
// Attach spells always have a target
|
|
||||||
final Target tgt = sa.getTarget();
|
|
||||||
if (tgt != null) {
|
|
||||||
tgt.resetTargets();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (abCost != null && abCost.getTotalMana().contains("X") && source.getSVar("X").equals("Count$xPaid")) {
|
|
||||||
final int xPay = ComputerUtil.determineLeftoverMana(sa, ai);
|
|
||||||
|
|
||||||
if (xPay == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
source.setSVar("PayX", Integer.toString(xPay));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
|
||||||
&& !"Curse".equals(af.getMapParams().get("AILogic"))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return chance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean unattachAllDoTriggerAI(final Player ai, final AbilityFactory af, final SpellAbility sa, final boolean mandatory) {
|
|
||||||
final Map<String, String> params = af.getMapParams();
|
|
||||||
final Card card = sa.getSourceCard();
|
|
||||||
|
|
||||||
if (!ComputerUtil.canPayCost(sa, ai)) {
|
|
||||||
// usually not mandatory
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Player opp = ai.getOpponent();
|
|
||||||
// Check if there are any valid targets
|
|
||||||
ArrayList<Object> targets = new ArrayList<Object>();
|
|
||||||
final Target tgt = sa.getTarget();
|
|
||||||
if (tgt == null) {
|
|
||||||
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), params.get("Defined"), sa);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!mandatory && card.isEquipment() && !targets.isEmpty()) {
|
|
||||||
Card newTarget = (Card) targets.get(0);
|
|
||||||
//don't equip human creatures
|
|
||||||
if (newTarget.getController().equals(opp)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//don't equip a worse creature
|
|
||||||
if (card.isEquipping()) {
|
|
||||||
Card oldTarget = card.getEquipping().get(0);
|
|
||||||
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check SubAbilities DoTrigger?
|
|
||||||
final AbilitySub abSub = sa.getSubAbility();
|
|
||||||
if (abSub != null) {
|
|
||||||
return abSub.doTrigger(mandatory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void unattachAllResolve(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
final Map<String, String> params = af.getMapParams();
|
|
||||||
Card source = sa.getSourceCard();
|
|
||||||
|
|
||||||
ArrayList<Object> targets;
|
|
||||||
|
|
||||||
final Target tgt = sa.getTarget();
|
|
||||||
if (tgt != null) {
|
|
||||||
targets = tgt.getTargets();
|
|
||||||
} else {
|
|
||||||
targets = AbilityFactory.getDefinedObjects(source, params.get("Defined"), sa);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If Cast Targets will be checked on the Stack
|
|
||||||
for (final Object o : targets) {
|
|
||||||
String valid = params.get("UnattachValid");
|
|
||||||
List<Card> unattachList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
|
|
||||||
unattachList = CardLists.getValidCards(unattachList, valid.split(","), source.getController(), source);
|
|
||||||
for (final Card c : unattachList) {
|
|
||||||
AbilityFactoryAttach.handleUnattachment(o, c, af);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void handleUnattachment(final Object o, final Card cardToUnattach, final AbilityFactory af) {
|
|
||||||
|
|
||||||
if (o instanceof Card) {
|
|
||||||
final Card c = (Card) o;
|
|
||||||
if (cardToUnattach.isAura()) {
|
|
||||||
//final boolean gainControl = "GainControl".equals(af.getMapParams().get("AILogic"));
|
|
||||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
|
||||||
} else if (cardToUnattach.isEquipment()) {
|
|
||||||
if (cardToUnattach.isEquipping() && c.getEquippedBy().contains(cardToUnattach)) {
|
|
||||||
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0));
|
|
||||||
}
|
|
||||||
//TODO - unfortify would also be handled here
|
|
||||||
}
|
|
||||||
} else if (o instanceof Player) {
|
|
||||||
final Player p = (Player) o;
|
|
||||||
if (cardToUnattach.isAura() && p.getEnchantedBy().contains(cardToUnattach)) {
|
|
||||||
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* this isn't modifed to handled unattach yet, but should be for things like Remove Enchantments, etc.
|
|
||||||
private static void handleUnattachAura(final Card card, final GameEntity tgt, final boolean gainControl) {
|
|
||||||
if (card.isEnchanting()) {
|
|
||||||
// If this Card is already Enchanting something
|
|
||||||
// Need to unenchant it, then clear out the commands
|
|
||||||
final GameEntity oldEnchanted = card.getEnchanting();
|
|
||||||
card.removeEnchanting(oldEnchanted);
|
|
||||||
card.clearEnchantCommand();
|
|
||||||
card.clearUnEnchantCommand();
|
|
||||||
card.clearTriggers(); // not sure if cleartriggers is needed?
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gainControl) {
|
|
||||||
// Handle GainControl Auras
|
|
||||||
final Player[] pl = new Player[1];
|
|
||||||
|
|
||||||
if (tgt instanceof Card) {
|
|
||||||
pl[0] = ((Card) tgt).getController();
|
|
||||||
} else {
|
|
||||||
pl[0] = (Player) tgt;
|
|
||||||
}
|
|
||||||
|
|
||||||
final Command onEnchant = new Command() {
|
|
||||||
private static final long serialVersionUID = -2519887209491512000L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
final Card crd = card.getEnchantingCard();
|
|
||||||
if (crd == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
pl[0] = crd.getController();
|
|
||||||
|
|
||||||
crd.addController(card);
|
|
||||||
|
|
||||||
} // execute()
|
|
||||||
}; // Command
|
|
||||||
|
|
||||||
final Command onUnEnchant = new Command() {
|
|
||||||
private static final long serialVersionUID = 3426441132121179288L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
final Card crd = card.getEnchantingCard();
|
|
||||||
if (crd == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (AllZoneUtil.isCardInPlay(crd)) {
|
|
||||||
crd.removeController(card);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // execute()
|
|
||||||
}; // Command
|
|
||||||
|
|
||||||
final Command onChangesControl = new Command() {
|
|
||||||
private static final long serialVersionUID = -65903786170234039L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
final Card crd = card.getEnchantingCard();
|
|
||||||
if (crd == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
crd.removeController(card); // This looks odd, but will
|
|
||||||
// simply refresh controller
|
|
||||||
crd.addController(card);
|
|
||||||
} // execute()
|
|
||||||
}; // Command
|
|
||||||
|
|
||||||
// Add Enchant Commands for Control changers
|
|
||||||
card.addEnchantCommand(onEnchant);
|
|
||||||
card.addUnEnchantCommand(onUnEnchant);
|
|
||||||
card.addChangeControllerCommand(onChangesControl);
|
|
||||||
}
|
|
||||||
|
|
||||||
final Command onLeavesPlay = new Command() {
|
|
||||||
private static final long serialVersionUID = -639204333673364477L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute() {
|
|
||||||
final GameEntity entity = card.getEnchanting();
|
|
||||||
if (entity == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
card.unEnchantEntity(entity);
|
|
||||||
}
|
|
||||||
}; // Command
|
|
||||||
|
|
||||||
card.addLeavesPlayCommand(onLeavesPlay);
|
|
||||||
card.enchantEntity(tgt);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
private static boolean unattachAllPlayDrawbackAI(final Player ai, final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
// AI should only activate this during Human's turn
|
|
||||||
boolean chance = AbilityFactoryAttach.unattachAllCanPlayAI(ai, af, sa);
|
|
||||||
|
|
||||||
final AbilitySub subAb = sa.getSubAbility();
|
|
||||||
if (subAb != null) {
|
|
||||||
chance &= subAb.chkAIDrawback();
|
|
||||||
}
|
|
||||||
|
|
||||||
return chance;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,124 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.card.abilityfactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.Singletons;
|
|
||||||
import forge.card.cardfactory.CardFactoryUtil;
|
|
||||||
import forge.card.spellability.AbilitySub;
|
|
||||||
import forge.card.spellability.SpellAbility;
|
|
||||||
import forge.card.spellability.Target;
|
|
||||||
|
|
||||||
// Cleanup is not the same as other AFs, it is only used as a Drawback, and only used to Cleanup particular card states
|
|
||||||
// That need to be reset. I'm creating this to clear Remembered Cards at the
|
|
||||||
// end of an Effect so they don't get shown on a card
|
|
||||||
// After the effect finishes resolving.
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* AbilityFactory_Cleanup class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id$
|
|
||||||
*/
|
|
||||||
public final class AbilityFactoryCleanup {
|
|
||||||
|
|
||||||
private AbilityFactoryCleanup() {
|
|
||||||
throw new AssertionError();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* getDrawback.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @return a {@link forge.card.spellability.AbilitySub} object.
|
|
||||||
*/
|
|
||||||
public static AbilitySub getDrawback(final AbilityFactory af) {
|
|
||||||
class DrawbackCleanup extends AbilitySub {
|
|
||||||
public DrawbackCleanup(final Card ca, final Target t) {
|
|
||||||
super(ca, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbilitySub getCopy() {
|
|
||||||
AbilitySub res = new DrawbackCleanup(getSourceCard(),
|
|
||||||
getTarget() == null ? null : new Target(getTarget()));
|
|
||||||
CardFactoryUtil.copySpellAbility(this, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = 6192972525033429820L;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean chkAIDrawback() {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doTrigger(final boolean mandatory) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryCleanup.doResolve(af, this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final AbilitySub drawback = new DrawbackCleanup(af.getHostCard(), af.getAbTgt());
|
|
||||||
|
|
||||||
return drawback;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* doResolve.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param AF
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
private static void doResolve(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
final Map<String, String> params = af.getMapParams();
|
|
||||||
Card source = sa.getSourceCard();
|
|
||||||
|
|
||||||
if (params.containsKey("ClearRemembered")) {
|
|
||||||
source.clearRemembered();
|
|
||||||
Singletons.getModel().getGame().getCardState(source).clearRemembered();
|
|
||||||
}
|
|
||||||
if (params.containsKey("ClearImprinted")) {
|
|
||||||
source.clearImprinted();
|
|
||||||
}
|
|
||||||
if (params.containsKey("ClearChosenX")) {
|
|
||||||
source.setSVar("ChosenX", "");
|
|
||||||
}
|
|
||||||
if (params.containsKey("ClearChosenY")) {
|
|
||||||
source.setSVar("ChosenY", "");
|
|
||||||
}
|
|
||||||
if (params.containsKey("ClearTriggered")) {
|
|
||||||
Singletons.getModel().getGame().getTriggerHandler().clearDelayedTrigger(source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end class AbilityFactory_Cleanup
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
* Forge: Play Magic: the Gathering.
|
|
||||||
* Copyright (C) 2011 Forge Team
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
package forge.card.abilityfactory;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import forge.Card;
|
|
||||||
import forge.Singletons;
|
|
||||||
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.cost.Cost;
|
|
||||||
import forge.card.spellability.Target;
|
|
||||||
import forge.game.phase.CombatUtil;
|
|
||||||
import forge.game.player.ComputerUtil;
|
|
||||||
import forge.game.player.Player;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* AbilityFactoryStoreSVar class.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @author Forge
|
|
||||||
* @version $Id: AbilityFactoryStoreSVar.java 15090 2012-04-07 12:50:31Z Max mtg $
|
|
||||||
*/
|
|
||||||
public class AbilityFactoryStoreSVar {
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* createAbilityStoreSVar.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param abilityFactory
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public static SpellAbility createAbilityStoreSVar(final AbilityFactory abilityFactory) {
|
|
||||||
class AbilityStoreSVar extends AbilityActivated {
|
|
||||||
public AbilityStoreSVar(final Card ca, final Cost co, final Target t) {
|
|
||||||
super(ca, co, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbilityActivated getCopy() {
|
|
||||||
AbilityActivated res = new AbilityStoreSVar(getSourceCard(),
|
|
||||||
getPayCosts(), getTarget() == null ? null : new Target(getTarget()));
|
|
||||||
CardFactoryUtil.copySpellAbility(this, res);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static final long serialVersionUID = -7299561150243337080L;
|
|
||||||
private final AbilityFactory af = abilityFactory;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getStackDescription() {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayAI() {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doTrigger(final boolean mandatory) {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final SpellAbility abStoreSVar = new AbilityStoreSVar(abilityFactory.getHostCard(), abilityFactory.getAbCost(),
|
|
||||||
abilityFactory.getAbTgt());
|
|
||||||
return abStoreSVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* createSpellStoreSVar.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param abilityFactory
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public static SpellAbility createSpellStoreSVar(final AbilityFactory abilityFactory) {
|
|
||||||
final SpellAbility spStoreSVar = 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 AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayAI() {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
||||||
return spStoreSVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* createDrawbackStoreSVar.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param abilityFactory
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @return a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public static SpellAbility createDrawbackStoreSVar(final AbilityFactory abilityFactory) {
|
|
||||||
class DrawbackStoreSVar extends AbilitySub {
|
|
||||||
public DrawbackStoreSVar(final Card ca, final Target t) {
|
|
||||||
super(ca, t);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AbilitySub getCopy() {
|
|
||||||
AbilitySub res = new DrawbackStoreSVar(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 AbilityFactoryStoreSVar.storeSVarStackDescription(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean canPlayAI() {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarCanPlayAI(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resolve() {
|
|
||||||
AbilityFactoryStoreSVar.storeSVarResolve(this.af, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean chkAIDrawback() {
|
|
||||||
boolean randomReturn = true;
|
|
||||||
final AbilitySub subAb = this.getSubAbility();
|
|
||||||
if (subAb != null) {
|
|
||||||
randomReturn &= subAb.chkAIDrawback();
|
|
||||||
}
|
|
||||||
|
|
||||||
return randomReturn;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean doTrigger(final boolean mandatory) {
|
|
||||||
return AbilityFactoryStoreSVar.storeSVarDoTriggerAI(getActivatingPlayer(), this.af, this, mandatory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
final SpellAbility dbStoreSVar = new DrawbackStoreSVar(abilityFactory.getHostCard(), abilityFactory.getAbTgt());
|
|
||||||
|
|
||||||
return dbStoreSVar;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* storeSVarStackDescription.
|
|
||||||
* </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.
|
|
||||||
*/
|
|
||||||
public static String storeSVarStackDescription(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
final Map<String, String> params = af.getMapParams();
|
|
||||||
|
|
||||||
final StringBuilder sb = new StringBuilder();
|
|
||||||
|
|
||||||
if (sa instanceof AbilitySub) {
|
|
||||||
sb.append(" ");
|
|
||||||
} else {
|
|
||||||
sb.append(sa.getSourceCard().getName()).append(" - ");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("StackDescription")) {
|
|
||||||
sb.append(params.get("StackDescription").replaceAll("CARDNAME", sa.getSourceCard().getName()));
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.append(sa.getDescription());
|
|
||||||
|
|
||||||
final AbilitySub abSub = sa.getSubAbility();
|
|
||||||
if (abSub != null) {
|
|
||||||
sb.append(abSub.getStackDescription());
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* storeSVarCanPlayAI.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
* @return a boolean.
|
|
||||||
*/
|
|
||||||
public static boolean storeSVarCanPlayAI(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
//Tree of Redemption
|
|
||||||
final Player ai = sa.getActivatingPlayer();
|
|
||||||
final Card source = sa.getSourceCard();
|
|
||||||
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
|
||||||
|| (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
final AbilitySub subAb = sa.getSubAbility();
|
|
||||||
if (subAb != null && !subAb.chkAIDrawback()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* storeSVarDoTriggerAI.
|
|
||||||
* </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.
|
|
||||||
*/
|
|
||||||
public static boolean storeSVarDoTriggerAI(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check SubAbilities DoTrigger?
|
|
||||||
final AbilitySub abSub = sa.getSubAbility();
|
|
||||||
if (abSub != null) {
|
|
||||||
return abSub.doTrigger(mandatory);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* storeSVarResolve.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param af
|
|
||||||
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
|
||||||
* @param sa
|
|
||||||
* a {@link forge.card.spellability.SpellAbility} object.
|
|
||||||
*/
|
|
||||||
public static void storeSVarResolve(final AbilityFactory af, final SpellAbility sa) {
|
|
||||||
//SVar$ OldToughness | Type$ Count | Expression$ CardToughness
|
|
||||||
final Map<String, String> params = af.getMapParams();
|
|
||||||
Card source = sa.getSourceCard();
|
|
||||||
|
|
||||||
String key = null;
|
|
||||||
String type = null;
|
|
||||||
String expr = null;
|
|
||||||
|
|
||||||
if (params.containsKey("SVar")) {
|
|
||||||
key = params.get("SVar");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("Type")) {
|
|
||||||
type = params.get("Type");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (params.containsKey("Expression")) {
|
|
||||||
expr = params.get("Expression");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key == null || type == null || expr == null) {
|
|
||||||
System.out.println("SVar, Type and Expression paramaters required for StoreSVar. They are missing for " + source.getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
int value = 0;
|
|
||||||
|
|
||||||
if (type.equals("Count")) {
|
|
||||||
value = CardFactoryUtil.xCount(source, expr);
|
|
||||||
}
|
|
||||||
else if (type.equals("Number")) {
|
|
||||||
value = Integer.valueOf(expr);
|
|
||||||
}
|
|
||||||
else if (type.equals("CountSVar")) {
|
|
||||||
value = CardFactoryUtil.xCount(source, "SVar$" + expr);
|
|
||||||
}
|
|
||||||
//TODO For other types call a different function
|
|
||||||
|
|
||||||
StringBuilder numBuilder = new StringBuilder();
|
|
||||||
numBuilder.append("Number$");
|
|
||||||
numBuilder.append(value);
|
|
||||||
|
|
||||||
source.setSVar(key, numBuilder.toString());
|
|
||||||
|
|
||||||
SpellAbility root = sa.getRootSpellAbility();
|
|
||||||
while(root != null) {
|
|
||||||
root.setSVar(key, numBuilder.toString());
|
|
||||||
root = root.getSubAbility();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // end class AbilityFactorystoreSVar
|
|
||||||
36
src/main/java/forge/card/abilityfactory/CleanUpEffect.java
Normal file
36
src/main/java/forge/card/abilityfactory/CleanUpEffect.java
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
package forge.card.abilityfactory;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
|
||||||
|
public class CleanUpEffect extends SpellEffect {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(Map<String, String> params, SpellAbility sa) {
|
||||||
|
Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
if (params.containsKey("ClearRemembered")) {
|
||||||
|
source.clearRemembered();
|
||||||
|
Singletons.getModel().getGame().getCardState(source).clearRemembered();
|
||||||
|
}
|
||||||
|
if (params.containsKey("ClearImprinted")) {
|
||||||
|
source.clearImprinted();
|
||||||
|
}
|
||||||
|
if (params.containsKey("ClearChosenX")) {
|
||||||
|
source.setSVar("ChosenX", "");
|
||||||
|
}
|
||||||
|
if (params.containsKey("ClearChosenY")) {
|
||||||
|
source.setSVar("ChosenY", "");
|
||||||
|
}
|
||||||
|
if (params.containsKey("ClearTriggered")) {
|
||||||
|
Singletons.getModel().getGame().getTriggerHandler().clearDelayedTrigger(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end class AbilityFactory_Cleanup
|
||||||
@@ -64,5 +64,4 @@ public class CommonAbility extends AbilityActivated {
|
|||||||
public boolean doTrigger(final boolean mandatory) {
|
public boolean doTrigger(final boolean mandatory) {
|
||||||
return ai.doTriggerAI(this.getActivatingPlayer(), params, this, mandatory);
|
return ai.doTriggerAI(this.getActivatingPlayer(), params, this, mandatory);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
297
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java
Normal file
297
src/main/java/forge/card/abilityfactory/ai/ChangeZoneAllAi.java
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.CardLists;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.cost.CostUtil;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
public class ChangeZoneAllAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, Map<String, String> params, SpellAbility sa) {
|
||||||
|
// Change Zone All, can be any type moving from one zone to another
|
||||||
|
final Cost abCost = sa.getAbilityFactory().getAbCost();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||||
|
final ZoneType origin = ZoneType.smartValueOf(params.get("Origin"));
|
||||||
|
|
||||||
|
if (abCost != null) {
|
||||||
|
// AI currently disabled for these costs
|
||||||
|
if (!CostUtil.checkLifeCost(ai, abCost, source, 4, null)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CostUtil.checkDiscardCost(ai, abCost, source)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
// prevent run-away activations - first time will always return true
|
||||||
|
boolean chance = r.nextFloat() <= Math.pow(.6667, sa.getActivationsThisTurn());
|
||||||
|
|
||||||
|
// TODO targeting with ChangeZoneAll
|
||||||
|
// really two types of targeting.
|
||||||
|
// Target Player has all their types change zones
|
||||||
|
// or target permanent and do something relative to that permanent
|
||||||
|
// ex. "Return all Auras attached to target"
|
||||||
|
// ex. "Return all blocking/blocked by target creature"
|
||||||
|
|
||||||
|
final Player opp = ai.getOpponent();
|
||||||
|
final List<Card> humanType = AbilityFactory.filterListByType(opp.getCardsIn(origin), params.get("ChangeType"), sa);
|
||||||
|
List<Card> computerType = ai.getCardsIn(origin);
|
||||||
|
computerType = AbilityFactory.filterListByType(computerType, params.get("ChangeType"), sa);
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
|
||||||
|
// TODO improve restrictions on when the AI would want to use this
|
||||||
|
// spBounceAll has some AI we can compare to.
|
||||||
|
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||||
|
if (tgt != null) {
|
||||||
|
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||||
|
|| !opp.canBeTargetedBy(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgt.resetTargets();
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||||
|
// this statement is assuming the AI is trying to use this spell
|
||||||
|
// offensively
|
||||||
|
// if the AI is using it defensively, then something else needs to
|
||||||
|
// occur
|
||||||
|
// if only creatures are affected evaluate both lists and pass only
|
||||||
|
// if human creatures are more valuable
|
||||||
|
if (tgt != null) {
|
||||||
|
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||||
|
|| !opp.canBeTargetedBy(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgt.resetTargets();
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
computerType.clear();
|
||||||
|
}
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
|
if ((CardFactoryUtil.evaluateCreatureList(computerType) + 200) >= CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are more valuable
|
||||||
|
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + 3) >= CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't cast during main1?
|
||||||
|
if (Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.MAIN1, ai)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||||
|
if (tgt != null) {
|
||||||
|
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
||||||
|
|| !opp.canBeTargetedBy(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgt.resetTargets();
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Exile)) {
|
||||||
|
|
||||||
|
} else if (origin.equals(ZoneType.Stack)) {
|
||||||
|
// time stop can do something like this:
|
||||||
|
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||||
|
// DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup
|
||||||
|
// otherwise, this situation doesn't exist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination.equals(ZoneType.Battlefield)) {
|
||||||
|
if (params.get("GainControl") != null) {
|
||||||
|
// Check if the cards are valuable enough
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
|
if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType)) < 400) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are less valuable
|
||||||
|
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType)) < 6) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// don't activate if human gets more back than AI does
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
|
if (CardFactoryUtil.evaluateCreatureList(computerType) <= (CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType) + 100)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are less valuable
|
||||||
|
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= (CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType) + 2)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
chance &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return (((r.nextFloat() < .8) || sa.isTrigger()) && chance);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* changeZoneAllPlayDrawbackAI.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* a {@link forge.card.abilityfactory.AbilityFactory} object.
|
||||||
|
* @param sa
|
||||||
|
* a {@link forge.card.spellability.SpellAbility} object.
|
||||||
|
* @return a boolean.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
|
// if putting cards from hand to library and parent is drawing cards
|
||||||
|
// make sure this will actually do something:
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* gainLifeDoTriggerAINoCost.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player ai, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
// Change Zone All, can be any type moving from one zone to another
|
||||||
|
|
||||||
|
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||||
|
final ZoneType origin = ZoneType.smartValueOf(params.get("Origin"));
|
||||||
|
|
||||||
|
final Player opp = ai.getOpponent();
|
||||||
|
final List<Card> humanType = AbilityFactory.filterListByType(opp.getCardsIn(origin), params.get("ChangeType"), sa);
|
||||||
|
List<Card> computerType = ai.getCardsIn(origin);
|
||||||
|
computerType = AbilityFactory.filterListByType(computerType, params.get("ChangeType"), sa);
|
||||||
|
|
||||||
|
// TODO improve restrictions on when the AI would want to use this
|
||||||
|
// spBounceAll has some AI we can compare to.
|
||||||
|
if (origin.equals(ZoneType.Hand) || origin.equals(ZoneType.Library)) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
if (opp.getCardsIn(ZoneType.Hand).isEmpty()
|
||||||
|
|| !opp.canBeTargetedBy(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgt.resetTargets();
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Battlefield)) {
|
||||||
|
// this statement is assuming the AI is trying to use this spell offensively
|
||||||
|
// if the AI is using it defensively, then something else needs to occur
|
||||||
|
// if only creatures are affected evaluate both lists and pass only
|
||||||
|
// if human creatures are more valuable
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
|
||||||
|
if (CardFactoryUtil.evaluateCreatureList(computerType) >= CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are more valuable
|
||||||
|
else if (CardFactoryUtil.evaluatePermanentList(computerType) >= CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Graveyard)) {
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
if (opp.getCardsIn(ZoneType.Graveyard).isEmpty()
|
||||||
|
|| !opp.canBeTargetedBy(sa)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
tgt.resetTargets();
|
||||||
|
tgt.addTarget(opp);
|
||||||
|
}
|
||||||
|
} else if (origin.equals(ZoneType.Exile)) {
|
||||||
|
|
||||||
|
} else if (origin.equals(ZoneType.Stack)) {
|
||||||
|
// time stop can do something like this:
|
||||||
|
// Origin$ Stack | Destination$ Exile | SubAbility$ DBSkip
|
||||||
|
// DBSKipToPhase | DB$SkipToPhase | Phase$ Cleanup
|
||||||
|
// otherwise, this situation doesn't exist
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (destination.equals(ZoneType.Battlefield)) {
|
||||||
|
if (params.get("GainControl") != null) {
|
||||||
|
// Check if the cards are valuable enough
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").size() == 0) && (CardLists.getNotType(computerType, "Creature").size() == 0)) {
|
||||||
|
if ((CardFactoryUtil.evaluateCreatureList(computerType) + CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType)) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are less valuable
|
||||||
|
else if ((CardFactoryUtil.evaluatePermanentList(computerType) + CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType)) < 1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// don't activate if human gets more back than AI does
|
||||||
|
if ((CardLists.getNotType(humanType, "Creature").isEmpty()) && (CardLists.getNotType(computerType, "Creature").isEmpty())) {
|
||||||
|
if (CardFactoryUtil.evaluateCreatureList(computerType) <= CardFactoryUtil
|
||||||
|
.evaluateCreatureList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} // otherwise evaluate both lists by CMC and pass only if human
|
||||||
|
// permanents are less valuable
|
||||||
|
else if (CardFactoryUtil.evaluatePermanentList(computerType) <= CardFactoryUtil
|
||||||
|
.evaluatePermanentList(humanType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean chance = true;
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null) {
|
||||||
|
chance &= subAb.chkAIDrawback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
50
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java
Normal file
50
src/main/java/forge/card/abilityfactory/ai/StoreSVarAi.java
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.game.phase.CombatUtil;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
|
||||||
|
public class StoreSVarAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
//Tree of Redemption
|
||||||
|
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
if (ComputerUtil.waitForBlocking(sa) || ai.getLife() + 1 >= source.getNetDefense()
|
||||||
|
|| (ai.getLife() > 5 && !CombatUtil.lifeInSeriousDanger(ai, Singletons.getModel().getGame().getCombat()))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final AbilitySub subAb = sa.getSubAbility();
|
||||||
|
if (subAb != null && !subAb.chkAIDrawback()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player aiPlayer) {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player aiPlayer, java.util.Map<String,String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
124
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java
Normal file
124
src/main/java/forge/card/abilityfactory/ai/UnattachAllAi.java
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
package forge.card.abilityfactory.ai;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellAiLogic;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.cost.Cost;
|
||||||
|
import forge.card.spellability.AbilitySub;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.phase.PhaseType;
|
||||||
|
import forge.game.player.ComputerUtil;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.util.MyRandom;
|
||||||
|
|
||||||
|
public class UnattachAllAi extends SpellAiLogic {
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellAiLogic#canPlayAI(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean canPlayAI(Player ai, Map<String, String> params, SpellAbility sa) {
|
||||||
|
final Random r = MyRandom.getRandom();
|
||||||
|
final Cost abCost = sa.getPayCosts();
|
||||||
|
final Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
if (abCost != null) {
|
||||||
|
// No Aura spells have Additional Costs
|
||||||
|
}
|
||||||
|
|
||||||
|
// prevent run-away activations - first time will always return true
|
||||||
|
boolean chance = r.nextFloat() <= .9;
|
||||||
|
|
||||||
|
// Attach spells always have a target
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgt.resetTargets();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (abCost != null && abCost.getTotalMana().contains("X") && source.getSVar("X").equals("Count$xPaid")) {
|
||||||
|
final int xPay = ComputerUtil.determineLeftoverMana(sa, ai);
|
||||||
|
|
||||||
|
if (xPay == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
source.setSVar("PayX", Integer.toString(xPay));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Singletons.getModel().getGame().getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_DECLARE_BLOCKERS_INSTANT_ABILITY)
|
||||||
|
&& !"Curse".equals(params.get("AILogic"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean doTriggerAINoCost(Player ai, Map<String, String> params, SpellAbility sa, boolean mandatory) {
|
||||||
|
final Card card = sa.getSourceCard();
|
||||||
|
final Player opp = ai.getOpponent();
|
||||||
|
// Check if there are any valid targets
|
||||||
|
ArrayList<Object> targets = new ArrayList<Object>();
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt == null) {
|
||||||
|
targets = AbilityFactory.getDefinedObjects(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!mandatory && card.isEquipment() && !targets.isEmpty()) {
|
||||||
|
Card newTarget = (Card) targets.get(0);
|
||||||
|
//don't equip human creatures
|
||||||
|
if (newTarget.getController().equals(opp)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//don't equip a worse creature
|
||||||
|
if (card.isEquipping()) {
|
||||||
|
Card oldTarget = card.getEquipping().get(0);
|
||||||
|
if (CardFactoryUtil.evaluateCreature(oldTarget) > CardFactoryUtil.evaluateCreature(newTarget)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// check SubAbilities DoTrigger?
|
||||||
|
final AbilitySub abSub = sa.getSubAbility();
|
||||||
|
if (abSub != null) {
|
||||||
|
return abSub.doTrigger(mandatory);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean chkAIDrawback(java.util.Map<String,String> params, SpellAbility sa, Player ai) {
|
||||||
|
// AI should only activate this during Human's turn
|
||||||
|
return canPlayAI(ai, params, sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UnattachAll stack description.
|
||||||
|
*
|
||||||
|
* @param af
|
||||||
|
* the af
|
||||||
|
* @param sa
|
||||||
|
* the sa
|
||||||
|
* @return the string
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.CardCharacteristicName;
|
||||||
|
import forge.CardPredicates;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.AbilityFactoryAttach;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
public class ChangeZoneAllEffect extends SpellEffect {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* changeZoneAllStackDescription.
|
||||||
|
* </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.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getStackDescription(java.util.Map<String,String> params, SpellAbility sa) {
|
||||||
|
// TODO build Stack Description will need expansion as more cards are added
|
||||||
|
|
||||||
|
final String[] desc = sa.getDescription().split(":");
|
||||||
|
|
||||||
|
if (desc.length > 1) {
|
||||||
|
return desc[1];
|
||||||
|
} else {
|
||||||
|
return desc[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* changeZoneAllResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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<String,String> params, SpellAbility sa) {
|
||||||
|
final ZoneType destination = ZoneType.smartValueOf(params.get("Destination"));
|
||||||
|
final List<ZoneType> origin = ZoneType.listValueOf(params.get("Origin"));
|
||||||
|
|
||||||
|
List<Card> cards = null;
|
||||||
|
|
||||||
|
ArrayList<Player> tgtPlayers = null;
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
if (tgt != null) {
|
||||||
|
tgtPlayers = tgt.getTargetPlayers();
|
||||||
|
} else if (params.containsKey("Defined")) {
|
||||||
|
tgtPlayers = AbilityFactory.getDefinedPlayers(sa.getSourceCard(), params.get("Defined"), sa);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((tgtPlayers == null) || tgtPlayers.isEmpty()) {
|
||||||
|
cards = Singletons.getModel().getGame().getCardsIn(origin);
|
||||||
|
} else {
|
||||||
|
cards = tgtPlayers.get(0).getCardsIn(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
cards = AbilityFactory.filterListByType(cards, params.get("ChangeType"), sa);
|
||||||
|
|
||||||
|
if (params.containsKey("ForgetOtherRemembered")) {
|
||||||
|
sa.getSourceCard().clearRemembered();
|
||||||
|
}
|
||||||
|
|
||||||
|
final String remember = params.get("RememberChanged");
|
||||||
|
|
||||||
|
// I don't know if library position is necessary. It's here if it is,
|
||||||
|
// just in case
|
||||||
|
final int libraryPos = params.containsKey("LibraryPosition") ? Integer.parseInt(params.get("LibraryPosition"))
|
||||||
|
: 0;
|
||||||
|
for (final Card c : cards) {
|
||||||
|
if (destination.equals(ZoneType.Battlefield)) {
|
||||||
|
// Auras without Candidates stay in their current location
|
||||||
|
if (c.isAura()) {
|
||||||
|
final SpellAbility saAura = AbilityFactoryAttach.getAttachSpellAbility(c);
|
||||||
|
if (!saAura.getTarget().hasCandidates(saAura, false)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (params.containsKey("Tapped")) {
|
||||||
|
c.setTapped(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("GainControl")) {
|
||||||
|
c.addController(sa.getSourceCard());
|
||||||
|
Singletons.getModel().getGame().getAction().moveToPlay(c, sa.getActivatingPlayer());
|
||||||
|
} else {
|
||||||
|
final Card movedCard = Singletons.getModel().getGame().getAction().moveTo(destination, c, libraryPos);
|
||||||
|
if (params.containsKey("ExileFaceDown")) {
|
||||||
|
movedCard.setState(CardCharacteristicName.FaceDown);
|
||||||
|
}
|
||||||
|
if (params.containsKey("Tapped")) {
|
||||||
|
movedCard.setTapped(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (remember != null) {
|
||||||
|
Singletons.getModel().getGame().getCardState(sa.getSourceCard()).addRemembered(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if Shuffle parameter exists, and any amount of cards were owned by
|
||||||
|
// that player, then shuffle that library
|
||||||
|
if (params.containsKey("Shuffle")) {
|
||||||
|
for( Player p : Singletons.getModel().getGame().getPlayers()) {
|
||||||
|
if (Iterables.any(cards, CardPredicates.isOwner(p))) {
|
||||||
|
p.shuffle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.card.abilityfactory.AbilityFactory;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.cardfactory.CardFactoryUtil;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
|
||||||
|
public class StoreSVarEffect extends SpellEffect {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* storeSVarResolve.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @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<String,String> params, SpellAbility sa) {
|
||||||
|
//SVar$ OldToughness | Type$ Count | Expression$ CardToughness
|
||||||
|
Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
String key = null;
|
||||||
|
String type = null;
|
||||||
|
String expr = null;
|
||||||
|
|
||||||
|
if (params.containsKey("SVar")) {
|
||||||
|
key = params.get("SVar");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("Type")) {
|
||||||
|
type = params.get("Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params.containsKey("Expression")) {
|
||||||
|
expr = params.get("Expression");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key == null || type == null || expr == null) {
|
||||||
|
System.out.println("SVar, Type and Expression paramaters required for StoreSVar. They are missing for " + source.getName());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int value = 0;
|
||||||
|
|
||||||
|
if (type.equals("Count")) {
|
||||||
|
value = CardFactoryUtil.xCount(source, expr);
|
||||||
|
}
|
||||||
|
else if (type.equals("Number")) {
|
||||||
|
value = Integer.valueOf(expr);
|
||||||
|
}
|
||||||
|
else if (type.equals("CountSVar")) {
|
||||||
|
value = CardFactoryUtil.xCount(source, "SVar$" + expr);
|
||||||
|
}
|
||||||
|
//TODO For other types call a different function
|
||||||
|
|
||||||
|
StringBuilder numBuilder = new StringBuilder();
|
||||||
|
numBuilder.append("Number$");
|
||||||
|
numBuilder.append(value);
|
||||||
|
|
||||||
|
source.setSVar(key, numBuilder.toString());
|
||||||
|
|
||||||
|
SpellAbility root = sa.getRootSpellAbility();
|
||||||
|
while(root != null) {
|
||||||
|
root.setSVar(key, numBuilder.toString());
|
||||||
|
root = root.getSubAbility();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end class AbilityFactorystoreSVar
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
package forge.card.abilityfactory.effects;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import forge.Card;
|
||||||
|
import forge.CardLists;
|
||||||
|
import forge.GameEntity;
|
||||||
|
import forge.Singletons;
|
||||||
|
import forge.card.abilityfactory.SpellEffect;
|
||||||
|
import forge.card.spellability.SpellAbility;
|
||||||
|
import forge.card.spellability.Target;
|
||||||
|
import forge.game.player.Player;
|
||||||
|
import forge.game.zone.ZoneType;
|
||||||
|
|
||||||
|
public class UnattachAllEffect extends SpellEffect {
|
||||||
|
|
||||||
|
private void handleUnattachment(final GameEntity o, final Card cardToUnattach) {
|
||||||
|
|
||||||
|
if (o instanceof Card) {
|
||||||
|
final Card c = (Card) o;
|
||||||
|
if (cardToUnattach.isAura()) {
|
||||||
|
//final boolean gainControl = "GainControl".equals(af.getMapParams().get("AILogic"));
|
||||||
|
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, c, gainControl);
|
||||||
|
} else if (cardToUnattach.isEquipment()) {
|
||||||
|
if (cardToUnattach.isEquipping() && c.getEquippedBy().contains(cardToUnattach)) {
|
||||||
|
cardToUnattach.unEquipCard(cardToUnattach.getEquipping().get(0));
|
||||||
|
}
|
||||||
|
//TODO - unfortify would also be handled here
|
||||||
|
}
|
||||||
|
} else if (o instanceof Player) {
|
||||||
|
final Player p = (Player) o;
|
||||||
|
if (cardToUnattach.isAura() && p.getEnchantedBy().contains(cardToUnattach)) {
|
||||||
|
//AbilityFactoryAttach.handleUnattachAura(cardToUnattach, p, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* this isn't modifed to handled unattach yet, but should be for things like Remove Enchantments, etc.
|
||||||
|
private static void handleUnattachAura(final Card card, final GameEntity tgt, final boolean gainControl) {
|
||||||
|
if (card.isEnchanting()) {
|
||||||
|
// If this Card is already Enchanting something
|
||||||
|
// Need to unenchant it, then clear out the commands
|
||||||
|
final GameEntity oldEnchanted = card.getEnchanting();
|
||||||
|
card.removeEnchanting(oldEnchanted);
|
||||||
|
card.clearEnchantCommand();
|
||||||
|
card.clearUnEnchantCommand();
|
||||||
|
card.clearTriggers(); // not sure if cleartriggers is needed?
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gainControl) {
|
||||||
|
// Handle GainControl Auras
|
||||||
|
final Player[] pl = new Player[1];
|
||||||
|
|
||||||
|
if (tgt instanceof Card) {
|
||||||
|
pl[0] = ((Card) tgt).getController();
|
||||||
|
} else {
|
||||||
|
pl[0] = (Player) tgt;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Command onEnchant = new Command() {
|
||||||
|
private static final long serialVersionUID = -2519887209491512000L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
final Card crd = card.getEnchantingCard();
|
||||||
|
if (crd == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
pl[0] = crd.getController();
|
||||||
|
|
||||||
|
crd.addController(card);
|
||||||
|
|
||||||
|
} // execute()
|
||||||
|
}; // Command
|
||||||
|
|
||||||
|
final Command onUnEnchant = new Command() {
|
||||||
|
private static final long serialVersionUID = 3426441132121179288L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
final Card crd = card.getEnchantingCard();
|
||||||
|
if (crd == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (AllZoneUtil.isCardInPlay(crd)) {
|
||||||
|
crd.removeController(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // execute()
|
||||||
|
}; // Command
|
||||||
|
|
||||||
|
final Command onChangesControl = new Command() {
|
||||||
|
private static final long serialVersionUID = -65903786170234039L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
final Card crd = card.getEnchantingCard();
|
||||||
|
if (crd == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
crd.removeController(card); // This looks odd, but will
|
||||||
|
// simply refresh controller
|
||||||
|
crd.addController(card);
|
||||||
|
} // execute()
|
||||||
|
}; // Command
|
||||||
|
|
||||||
|
// Add Enchant Commands for Control changers
|
||||||
|
card.addEnchantCommand(onEnchant);
|
||||||
|
card.addUnEnchantCommand(onUnEnchant);
|
||||||
|
card.addChangeControllerCommand(onChangesControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Command onLeavesPlay = new Command() {
|
||||||
|
private static final long serialVersionUID = -639204333673364477L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() {
|
||||||
|
final GameEntity entity = card.getEnchanting();
|
||||||
|
if (entity == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
card.unEnchantEntity(entity);
|
||||||
|
}
|
||||||
|
}; // Command
|
||||||
|
|
||||||
|
card.addLeavesPlayCommand(onLeavesPlay);
|
||||||
|
card.enchantEntity(tgt);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#getStackDescription(java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected String getStackDescription(Map<String, String> params, SpellAbility sa) {
|
||||||
|
final StringBuilder sb = new StringBuilder();
|
||||||
|
sb.append("Unattach all valid Equipment and Auras from ");
|
||||||
|
final List<Object> targets = getTargetObjects(sa, params);
|
||||||
|
sb.append(StringUtils.join(targets, " "));
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see forge.card.abilityfactory.SpellEffect#resolve(java.util.Map, forge.card.spellability.SpellAbility)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void resolve(Map<String, String> params, SpellAbility sa) {
|
||||||
|
Card source = sa.getSourceCard();
|
||||||
|
|
||||||
|
final Target tgt = sa.getTarget();
|
||||||
|
final List<Object> targets = getTargetObjects(sa, params);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// If Cast Targets will be checked on the Stack
|
||||||
|
for (final Object o : targets) {
|
||||||
|
if (!( o instanceof GameEntity )) continue;
|
||||||
|
|
||||||
|
String valid = params.get("UnattachValid");
|
||||||
|
List<Card> unattachList = Singletons.getModel().getGame().getCardsIn(ZoneType.Battlefield);
|
||||||
|
unattachList = CardLists.getValidCards(unattachList, valid.split(","), source.getController(), source);
|
||||||
|
for (final Card c : unattachList) {
|
||||||
|
handleUnattachment((GameEntity)o, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user