mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-20 20:58:03 +00:00
* CommonDrawback merged into AbilitySub, as there are no other SubAbilities without api.
* (fixes for 19720 & 19724) CheckAiDrawback was already recursivelly checking every subability, so no special methods were required * numerous fixes to make ApiType comparisons null-safe * CommonXXX classes do not take SpellEffect and AILogic as separate parameters. These are obtained from ApiType instead
This commit is contained in:
3
.gitattributes
vendored
3
.gitattributes
vendored
@@ -13650,7 +13650,6 @@ src/main/java/forge/card/ability/AbilityFactory.java svneol=native#text/plain
|
||||
src/main/java/forge/card/ability/AbilityUtils.java -text
|
||||
src/main/java/forge/card/ability/ApiType.java -text
|
||||
src/main/java/forge/card/ability/CommonAbility.java -text
|
||||
src/main/java/forge/card/ability/CommonDrawback.java svneol=native#text/plain
|
||||
src/main/java/forge/card/ability/CommonSpell.java -text
|
||||
src/main/java/forge/card/ability/SpellAiLogic.java -text
|
||||
src/main/java/forge/card/ability/SpellEffect.java -text
|
||||
@@ -13799,6 +13798,7 @@ src/main/java/forge/card/ability/effects/DigUntilEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/DiscardEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/DrainManaEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/DrawEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/ETBReplacementEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/EffectEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/EncodeEffect.java -text
|
||||
src/main/java/forge/card/ability/effects/EndTurnEffect.java -text
|
||||
@@ -14427,6 +14427,7 @@ src/main/java/forge/util/MultiplexOutputStream.java svneol=native#text/plain
|
||||
src/main/java/forge/util/MyObservable.java svneol=native#text/plain
|
||||
src/main/java/forge/util/MyRandom.java svneol=native#text/plain
|
||||
src/main/java/forge/util/PredicateString.java -text
|
||||
src/main/java/forge/util/ReflectionUtil.java -text
|
||||
src/main/java/forge/util/TextUtil.java -text
|
||||
src/main/java/forge/util/ThreadUtil.java svneol=native#text/plain
|
||||
src/main/java/forge/util/TreeProperties.java svneol=native#text/plain
|
||||
|
||||
@@ -2652,7 +2652,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
// if there is a parent ability the AI can't use it
|
||||
final Cost cost = a.getPayCosts();
|
||||
if (!cost.hasNoManaCost()
|
||||
|| (!a.getApi().equals(ApiType.Mana) && !a.getApi().equals(ApiType.ManaReflected))) {
|
||||
|| (a.getApi() != ApiType.Mana && a.getApi() != ApiType.ManaReflected)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -5973,7 +5973,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
*/
|
||||
public final boolean isReflectedLand() {
|
||||
for (final SpellAbility a : this.getCharacteristics().getManaAbility()) {
|
||||
if (a.getApi().equals(ApiType.ManaReflected)) {
|
||||
if (a.getApi() == ApiType.ManaReflected) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -503,7 +503,7 @@ public final class CardUtil {
|
||||
// so we don't infinite recurse.
|
||||
final Card card = abMana.getSourceCard();
|
||||
|
||||
if (!abMana.getApi().equals(ApiType.ManaReflected)) {
|
||||
if (abMana.getApi() != ApiType.ManaReflected) {
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
@@ -126,15 +126,13 @@ public final class AbilityFactory {
|
||||
}
|
||||
}
|
||||
|
||||
SpellAiLogic ai = api.getAi();
|
||||
SpellEffect se = api.getSpellEffect();
|
||||
|
||||
if (isAb) {
|
||||
spellAbility = new CommonAbility(api, hostCard, abCost, abTgt, mapParams, se, ai);
|
||||
spellAbility = new CommonAbility(api, hostCard, abCost, abTgt, mapParams);
|
||||
} else if (isSp) {
|
||||
spellAbility = new CommonSpell(api, hostCard, abCost, abTgt, mapParams, se, ai);
|
||||
spellAbility = new CommonSpell(api, hostCard, abCost, abTgt, mapParams);
|
||||
} else if (isDb) {
|
||||
spellAbility = new CommonDrawback(api, hostCard, abTgt, mapParams, se, ai);
|
||||
spellAbility = new AbilitySub(api, hostCard, abTgt, mapParams);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
package forge.card.ability;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import forge.card.ability.ai.*;
|
||||
import forge.card.ability.effects.*;
|
||||
import forge.util.ReflectionUtil;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
@@ -113,69 +116,41 @@ public enum ApiType {
|
||||
UnattachAll (UnattachAllEffect.class, UnattachAllAi.class),
|
||||
Untap (UntapEffect.class, UntapAi.class),
|
||||
UntapAll (UntapAllEffect.class, UntapAllAi.class),
|
||||
WinsGame (GameWinEffect.class, GameWinAi.class);
|
||||
WinsGame (GameWinEffect.class, GameWinAi.class),
|
||||
|
||||
|
||||
|
||||
InternalEtbReplacement(ETBReplacementEffect.class, CanPlayAsDrawbackAi.class);
|
||||
|
||||
private final Class<? extends SpellEffect> clsEffect;
|
||||
private final Class<? extends SpellAiLogic> clsAi;
|
||||
|
||||
|
||||
private static final Map<String, ApiType> allValues = new TreeMap<String, ApiType>(String.CASE_INSENSITIVE_ORDER);
|
||||
|
||||
ApiType(Class<? extends SpellEffect> clsEf, Class<? extends SpellAiLogic> clsAI) {
|
||||
clsEffect = clsEf;
|
||||
clsAi = clsAI;
|
||||
}
|
||||
|
||||
private final Class<? extends SpellEffect> clsEffect;
|
||||
private final Class<? extends SpellAiLogic> clsAi;
|
||||
|
||||
public static ApiType smartValueOf(String value) {
|
||||
|
||||
final String valToCompate = value.trim();
|
||||
for (final ApiType v : ApiType.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException("Element " + value + " not found in ApiType enum");
|
||||
if (allValues.isEmpty())
|
||||
for(ApiType c : ApiType.values())
|
||||
allValues.put(c.toString(), c);
|
||||
|
||||
ApiType v = allValues.get(value);
|
||||
if ( v == null )
|
||||
throw new RuntimeException("Element " + value + " not found in ApiType enum");
|
||||
return v;
|
||||
}
|
||||
|
||||
public SpellEffect getSpellEffect() {
|
||||
if (null == clsEffect) {
|
||||
return null;
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<? extends SpellEffect>[] cc = (Constructor<? extends SpellEffect>[]) clsEffect.getConstructors();
|
||||
for (Constructor<? extends SpellEffect> c : cc) {
|
||||
Class<?>[] pp = c.getParameterTypes();
|
||||
if (pp.length == 0) {
|
||||
try {
|
||||
SpellEffect res = c.newInstance();
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No default constructor found in class " + clsEffect.getName());
|
||||
return clsEffect == null ? null : ReflectionUtil.makeDefaultInstanceOf(clsEffect);
|
||||
|
||||
}
|
||||
|
||||
public SpellAiLogic getAi() {
|
||||
if (null == clsAi) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<? extends SpellAiLogic>[] cc = (Constructor<? extends SpellAiLogic>[]) clsAi.getConstructors();
|
||||
for (Constructor<? extends SpellAiLogic> c : cc) {
|
||||
Class<?>[] pp = c.getParameterTypes();
|
||||
if (pp.length == 0) {
|
||||
try {
|
||||
SpellAiLogic res = c.newInstance();
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block ignores the exception, but sends it to System.err and probably forge.log.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No default constructor found in class " + clsEffect.getName());
|
||||
return clsAi == null ? null : ReflectionUtil.makeDefaultInstanceOf(clsAi);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,20 +20,20 @@ public class CommonAbility extends AbilityActivated {
|
||||
|
||||
private static final long serialVersionUID = -4183793555528531978L;
|
||||
|
||||
public CommonAbility(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
|
||||
public CommonAbility(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0) {
|
||||
super(sourceCard, abCost, tgt);
|
||||
params = params0;
|
||||
api = api0;
|
||||
effect = effect0;
|
||||
ai = ai0;
|
||||
effect = api.getSpellEffect();
|
||||
ai = api.getAi();
|
||||
|
||||
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
|
||||
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
|
||||
|
||||
this.setManaPart(new AbilityManaPart(sourceCard, params));
|
||||
this.setUndoable(true); // will try at least
|
||||
}
|
||||
|
||||
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
|
||||
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
|
||||
AbilityFactory.adjustChangeZoneTarget(params, this);
|
||||
}
|
||||
}
|
||||
@@ -49,7 +49,7 @@ public class CommonAbility extends AbilityActivated {
|
||||
@Override
|
||||
public AbilityActivated getCopy() {
|
||||
Target tgt = getTarget() == null ? null : new Target(getTarget());
|
||||
AbilityActivated res = new CommonAbility(api, getSourceCard(), getPayCosts(), tgt, params, effect, ai);
|
||||
AbilityActivated res = new CommonAbility(api, getSourceCard(), getPayCosts(), tgt, params);
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1,88 +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.ability;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.effects.ChangeZoneAllEffect;
|
||||
import forge.card.ability.effects.ChangeZoneEffect;
|
||||
import forge.card.ability.effects.ManaEffect;
|
||||
import forge.card.ability.effects.ManaReflectedEffect;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.spellability.AbilityManaPart;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Target;
|
||||
import forge.game.player.AIPlayer;
|
||||
|
||||
public class CommonDrawback extends AbilitySub {
|
||||
private final SpellEffect effect;
|
||||
private final SpellAiLogic ai;
|
||||
private static final long serialVersionUID = 6631124959690157874L;
|
||||
|
||||
public CommonDrawback(ApiType api0, final Card ca, final Target t, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
|
||||
super(ca, t);
|
||||
api = api0;
|
||||
params = params0;
|
||||
ai = ai0;
|
||||
effect = effect0;
|
||||
|
||||
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
|
||||
this.setManaPart(new AbilityManaPart(ca, params));
|
||||
}
|
||||
|
||||
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
|
||||
AbilityFactory.adjustChangeZoneTarget(params, this);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
Target t = getTarget() == null ? null : new Target(getTarget());
|
||||
AbilitySub res = new CommonDrawback(api, getSourceCard(), t, params, effect, ai);
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return effect.getStackDescriptionWithSubs(params, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return ai.canPlayAIWithSubs((AIPlayer)getActivatingPlayer(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
effect.resolve(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean chkAIDrawback(AIPlayer aiPlayer) {
|
||||
final AbilitySub subAb = getSubAbility();
|
||||
return ai.chkAIDrawback(this, aiPlayer) && (subAb == null || subAb.chkAIDrawback(aiPlayer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory, AIPlayer aiPlayer) {
|
||||
return ai.doTriggerAI(aiPlayer, this, mandatory);
|
||||
}
|
||||
}
|
||||
|
||||
// end class AbilityFactory_AlterLife
|
||||
@@ -18,18 +18,18 @@ public class CommonSpell extends Spell {
|
||||
private final SpellEffect effect;
|
||||
private final SpellAiLogic ai;
|
||||
|
||||
public CommonSpell(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0, SpellEffect effect0, SpellAiLogic ai0) {
|
||||
public CommonSpell(ApiType api0, Card sourceCard, Cost abCost, Target tgt, Map<String, String> params0) {
|
||||
super(sourceCard, abCost, tgt);
|
||||
params = params0;
|
||||
api = api0;
|
||||
effect = effect0;
|
||||
ai = ai0;
|
||||
effect = api.getSpellEffect();
|
||||
ai = api.getAi();
|
||||
|
||||
if (effect0 instanceof ManaEffect || effect0 instanceof ManaReflectedEffect) {
|
||||
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
|
||||
this.setManaPart(new AbilityManaPart(sourceCard, params));
|
||||
}
|
||||
|
||||
if (effect0 instanceof ChangeZoneEffect || effect0 instanceof ChangeZoneAllEffect) {
|
||||
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
|
||||
AbilityFactory.adjustChangeZoneTarget(params, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,10 +16,7 @@ public abstract class SpellAiLogic {
|
||||
return false;
|
||||
}
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null && !subAb.chkAIDrawbackWithSubs(aiPlayer)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return subAb == null || subAb.chkAIDrawback(aiPlayer);
|
||||
}
|
||||
|
||||
protected abstract boolean canPlayAI(final AIPlayer aiPlayer, final SpellAbility sa);
|
||||
|
||||
@@ -295,9 +295,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
chance &= (r.nextFloat() < .8);
|
||||
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback(ai);
|
||||
}
|
||||
chance &= subAb == null || subAb.chkAIDrawback(ai);
|
||||
|
||||
return chance;
|
||||
}
|
||||
@@ -589,13 +587,13 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
ApiType subAPI = null;
|
||||
ApiType subApi = null;
|
||||
if (abSub != null) {
|
||||
subAPI = abSub.getApi();
|
||||
subApi = abSub.getApi();
|
||||
}
|
||||
|
||||
// only use blink or bounce effects
|
||||
if (!(destination.equals(ZoneType.Exile) && (subAPI == ApiType.DelayedTrigger || subAPI == ApiType.ChangeZone))
|
||||
if (!(destination.equals(ZoneType.Exile) && (subApi == ApiType.DelayedTrigger || subApi == ApiType.ChangeZone))
|
||||
&& !destination.equals(ZoneType.Hand)) {
|
||||
return false;
|
||||
}
|
||||
@@ -629,11 +627,9 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
}
|
||||
|
||||
final AbilitySub subAb = sa.getSubAbility();
|
||||
if (subAb != null) {
|
||||
chance &= subAb.chkAIDrawback(ai);
|
||||
}
|
||||
chance &= subAb == null || subAb.chkAIDrawback(ai);
|
||||
|
||||
return (chance);
|
||||
return chance;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -676,10 +672,10 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
final Target tgt = sa.getTarget();
|
||||
|
||||
final AbilitySub abSub = sa.getSubAbility();
|
||||
ApiType subAPI = null;
|
||||
ApiType subApi = null;
|
||||
String subAffected = "";
|
||||
if (abSub != null) {
|
||||
subAPI = abSub.getApi();
|
||||
subApi = abSub.getApi();
|
||||
if (abSub.hasParam("Defined")) {
|
||||
subAffected = abSub.getParam("Defined");
|
||||
}
|
||||
@@ -714,7 +710,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
|
||||
// if it's blink or bounce, try to save my about to die stuff
|
||||
if ((destination.equals(ZoneType.Hand) || (destination.equals(ZoneType.Exile)
|
||||
&& (subAPI == ApiType.DelayedTrigger || (subAPI == ApiType.ChangeZone && subAffected.equals("Remembered")))))
|
||||
&& (subApi == ApiType.DelayedTrigger || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered")))))
|
||||
&& (tgt.getMinTargets(sa.getSourceCard(), sa) <= 1)) {
|
||||
|
||||
// check stack for something on the stack that will kill
|
||||
@@ -792,7 +788,7 @@ public class ChangeZoneAi extends SpellAiLogic {
|
||||
// blink human targets only during combat
|
||||
if (origin.equals(ZoneType.Battlefield)
|
||||
&& destination.equals(ZoneType.Exile)
|
||||
&& (subAPI == ApiType.DelayedTrigger || (subAPI == ApiType.ChangeZone && subAffected.equals("Remembered")))
|
||||
&& (subApi == ApiType.DelayedTrigger || (subApi == ApiType.ChangeZone && subAffected.equals("Remembered")))
|
||||
&& !(Singletons.getModel().getGame().getPhaseHandler().is(PhaseType.COMBAT_DECLARE_ATTACKERS_INSTANT_ABILITY) || sa
|
||||
.isAbility())) {
|
||||
return false;
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package forge.card.ability.effects;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.SpellEffect;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class ETBReplacementEffect extends SpellEffect {
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
forge.Singletons.getModel().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject("Card")));
|
||||
}
|
||||
}
|
||||
@@ -50,9 +50,7 @@ import forge.card.MagicColor;
|
||||
import forge.card.SpellManaCost;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.ability.CommonDrawback;
|
||||
import forge.card.ability.SpellEffect;
|
||||
import forge.card.ability.ai.CanPlayAsDrawbackAi;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCostParser;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
@@ -62,6 +60,7 @@ import forge.card.replacement.ReplacementLayer;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
import forge.card.spellability.AbilitySub;
|
||||
import forge.card.spellability.Spell;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.spellability.SpellAbilityRestriction;
|
||||
@@ -4469,14 +4468,7 @@ public class CardFactoryUtil {
|
||||
tailend = tailend.getSubAbility();
|
||||
}
|
||||
|
||||
class ETBReplacementEffect extends SpellEffect {
|
||||
@Override
|
||||
public void resolve(SpellAbility sa) {
|
||||
forge.Singletons.getModel().getGame().getAction().moveToPlay(((Card) sa.getReplacingObject("Card")));
|
||||
}
|
||||
}
|
||||
|
||||
tailend.setSubAbility(new CommonDrawback(null, sa.getSourceCard(), null, null, new ETBReplacementEffect(), new CanPlayAsDrawbackAi()));
|
||||
tailend.setSubAbility(new AbilitySub(ApiType.InternalEtbReplacement, sa.getSourceCard(), null, null));
|
||||
// ETBReplacementMove(sa.getSourceCard(), null));
|
||||
}
|
||||
|
||||
|
||||
@@ -17,7 +17,18 @@
|
||||
*/
|
||||
package forge.card.spellability;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import forge.Card;
|
||||
import forge.card.ability.AbilityFactory;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.card.ability.SpellAiLogic;
|
||||
import forge.card.ability.SpellEffect;
|
||||
import forge.card.ability.effects.ChangeZoneAllEffect;
|
||||
import forge.card.ability.effects.ChangeZoneEffect;
|
||||
import forge.card.ability.effects.ManaEffect;
|
||||
import forge.card.ability.effects.ManaReflectedEffect;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.game.player.AIPlayer;
|
||||
|
||||
/**
|
||||
@@ -28,61 +39,12 @@ import forge.game.player.AIPlayer;
|
||||
* @author Forge
|
||||
* @version $Id$
|
||||
*/
|
||||
public abstract class AbilitySub extends SpellAbility implements java.io.Serializable {
|
||||
public final class AbilitySub extends SpellAbility implements java.io.Serializable {
|
||||
/** Constant <code>serialVersionUID=4650634415821733134L</code>. */
|
||||
private static final long serialVersionUID = 4650634415821733134L;
|
||||
|
||||
private SpellAbility parent = null;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Constructor for Ability_Sub.
|
||||
* </p>
|
||||
*
|
||||
* @param sourceCard
|
||||
* a {@link forge.Card} object.
|
||||
* @param tgt
|
||||
* a {@link forge.card.spellability.Target} object.
|
||||
*/
|
||||
public AbilitySub(final Card sourceCard, final Target tgt) {
|
||||
super(sourceCard);
|
||||
this.setTarget(tgt);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
// this should never be on the Stack by itself
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* chkAI_Drawback.
|
||||
* </p>
|
||||
* @param ai TODO
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public abstract boolean chkAIDrawback(AIPlayer ai);
|
||||
|
||||
public final boolean chkAIDrawbackWithSubs(final AIPlayer aiPlayer) {
|
||||
if (!chkAIDrawback(aiPlayer)) {
|
||||
return false;
|
||||
}
|
||||
final AbilitySub subAb = this.getSubAbility();
|
||||
if (subAb != null && !subAb.chkAIDrawbackWithSubs(aiPlayer)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public abstract AbilitySub getCopy();
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public abstract boolean doTrigger(boolean mandatory, AIPlayer ai);
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>parent</code>.
|
||||
@@ -106,4 +68,66 @@ public abstract class AbilitySub extends SpellAbility implements java.io.Seriali
|
||||
public final SpellAbility getParent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean canPlay() {
|
||||
// this should never be on the Stack by itself
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private final SpellEffect effect;
|
||||
private final SpellAiLogic ai;
|
||||
|
||||
public AbilitySub(ApiType api0, final Card ca, final Target tgt, Map<String, String> params0) {
|
||||
super(ca);
|
||||
this.setTarget(tgt);
|
||||
api = api0;
|
||||
params = params0;
|
||||
ai = api.getAi();
|
||||
effect = api.getSpellEffect();
|
||||
|
||||
if (effect instanceof ManaEffect || effect instanceof ManaReflectedEffect) {
|
||||
this.setManaPart(new AbilityManaPart(ca, params));
|
||||
}
|
||||
|
||||
if (effect instanceof ChangeZoneEffect || effect instanceof ChangeZoneAllEffect) {
|
||||
AbilityFactory.adjustChangeZoneTarget(params, this);
|
||||
}
|
||||
}
|
||||
|
||||
public AbilitySub getCopy() {
|
||||
Target t = getTarget() == null ? null : new Target(getTarget());
|
||||
AbilitySub res = new AbilitySub(api, getSourceCard(), t, params);
|
||||
CardFactoryUtil.copySpellAbility(this, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getStackDescription() {
|
||||
return effect.getStackDescriptionWithSubs(params, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canPlayAI() {
|
||||
return ai.canPlayAIWithSubs((AIPlayer)getActivatingPlayer(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
effect.resolve(this);
|
||||
}
|
||||
|
||||
public boolean chkAIDrawback(AIPlayer aiPlayer) {
|
||||
final AbilitySub subAb = getSubAbility();
|
||||
return ai.chkAIDrawback(this, aiPlayer) && (subAb == null || subAb.chkAIDrawback(aiPlayer));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean doTrigger(final boolean mandatory, AIPlayer aiPlayer) {
|
||||
return ai.doTriggerAI(aiPlayer, this, mandatory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import forge.Singletons;
|
||||
|
||||
import forge.CardLists;
|
||||
import forge.card.ability.AbilityUtils;
|
||||
import forge.card.ability.ApiType;
|
||||
import forge.control.input.Input;
|
||||
import forge.game.player.Player;
|
||||
import forge.game.zone.ZoneType;
|
||||
@@ -442,11 +443,11 @@ public class TargetSelection {
|
||||
choices[i - 1] = i;
|
||||
}
|
||||
String apiBasedMessage = "Distribute how much to ";
|
||||
if (sa.getApi().toString().equals("DealDamage")) {
|
||||
if (sa.getApi() == ApiType.DealDamage) {
|
||||
apiBasedMessage = "Select how much damage to deal to ";
|
||||
} else if (sa.getApi().toString().equals("PreventDamage")) {
|
||||
} else if (sa.getApi() == ApiType.PreventDamage) {
|
||||
apiBasedMessage = "Select how much damage to prevent to ";
|
||||
} else if (sa.getApi().toString().equals("PutCounter")) {
|
||||
} else if (sa.getApi() == ApiType.PutCounter) {
|
||||
apiBasedMessage = "Select how many counters to distribute to ";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
@@ -486,9 +487,9 @@ public class TargetSelection {
|
||||
choices[i - 1] = i;
|
||||
}
|
||||
String apiBasedMessage = "Distribute how much to ";
|
||||
if (sa.getApi().toString().equals("DealDamage")) {
|
||||
if (sa.getApi() == ApiType.DealDamage) {
|
||||
apiBasedMessage = "Select how much damage to deal to ";
|
||||
} else if (sa.getApi().toString().equals("PreventDamage")) {
|
||||
} else if (sa.getApi() == ApiType.PreventDamage) {
|
||||
apiBasedMessage = "Select how much damage to prevent to ";
|
||||
}
|
||||
final StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -69,7 +69,7 @@ public abstract class InputPayManaBase extends Input {
|
||||
if (m.isAnyMana()) {
|
||||
return true;
|
||||
}
|
||||
if (am.getApi().equals(ApiType.ManaReflected)) {
|
||||
if (am.getApi() == ApiType.ManaReflected) {
|
||||
final Iterable<String> reflectableColors = CardUtil.getReflectableManaColors(am, am, new HashSet<String>(), new ArrayList<Card>());
|
||||
for (final String color : reflectableColors) {
|
||||
if (mana.contains(MagicColor.toShortString(color))) {
|
||||
@@ -228,7 +228,7 @@ public abstract class InputPayManaBase extends Input {
|
||||
|
||||
for (final SpellAbility am : abilities) {
|
||||
AbilityManaPart m = am.getManaPart();
|
||||
if (am.getApi().equals(ApiType.ManaReflected)) {
|
||||
if (am.getApi() == ApiType.ManaReflected) {
|
||||
final Iterable<String> reflectableColors = CardUtil.getReflectableManaColors(am, am, new HashSet<String>(), new ArrayList<Card>());
|
||||
for (final String color : reflectableColors) {
|
||||
if (manaCost.isColor(color)) {
|
||||
|
||||
@@ -1533,7 +1533,7 @@ public final class GameActionUtil {
|
||||
baseMana = "Any";
|
||||
}
|
||||
}
|
||||
else if (sa.getApi().equals(ApiType.ManaReflected)) {
|
||||
else if (sa.getApi() == ApiType.ManaReflected) {
|
||||
baseMana = abMana.getExpressChoice();
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -132,7 +132,7 @@ public class ComputerUtilMana {
|
||||
m.setExpressChoice(colorChoice);
|
||||
colorChoice = ComputerUtilMana.getComboManaChoice(ai, ma, sa, cost);
|
||||
m.setExpressChoice(colorChoice);
|
||||
} else if (ma.getApi().equals(ApiType.ManaReflected)) {
|
||||
} else if (ma.getApi() == ApiType.ManaReflected) {
|
||||
if (CardUtil.getReflectableManaColors(ma, ma, new HashSet<String>(), new ArrayList<Card>()).contains(MagicColor.toLongString(costParts[nPart]))) {
|
||||
m.setExpressChoice(costParts[nPart]);
|
||||
} else {
|
||||
|
||||
31
src/main/java/forge/util/ReflectionUtil.java
Normal file
31
src/main/java/forge/util/ReflectionUtil.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package forge.util;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public class ReflectionUtil {
|
||||
|
||||
public static <T> T makeDefaultInstanceOf(Class<? extends T> cls) {
|
||||
if ( null == cls )
|
||||
throw new IllegalArgumentException("Class<? extends T> cls must not be null");
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Constructor<? extends T>[] cc = (Constructor<? extends T>[]) cls.getConstructors();
|
||||
for (Constructor<? extends T> c : cc) {
|
||||
Class<?>[] pp = c.getParameterTypes();
|
||||
if (pp.length == 0) {
|
||||
try {
|
||||
T res = c.newInstance();
|
||||
return res;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new RuntimeException("No default constructor found in class " + cls.getName());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user