mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-19 04:08:01 +00:00
*Added ETBReplacement:<Mode>:<SVar>[:Optional] keyword.
*Added ActiveZones parameter to replacement effects to let replacement effects function wherever. *Converted clones to ETBReplacement *Added Essence of the Wild *CardCharacteristics now copy ReplacementEffects *ReplacementEffects now copy alot more stuff. *Divvied up Replacement Effect running into layers *Moved stuff common between Trigger and ReplacementEffect to TriggerReplacementBase *Let AF_Tap tap cards on the stack in order to work with ETBReplacement. *Converted Remote Farm to ETBReplacement.
This commit is contained in:
@@ -41,6 +41,7 @@ import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
import forge.card.replacement.ReplacementResult;
|
||||
import forge.card.spellability.AbilityMana;
|
||||
import forge.card.spellability.AbilityTriggered;
|
||||
import forge.card.spellability.Spell;
|
||||
@@ -2322,6 +2323,8 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
sbLong.append("defending player controls untap and block it if able.)");
|
||||
} else if (keyword.get(i).startsWith("MayEffectFromOpeningHand")) {
|
||||
continue;
|
||||
} else if (keyword.get(i).startsWith("ETBReplacement")) {
|
||||
continue;
|
||||
} else if (keyword.get(i).contains("Haunt")) {
|
||||
sb.append("\r\nHaunt (");
|
||||
if (this.isCreature()) {
|
||||
@@ -5079,6 +5082,9 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
* </p>
|
||||
*/
|
||||
public final void untap() {
|
||||
if(getName().equals("Remote Farm")) {
|
||||
System.out.println("HE TOUCHED ME");
|
||||
}
|
||||
if (this.isTapped()) {
|
||||
// Run triggers
|
||||
final Map<String, Object> runParams = new TreeMap<String, Object>();
|
||||
@@ -8065,7 +8071,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
repParams.put("IsCombat", isCombat);
|
||||
repParams.put("Prevention", true);
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -8192,7 +8198,7 @@ public class Card extends GameEntity implements Comparable<Card> {
|
||||
repParams.put("DamageAmount", damageIn);
|
||||
repParams.put("IsCombat", isCombat);
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import forge.card.cost.Cost;
|
||||
import forge.card.cost.CostPayment;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
import forge.card.replacement.ReplacementResult;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
@@ -128,8 +129,9 @@ public class GameAction {
|
||||
repParams.put("Origin", zoneFrom != null ? zoneFrom.getZoneType() : null);
|
||||
repParams.put("Destination", zoneTo.getZoneType());
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getStack().isResolving(c) && !zoneTo.is(ZoneType.Graveyard)) {
|
||||
ReplacementResult repres = AllZone.getReplacementHandler().run(repParams);
|
||||
if (repres != ReplacementResult.NotReplaced) {
|
||||
if (AllZone.getStack().isResolving(c) && !zoneTo.is(ZoneType.Graveyard) && repres == ReplacementResult.Prevented) {
|
||||
return Singletons.getModel().getGameAction().moveToGraveyard(c);
|
||||
}
|
||||
return c;
|
||||
|
||||
@@ -488,6 +488,11 @@ public class CardCharacteristics {
|
||||
this.sVars = new TreeMap<String, String>(source.getSVars());
|
||||
// String curSetCode = "";
|
||||
this.curSetCode = source.getCurSetCode();
|
||||
|
||||
this.replacementEffects = new ArrayList<ReplacementEffect>();
|
||||
for(ReplacementEffect RE : source.getReplacementEffects()) {
|
||||
this.replacementEffects.add(RE.getCopy());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,7 +1,12 @@
|
||||
package forge.card;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
import forge.Card;
|
||||
import forge.GameEntity;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.game.zone.PlayerZone;
|
||||
import forge.game.zone.ZoneType;
|
||||
|
||||
/**
|
||||
* Base class for Triggers and ReplacementEffects.
|
||||
@@ -9,6 +14,75 @@ import forge.GameEntity;
|
||||
*
|
||||
*/
|
||||
public abstract class TriggerReplacementBase {
|
||||
|
||||
/** The host card. */
|
||||
protected Card hostCard;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public final Card getHostCard() {
|
||||
return this.hostCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
*/
|
||||
public final void setHostCard(final Card c) {
|
||||
this.hostCard = c;
|
||||
}
|
||||
|
||||
protected EnumSet<ZoneType> validHostZones;
|
||||
|
||||
public void setActiveZone(EnumSet<ZoneType> zones) {
|
||||
validHostZones = zones;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* zonesCheck.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean zonesCheck(PlayerZone hostCardZone) {
|
||||
return !this.hostCard.isPhasedOut()
|
||||
&& (validHostZones == null || validHostZones.isEmpty()
|
||||
|| (hostCardZone != null && validHostZones.contains(hostCardZone.getZoneType()))
|
||||
);
|
||||
}
|
||||
|
||||
/** The overriding ability. */
|
||||
private SpellAbility overridingAbility = null;
|
||||
|
||||
/**
|
||||
* Gets the overriding ability.
|
||||
*
|
||||
* @return the overridingAbility
|
||||
*/
|
||||
public SpellAbility getOverridingAbility() {
|
||||
return this.overridingAbility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the overriding ability.
|
||||
*
|
||||
* @param overridingAbility0
|
||||
* the overridingAbility to set
|
||||
*/
|
||||
public void setOverridingAbility(final SpellAbility overridingAbility0) {
|
||||
this.overridingAbility = overridingAbility0;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* matchesValid.
|
||||
|
||||
@@ -2823,6 +2823,10 @@ public class AbilityFactory {
|
||||
final AbilityFactory af = sa.getAbilityFactory();
|
||||
if (af == null) {
|
||||
sa.resolve();
|
||||
if(sa.getSubAbility() != null)
|
||||
{
|
||||
resolve(sa.getSubAbility(),usedStack);
|
||||
}
|
||||
return;
|
||||
}
|
||||
final HashMap<String, String> params = af.getMapParams();
|
||||
|
||||
@@ -1228,7 +1228,7 @@ public class AbilityFactoryPermanentState {
|
||||
}
|
||||
|
||||
for (final Card tgtC : tgtCards) {
|
||||
if (AllZoneUtil.isCardInPlay(tgtC) && ((tgt == null) || tgtC.canBeTargetedBy(sa))) {
|
||||
if ((AllZoneUtil.isCardInPlay(tgtC) || AllZone.getZoneOf(tgtC).is(ZoneType.Stack)) && ((tgt == null) || tgtC.canBeTargetedBy(sa))) {
|
||||
if (tgtC.isUntapped() && (remTapped)) {
|
||||
card.addRemembered(tgtC);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.esotericsoftware.minlog.Log;
|
||||
import forge.AllZone;
|
||||
import forge.AllZoneUtil;
|
||||
import forge.Card;
|
||||
import forge.CardCharacteristicName;
|
||||
import forge.CardList;
|
||||
import forge.CardListFilter;
|
||||
import forge.CardUtil;
|
||||
@@ -36,6 +37,9 @@ import forge.Counters;
|
||||
import forge.Singletons;
|
||||
import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
import forge.card.replacement.ReplacementHandler;
|
||||
import forge.card.replacement.ReplacementLayer;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityStatic;
|
||||
@@ -1476,6 +1480,47 @@ public class CardFactoryCreatures {
|
||||
|
||||
card.addSpellAbility(finalAb);
|
||||
}
|
||||
|
||||
private static void getCard_EssenceOfTheWild(final Card card,final String cardName) {
|
||||
class EOTWReplacement extends Ability {
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sourceCard
|
||||
* @param manaCost
|
||||
*/
|
||||
public EOTWReplacement(Card sourceCard, String manaCost) {
|
||||
super(sourceCard, manaCost);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.SpellAbility#resolve()
|
||||
*/
|
||||
@Override
|
||||
public void resolve() {
|
||||
Card movedCard = (Card)this.getReplacingObject("Card");
|
||||
if (movedCard.isCloned()) { // cloning again
|
||||
movedCard.switchStates(CardCharacteristicName.Cloner, CardCharacteristicName.Original);
|
||||
movedCard.setState(CardCharacteristicName.Original);
|
||||
movedCard.clearStates(CardCharacteristicName.Cloner);
|
||||
}
|
||||
movedCard.addAlternateState(CardCharacteristicName.Cloner);
|
||||
movedCard.switchStates(CardCharacteristicName.Original, CardCharacteristicName.Cloner);
|
||||
movedCard.setState(CardCharacteristicName.Original);
|
||||
movedCard.getCharacteristics().copy(this.getSourceCard().getCharacteristics());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
SpellAbility repAb = new EOTWReplacement(card,"0");
|
||||
CardFactoryUtil.setupETBReplacementAbility(repAb);
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement("Event$ Moved | ValidCard$ Creature.Other+YouCtrl | Destination$ Battlefield | ActiveZones$ Battlefield | Description$ Creatures you control enter the battlefield as copies of CARDNAME.", card);
|
||||
re.setLayer(ReplacementLayer.Copy);
|
||||
re.setOverridingAbility(repAb);
|
||||
|
||||
card.addReplacementEffect(re);
|
||||
}
|
||||
|
||||
// // This is a hardcoded card template
|
||||
//
|
||||
@@ -1532,7 +1577,10 @@ public class CardFactoryCreatures {
|
||||
} else if (cardName.equals("Duct Crawler") || cardName.equals("Shrewd Hatchling")
|
||||
|| cardName.equals("Spin Engine") || cardName.equals("Screeching Griffin")) {
|
||||
getCard_DuctCrawler(card, cardName);
|
||||
} else if (cardName.equals("Essence of the Wild")) {
|
||||
getCard_EssenceOfTheWild(card, cardName);
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************
|
||||
// end of card specific code
|
||||
|
||||
@@ -46,10 +46,14 @@ import forge.card.abilityfactory.AbilityFactory;
|
||||
import forge.card.cost.Cost;
|
||||
import forge.card.mana.ManaCost;
|
||||
import forge.card.mana.ManaCostShard;
|
||||
import forge.card.replacement.ReplacementEffect;
|
||||
import forge.card.replacement.ReplacementHandler;
|
||||
import forge.card.replacement.ReplacementLayer;
|
||||
import forge.card.spellability.Ability;
|
||||
import forge.card.spellability.AbilityActivated;
|
||||
import forge.card.spellability.AbilityMana;
|
||||
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;
|
||||
@@ -4807,9 +4811,89 @@ public class CardFactoryUtil {
|
||||
// add ability to instrinic strings so copies/clones create the ability also
|
||||
card.getIntrinsicAbilities().add(abilityStr.toString());
|
||||
}
|
||||
|
||||
final int etbrep = CardFactoryUtil.hasKeyword(card, "ETBReplacement");
|
||||
if (etbrep != -1)
|
||||
{
|
||||
String fullkw = card.getKeyword().get(etbrep);
|
||||
card.getKeyword().remove(etbrep);
|
||||
String[] splitkw = fullkw.split(":");
|
||||
ReplacementLayer layer = ReplacementLayer.smartValueOf(splitkw[1]);
|
||||
AbilityFactory af = new AbilityFactory();
|
||||
SpellAbility repAb = af.getAbility(card.getSVar(splitkw[2]), card);
|
||||
String desc = repAb.getDescription();
|
||||
setupETBReplacementAbility(repAb);
|
||||
|
||||
String repeffstr = "Event$ Moved | ValidCard$ Card.Self | Destination$ Battlefield | Description$ " + desc;
|
||||
if(splitkw.length == 4) {
|
||||
if(splitkw[3].contains("Optional")) {
|
||||
repeffstr += " | OptionalDecider$ You";
|
||||
}
|
||||
}
|
||||
|
||||
ReplacementEffect re = ReplacementHandler.parseReplacement(repeffstr, card);
|
||||
re.setLayer(layer);
|
||||
re.setOverridingAbility(repAb);
|
||||
|
||||
card.addReplacementEffect(re);
|
||||
}
|
||||
|
||||
return card;
|
||||
}
|
||||
|
||||
public static void setupETBReplacementAbility(SpellAbility sa) {
|
||||
SpellAbility tailend = sa;
|
||||
while(tailend.getSubAbility() != null) {
|
||||
tailend = tailend.getSubAbility();
|
||||
}
|
||||
|
||||
class ETBReplacementMove extends AbilitySub {
|
||||
private static final long serialVersionUID = 704771599662730112L;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for Constructor.
|
||||
* @param sourceCard
|
||||
* @param tgt
|
||||
*/
|
||||
public ETBReplacementMove(Card sourceCard, Target tgt) {
|
||||
super(sourceCard, tgt);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resolve() {
|
||||
forge.Singletons.getModel().getGameAction().moveToPlay(((Card)this.getReplacingObject("Card")));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.AbilitySub#chkAIDrawback()
|
||||
*/
|
||||
@Override
|
||||
public boolean chkAIDrawback() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.AbilitySub#getCopy()
|
||||
*/
|
||||
@Override
|
||||
public AbilitySub getCopy() {
|
||||
// TODO Auto-generated method stub
|
||||
return new ETBReplacementMove(getSourceCard(),null);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see forge.card.spellability.AbilitySub#doTrigger(boolean)
|
||||
*/
|
||||
@Override
|
||||
public boolean doTrigger(boolean mandatory) {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tailend.setSubAbility(new ETBReplacementMove(sa.getSourceCard(),null));
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
|
||||
@@ -100,7 +100,11 @@ public class ReplaceDamage extends ReplacementEffect {
|
||||
*/
|
||||
@Override
|
||||
public ReplacementEffect getCopy() {
|
||||
return new ReplaceDamage(this.getMapParams(), this.getHostCard());
|
||||
ReplacementEffect res = new ReplaceDamage(this.getMapParams(), this.getHostCard());
|
||||
res.setOverridingAbility(this.getOverridingAbility());
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -59,7 +59,11 @@ public class ReplaceDraw extends ReplacementEffect {
|
||||
*/
|
||||
@Override
|
||||
public ReplacementEffect getCopy() {
|
||||
return new ReplaceDraw(this.getMapParams(), getHostCard());
|
||||
ReplacementEffect res = new ReplaceDraw(this.getMapParams(), this.getHostCard());
|
||||
res.setOverridingAbility(this.getOverridingAbility());
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -60,7 +60,11 @@ public class ReplaceGainLife extends ReplacementEffect {
|
||||
*/
|
||||
@Override
|
||||
public ReplacementEffect getCopy() {
|
||||
return new ReplaceGainLife(this.getMapParams(), getHostCard());
|
||||
ReplacementEffect res = new ReplaceGainLife(this.getMapParams(), this.getHostCard());
|
||||
res.setOverridingAbility(this.getOverridingAbility());
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -42,7 +42,11 @@ public class ReplaceGameLoss extends ReplacementEffect {
|
||||
*/
|
||||
@Override
|
||||
public ReplacementEffect getCopy() {
|
||||
return new ReplaceGameLoss(this.getMapParams(), getHostCard());
|
||||
ReplacementEffect res = new ReplaceGameLoss(this.getMapParams(), this.getHostCard());
|
||||
res.setOverridingAbility(this.getOverridingAbility());
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -56,7 +56,11 @@ public class ReplaceMoved extends ReplacementEffect {
|
||||
*/
|
||||
@Override
|
||||
public ReplacementEffect getCopy() {
|
||||
return new ReplaceMoved(this.getMapParams(), this.getHostCard());
|
||||
ReplacementEffect res = new ReplaceMoved(this.getMapParams(), this.getHostCard());
|
||||
res.setOverridingAbility(this.getOverridingAbility());
|
||||
res.setActiveZone(validHostZones);
|
||||
res.setLayer(getLayer());
|
||||
return res;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -35,6 +35,8 @@ import forge.game.zone.ZoneType;
|
||||
*/
|
||||
public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
|
||||
private ReplacementLayer layer = ReplacementLayer.None;
|
||||
|
||||
/** The has run. */
|
||||
private boolean hasRun = false;
|
||||
|
||||
@@ -135,32 +137,6 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
this.mapParams = mapParams;
|
||||
}
|
||||
|
||||
/** The host card. */
|
||||
private Card hostCard;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public final Card getHostCard() {
|
||||
return this.hostCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
*/
|
||||
public final void setHostCard(final Card c) {
|
||||
this.hostCard = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can replace.
|
||||
*
|
||||
@@ -415,4 +391,18 @@ public abstract class ReplacementEffect extends TriggerReplacementBase {
|
||||
this.setMapParams(map);
|
||||
this.setHostCard(host);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the layer
|
||||
*/
|
||||
public ReplacementLayer getLayer() {
|
||||
return layer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param layer0 the layer to set
|
||||
*/
|
||||
public void setLayer(ReplacementLayer layer0) {
|
||||
this.layer = layer0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package forge.card.replacement;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.EnumSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
@@ -40,17 +41,8 @@ public class ReplacementHandler {
|
||||
|
||||
private final List<ReplacementEffect> tmpEffects = new ArrayList<ReplacementEffect>();
|
||||
|
||||
/**
|
||||
*
|
||||
* Runs any applicable replacement effects.
|
||||
*
|
||||
* @param runParams
|
||||
* the run params,same as for triggers.
|
||||
* @return true if the event was replaced.
|
||||
*/
|
||||
public boolean run(final HashMap<String, Object> runParams) {
|
||||
public ReplacementResult run(final HashMap<String, Object> runParams) {
|
||||
final Object affected = runParams.get("Affected");
|
||||
final List<ReplacementEffect> possibleReplacers = new ArrayList<ReplacementEffect>();
|
||||
Player decider = null;
|
||||
|
||||
// Figure out who decides which of multiple replacements to apply
|
||||
@@ -60,21 +52,66 @@ public class ReplacementHandler {
|
||||
} else {
|
||||
decider = ((Card) affected).getController();
|
||||
}
|
||||
|
||||
|
||||
if(runParams.get("Event").equals("Moved")) {
|
||||
ReplacementResult res = run(runParams,ReplacementLayer.Control,decider);
|
||||
if(res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams,ReplacementLayer.Copy,decider);
|
||||
if(res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams,ReplacementLayer.Other,decider);
|
||||
if(res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
res = run(runParams,ReplacementLayer.None,decider);
|
||||
if(res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ReplacementResult res = run(runParams,ReplacementLayer.None,decider);
|
||||
if(res != ReplacementResult.NotReplaced) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return ReplacementResult.NotReplaced;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Runs any applicable replacement effects.
|
||||
*
|
||||
* @param runParams
|
||||
* the run params,same as for triggers.
|
||||
* @return true if the event was replaced.
|
||||
*/
|
||||
public ReplacementResult run(final HashMap<String, Object> runParams, final ReplacementLayer layer,final Player decider) {
|
||||
|
||||
final List<ReplacementEffect> possibleReplacers = new ArrayList<ReplacementEffect>();
|
||||
if(layer == ReplacementLayer.Other && ((String)runParams.get("Event")).equals("Moved")) {
|
||||
System.out.println("Shdf");
|
||||
}
|
||||
|
||||
// Round up Non-static replacement effects ("Until EOT," or
|
||||
// "The next time you would..." etc)
|
||||
for (final ReplacementEffect replacementEffect : this.tmpEffects) {
|
||||
if (!replacementEffect.hasRun() && replacementEffect.canReplace(runParams)) {
|
||||
if (!replacementEffect.hasRun() && replacementEffect.canReplace(runParams) && replacementEffect.getLayer() == layer) {
|
||||
possibleReplacers.add(replacementEffect);
|
||||
}
|
||||
}
|
||||
|
||||
// Round up Static replacement effects
|
||||
for (final Player p : AllZone.getPlayersInGame()) {
|
||||
for (final Card crd : p.getCardsIn(ZoneType.Battlefield)) {
|
||||
for (final Card crd : p.getAllCards()) {
|
||||
for (final ReplacementEffect replacementEffect : crd.getReplacementEffects()) {
|
||||
if (replacementEffect.requirementsCheck()) {
|
||||
if (!replacementEffect.hasRun() && replacementEffect.canReplace(runParams)) {
|
||||
if (!replacementEffect.hasRun() && replacementEffect.canReplace(runParams) && replacementEffect.getLayer() == layer && replacementEffect.zonesCheck(AllZone.getZoneOf(crd))) {
|
||||
possibleReplacers.add(replacementEffect);
|
||||
}
|
||||
}
|
||||
@@ -83,7 +120,7 @@ public class ReplacementHandler {
|
||||
}
|
||||
|
||||
if (possibleReplacers.isEmpty()) {
|
||||
return false;
|
||||
return ReplacementResult.NotReplaced;
|
||||
}
|
||||
|
||||
ReplacementEffect chosenRE = null;
|
||||
@@ -106,23 +143,24 @@ public class ReplacementHandler {
|
||||
possibleReplacers.remove(chosenRE);
|
||||
|
||||
if (chosenRE != null) {
|
||||
chosenRE.setHasRun(true);
|
||||
if (this.executeReplacement(runParams, chosenRE, decider)) {
|
||||
chosenRE.setHasRun(true);
|
||||
ReplacementResult res = this.executeReplacement(runParams, chosenRE, decider);
|
||||
if (res != ReplacementResult.NotReplaced) {
|
||||
chosenRE.setHasRun(false);
|
||||
AllZone.getGameLog().add("ReplacementEffect", chosenRE.toString(), 2);
|
||||
return true;
|
||||
return res;
|
||||
} else {
|
||||
if (possibleReplacers.size() == 0) {
|
||||
return false;
|
||||
return res;
|
||||
}
|
||||
else {
|
||||
boolean ret = run(runParams);
|
||||
ReplacementResult ret = run(runParams);
|
||||
chosenRE.setHasRun(false);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
return ReplacementResult.NotReplaced;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -134,9 +172,11 @@ public class ReplacementHandler {
|
||||
* @param replacementEffect
|
||||
* the replacement effect to run
|
||||
*/
|
||||
private boolean executeReplacement(final HashMap<String, Object> runParams,
|
||||
private ReplacementResult executeReplacement(final HashMap<String, Object> runParams,
|
||||
final ReplacementEffect replacementEffect, final Player decider) {
|
||||
|
||||
if(replacementEffect.getHostCard().getName().equals("Clone")) {
|
||||
System.out.println("And here we go.");
|
||||
}
|
||||
final HashMap<String, String> mapParams = replacementEffect.getMapParams();
|
||||
|
||||
SpellAbility effectSA = null;
|
||||
@@ -149,7 +189,21 @@ public class ReplacementHandler {
|
||||
|
||||
effectSA = abilityFactory.getAbility(effectAbString, replacementEffect.getHostCard());
|
||||
|
||||
replacementEffect.setReplacingObjects(runParams, effectSA);
|
||||
SpellAbility tailend = effectSA;
|
||||
do
|
||||
{
|
||||
replacementEffect.setReplacingObjects(runParams, tailend);
|
||||
tailend = tailend.getSubAbility();
|
||||
} while(tailend != null);
|
||||
}
|
||||
else if (replacementEffect.getOverridingAbility() != null) {
|
||||
effectSA = replacementEffect.getOverridingAbility();
|
||||
SpellAbility tailend = effectSA;
|
||||
do
|
||||
{
|
||||
replacementEffect.setReplacingObjects(runParams, tailend);
|
||||
tailend = tailend.getSubAbility();
|
||||
} while(tailend != null);
|
||||
}
|
||||
|
||||
// Decider gets to choose wether or not to apply the replacement.
|
||||
@@ -168,19 +222,19 @@ public class ReplacementHandler {
|
||||
buildQuestion.append(replacementEffect.toString());
|
||||
buildQuestion.append(")");
|
||||
if (!GameActionUtil.showYesNoDialog(replacementEffect.getHostCard(), buildQuestion.toString())) {
|
||||
return false;
|
||||
return ReplacementResult.NotReplaced;
|
||||
}
|
||||
} else {
|
||||
// AI-logic
|
||||
if (!replacementEffect.aiShouldRun(effectSA)) {
|
||||
return false;
|
||||
return ReplacementResult.NotReplaced;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mapParams.containsKey("Prevent")) {
|
||||
if (mapParams.get("Prevent").equals("True")) {
|
||||
return true; // Nothing should replace the event.
|
||||
return ReplacementResult.Prevented; // Nothing should replace the event.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +244,7 @@ public class ReplacementHandler {
|
||||
ComputerUtil.playNoStack(effectSA);
|
||||
}
|
||||
|
||||
return true;
|
||||
return ReplacementResult.Replaced;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -235,6 +289,11 @@ public class ReplacementHandler {
|
||||
} else if (eventToReplace.equals("Moved")) {
|
||||
ret = new ReplaceMoved(mapParams, host);
|
||||
}
|
||||
|
||||
String activeZones = mapParams.get("ActiveZones");
|
||||
if (null != activeZones) {
|
||||
ret.setActiveZone(EnumSet.copyOf(ZoneType.listValueOf(activeZones)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
32
src/main/java/forge/card/replacement/ReplacementLayer.java
Normal file
32
src/main/java/forge/card/replacement/ReplacementLayer.java
Normal file
@@ -0,0 +1,32 @@
|
||||
package forge.card.replacement;
|
||||
|
||||
import forge.CardCharacteristicName;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum ReplacementLayer {
|
||||
Control,
|
||||
Copy,
|
||||
Other,
|
||||
None;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this method.
|
||||
* @param substring
|
||||
* @return
|
||||
*/
|
||||
public static ReplacementLayer smartValueOf(String value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
final String valToCompate = value.trim();
|
||||
for (final ReplacementLayer v : ReplacementLayer.values()) {
|
||||
if (v.name().compareToIgnoreCase(valToCompate) == 0) {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("No element named " + value + " in enum ReplacementLayer");
|
||||
}
|
||||
}
|
||||
11
src/main/java/forge/card/replacement/ReplacementResult.java
Normal file
11
src/main/java/forge/card/replacement/ReplacementResult.java
Normal file
@@ -0,0 +1,11 @@
|
||||
package forge.card.replacement;
|
||||
|
||||
/**
|
||||
* TODO: Write javadoc for this type.
|
||||
*
|
||||
*/
|
||||
public enum ReplacementResult {
|
||||
Replaced,
|
||||
NotReplaced,
|
||||
Prevented;
|
||||
}
|
||||
@@ -127,8 +127,7 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
|
||||
private TriggerType mode;
|
||||
|
||||
/** The overriding ability. */
|
||||
private SpellAbility overridingAbility = null;
|
||||
|
||||
|
||||
private HashMap<String, Object> storedTriggeredObjects = null;
|
||||
|
||||
@@ -157,32 +156,6 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
return this.storedTriggeredObjects;
|
||||
}
|
||||
|
||||
/** The host card. */
|
||||
private Card hostCard;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Getter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @return a {@link forge.Card} object.
|
||||
*/
|
||||
public final Card getHostCard() {
|
||||
return this.hostCard;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Setter for the field <code>hostCard</code>.
|
||||
* </p>
|
||||
*
|
||||
* @param c
|
||||
* a {@link forge.Card} object.
|
||||
*/
|
||||
public final void setHostCard(final Card c) {
|
||||
this.hostCard = c;
|
||||
}
|
||||
|
||||
/** The is intrinsic. */
|
||||
private boolean isIntrinsic;
|
||||
|
||||
@@ -251,20 +224,6 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* zonesCheck.
|
||||
* </p>
|
||||
*
|
||||
* @return a boolean.
|
||||
*/
|
||||
public final boolean zonesCheck(PlayerZone hostCardZone) {
|
||||
return !this.getHostCard().isPhasedOut()
|
||||
&& (validHostZones == null || validHostZones.isEmpty()
|
||||
|| (hostCardZone != null && validHostZones.contains(hostCardZone.getZoneType()))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* phasesCheck.
|
||||
@@ -560,7 +519,7 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
|
||||
/** The temporary. */
|
||||
private boolean temporary = false;
|
||||
private EnumSet<ZoneType> validHostZones;
|
||||
|
||||
|
||||
/**
|
||||
* Sets the temporary.
|
||||
@@ -619,25 +578,6 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
this.runParams = runParams0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the overriding ability.
|
||||
*
|
||||
* @return the overridingAbility
|
||||
*/
|
||||
public SpellAbility getOverridingAbility() {
|
||||
return this.overridingAbility;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the overriding ability.
|
||||
*
|
||||
* @param overridingAbility0
|
||||
* the overridingAbility to set
|
||||
*/
|
||||
public void setOverridingAbility(final SpellAbility overridingAbility0) {
|
||||
this.overridingAbility = overridingAbility0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id.
|
||||
*
|
||||
@@ -683,18 +623,13 @@ public abstract class Trigger extends TriggerReplacementBase {
|
||||
copy.setID(this.getId());
|
||||
copy.setMode(this.getMode());
|
||||
copy.setTriggerPhases(this.validPhases);
|
||||
copy.setTriggerZone(validHostZones);
|
||||
copy.setActiveZone(validHostZones);
|
||||
}
|
||||
|
||||
public boolean isStatic() {
|
||||
return getMapParams().containsKey("Static"); // && params.get("Static").equals("True") [always true if present]
|
||||
}
|
||||
|
||||
|
||||
public void setTriggerZone(EnumSet<ZoneType> zones) {
|
||||
validHostZones = zones;
|
||||
}
|
||||
|
||||
public void setTriggerPhases(List<PhaseType> phases) {
|
||||
validPhases = phases;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ public class TriggerHandler {
|
||||
|
||||
String triggerZones = mapParams.get("TriggerZones");
|
||||
if (null != triggerZones) {
|
||||
ret.setTriggerZone(EnumSet.copyOf(ZoneType.listValueOf(triggerZones)));
|
||||
ret.setActiveZone(EnumSet.copyOf(ZoneType.listValueOf(triggerZones)));
|
||||
}
|
||||
|
||||
String triggerPhases = mapParams.get("Phase");
|
||||
|
||||
@@ -39,6 +39,7 @@ import forge.GameEntity;
|
||||
import forge.Singletons;
|
||||
import forge.card.cardfactory.CardFactoryUtil;
|
||||
import forge.card.mana.ManaPool;
|
||||
import forge.card.replacement.ReplacementResult;
|
||||
import forge.card.spellability.SpellAbility;
|
||||
import forge.card.staticability.StaticAbility;
|
||||
import forge.card.trigger.TriggerType;
|
||||
@@ -142,7 +143,7 @@ public abstract class Player extends GameEntity {
|
||||
|
||||
/** The Constant ALL_ZONES. */
|
||||
public static final List<ZoneType> ALL_ZONES = Collections.unmodifiableList(Arrays.asList(ZoneType.Battlefield,
|
||||
ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante));
|
||||
ZoneType.Library, ZoneType.Graveyard, ZoneType.Hand, ZoneType.Exile, ZoneType.Command, ZoneType.Ante, ZoneType.Stack));
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -349,7 +350,7 @@ public abstract class Player extends GameEntity {
|
||||
repParams.put("Event", "GainLife");
|
||||
repParams.put("Affected", this);
|
||||
repParams.put("LifeGained", toGain);
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -772,7 +773,7 @@ public abstract class Player extends GameEntity {
|
||||
repParams.put("DamageAmount", damage);
|
||||
repParams.put("IsCombat", isCombat);
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -822,7 +823,7 @@ public abstract class Player extends GameEntity {
|
||||
repParams.put("IsCombat", isCombat);
|
||||
repParams.put("Prevention", true);
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repParams) != ReplacementResult.NotReplaced) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1255,7 +1256,7 @@ public abstract class Player extends GameEntity {
|
||||
repRunParams.put("Event", "Draw");
|
||||
repRunParams.put("Affected", this);
|
||||
|
||||
if (AllZone.getReplacementHandler().run(repRunParams)) {
|
||||
if (AllZone.getReplacementHandler().run(repRunParams) != ReplacementResult.NotReplaced) {
|
||||
return drawn;
|
||||
}
|
||||
|
||||
@@ -1378,10 +1379,19 @@ public abstract class Player extends GameEntity {
|
||||
public final CardList getCardsIn(final List<ZoneType> zones) {
|
||||
final CardList result = new CardList();
|
||||
for (final ZoneType z : zones) {
|
||||
if(z == ZoneType.Stack) {
|
||||
for(Card c : AllZone.getStackZone().getCards())
|
||||
{
|
||||
if(c.getOwner().equals(this)) {
|
||||
result.add(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.getZone(z) != null) {
|
||||
result.addAll(this.getZone(z).getCards());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -2172,7 +2182,7 @@ public abstract class Player extends GameEntity {
|
||||
runParams.put("Affected", this);
|
||||
runParams.put("Event", "GameLoss");
|
||||
|
||||
if (AllZone.getReplacementHandler().run(runParams)) {
|
||||
if (AllZone.getReplacementHandler().run(runParams) != ReplacementResult.NotReplaced) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -68,6 +68,10 @@ public class DefaultPlayerZone extends PlayerZone implements java.io.Serializabl
|
||||
|
||||
public void add(final Object o, boolean update) {
|
||||
final Card c = (Card) o;
|
||||
|
||||
if(zoneName == ZoneType.Graveyard && c.getName().equals("Clone")) {
|
||||
System.out.println("I'm not a freak.");
|
||||
}
|
||||
|
||||
// Immutable cards are usually emblems,effects and the mana pool and we
|
||||
// don't want to log those.
|
||||
|
||||
Reference in New Issue
Block a user