Totem Armor turned into replacement effect for Destroy.

PhaseHandler - renamed methods to fix typo
SpellAbility - getType removed, 2 flags used instead
This commit is contained in:
Maxmtg
2013-06-04 13:16:54 +00:00
parent b02ae4adc1
commit ea5a00a2dd
13 changed files with 159 additions and 104 deletions

1
.gitattributes vendored
View File

@@ -14089,6 +14089,7 @@ src/main/java/forge/card/mana/ManaPool.java svneol=native#text/plain
src/main/java/forge/card/mana/package-info.java svneol=native#text/plain
src/main/java/forge/card/package-info.java svneol=native#text/plain
src/main/java/forge/card/replacement/ReplaceDamage.java -text
src/main/java/forge/card/replacement/ReplaceDestroy.java -text
src/main/java/forge/card/replacement/ReplaceDiscard.java -text
src/main/java/forge/card/replacement/ReplaceDraw.java -text
src/main/java/forge/card/replacement/ReplaceGainLife.java -text

View File

@@ -222,7 +222,7 @@ public class StaticEffects {
// remove abilities
if (params.containsKey("AddAbility") || params.containsKey("GainsAbilitiesOf")) {
for (final SpellAbility s : affectedCard.getSpellAbilities()) {
if (s.getType().equals("Temporary")) {
if (s.isTemporary()) {
affectedCard.removeSpellAbility(s);
}
}

View File

@@ -321,13 +321,6 @@ public class CardCharacteristics {
return replacementEffects;
}
/**
* @param replacementEffects0 the replacementEffects to set
*/
public void setReplacementEffects(ArrayList<ReplacementEffect> replacementEffects0) {
this.replacementEffects = replacementEffects0;
}
/**
* <p>
* getSVar.

View File

@@ -71,10 +71,11 @@ public class DamageDealEffect extends SpellAbilityEffect {
final boolean noPrevention = sa.hasParam("NoPrevention");
final boolean combatDmg = sa.hasParam("CombatDamage");
final boolean removeDamage = sa.hasParam("Remove");
ArrayList<Object> tgts;
if (sa.getTarget() == null) {
tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa);
tgts = AbilityUtils.getDefinedObjects(sa.getSourceCard(), sa.getParam("Defined"), sa) ;
} else {
tgts = sa.getTarget().getTargets();
}
@@ -119,7 +120,11 @@ public class DamageDealEffect extends SpellAbilityEffect {
if (o instanceof Card) {
final Card c = (Card) o;
if (c.isInPlay() && (!targeted || c.canBeTargetedBy(sa))) {
if (noPrevention) {
if (removeDamage) {
c.setDamage(0);
c.clearAssignedDamage();
}
else if (noPrevention) {
if (c.addDamageWithoutPrevention(dmg, source) && remember) {
source.addRemembered(c);
}

View File

@@ -2228,14 +2228,13 @@ public class CardFactoryUtil {
if (hasKeyword(card, "Replicate") != -1) {
final int n = hasKeyword(card, "Replicate");
if (n != -1) {
final String parse = card.getKeyword().get(n).toString();
final String[] k = parse.split("cate ");
final String parse = card.getKeyword().get(n).toString();
final String[] k = parse.split("cate ");
final SpellAbility sa = card.getFirstSpellAbility();
sa.setIsReplicate(true);
sa.setReplicateManaCost(new ManaCost(new ManaCostParser(k[1])));
final SpellAbility sa = card.getFirstSpellAbility();
sa.setIsReplicate(true);
sa.setReplicateManaCost(new ManaCost(new ManaCostParser(k[1])));
}
}
if(hasKeyword(card, "Fuse") != -1) {
@@ -2472,7 +2471,7 @@ public class CardFactoryUtil {
final Trigger etbTrigger = TriggerHandler.parseTrigger(sbTrig.toString(), card, true);
card.addTrigger(etbTrigger);
}
if (card.hasKeyword("Epic")) {
makeEpic(card);
}
@@ -3339,5 +3338,25 @@ public class CardFactoryUtil {
card.addTrigger(stormTrigger);
} // Storm
}
public final static void refreshTotemArmor(Card c) {
boolean hasKw = c.hasKeyword("Totem armor");
List<ReplacementEffect> res = c.getReplacementEffects();
for ( int ix = 0; ix < res.size(); ix++ ) {
ReplacementEffect re = res.get(ix);
if( re.getMapParams().containsKey("TotemArmor") ) {
if(hasKw) return; // has re and kw - nothing to do here
res.remove(ix--);
}
}
if( hasKw ) {
ReplacementEffect re = ReplacementHandler.parseReplacement("Event$ Destroy | ActiveZones$ Battlefield | ValidCard$ Card.EnchantedBy | ReplaceWith$ RegenTA | Secondary$ True | TotemArmor$ True | Description$ Totem armor - " + c, c);
c.getSVars().put("RegenTA", "AB$ DealDamage | Cost$ 0 | Defined$ ReplacedCard | Remove$ All | SubAbility$ DestroyMe");
c.getSVars().put("DestroyMe", "DB$ Destroy | Defined$ Self");
c.getReplacementEffects().add(re);
}
}
} // end class CardFactoryUtil

View File

@@ -0,0 +1,76 @@
/*
* 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.replacement;
import java.util.Map;
import forge.Card;
import forge.card.spellability.SpellAbility;
/**
* TODO: Write javadoc for this type.
*
*/
public class ReplaceDestroy extends ReplacementEffect {
/**
* Instantiates a new replace discard.
*
* @param params the params
* @param host the host
*/
public ReplaceDestroy(final Map<String, String> params, final Card host) {
super(params, host);
}
/* (non-Javadoc)
* @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap)
*/
@Override
public boolean canReplace(Map<String, Object> runParams) {
if (!runParams.get("Event").equals("Destroy")) {
return false;
}
if (this.getMapParams().containsKey("ValidPlayer")) {
if (!matchesValid(runParams.get("Affected"), this.getMapParams().get("ValidPlayer").split(","), this.getHostCard())) {
return false;
}
}
if (this.getMapParams().containsKey("ValidCard")) {
if (!matchesValid(runParams.get("Card"), this.getMapParams().get("ValidCard").split(","), this.getHostCard())) {
return false;
}
}
if (this.getMapParams().containsKey("ValidSource")) {
if (!matchesValid(runParams.get("Source"), this.getMapParams().get("ValidSource").split(","), this.getHostCard())) {
return false;
}
}
return true;
}
/* (non-Javadoc)
* @see forge.card.replacement.ReplacementEffect#setReplacingObjects(java.util.HashMap, forge.card.spellability.SpellAbility)
*/
@Override
public void setReplacingObjects(Map<String, Object> runParams, SpellAbility sa) {
sa.setReplacingObject("Card", runParams.get("Card"));
}
}

View File

@@ -12,6 +12,7 @@ import forge.Card;
*/
public enum ReplacementType {
DamageDone(ReplaceDamage.class),
Destroy(ReplaceDestroy.class),
Discard(ReplaceDiscard.class),
Draw(ReplaceDraw.class),
GainLife(ReplaceGainLife.class),

View File

@@ -57,10 +57,11 @@ public abstract class SpellAbility implements ISpellAbility {
private ManaCost replicateManaCost = null;
private Player activatingPlayer = null;
private String type = "Intrinsic"; // set to Intrinsic by default
private boolean temporary; // that is given by some static ability
private boolean basicLandAbility; // granted by basic land type
private Card sourceCard;
private Card originalHost = null;
private Card grantorCard = null; // card which grants the ability (equipment or owner of static ability that gave this one)
private List<Card> splicedCards = null;
// private List<Card> targetList;
@@ -385,7 +386,7 @@ public abstract class SpellAbility implements ISpellAbility {
* a {@link forge.Card} object.
*/
public void setOriginalHost(final Card c) {
this.originalHost = c;
this.grantorCard = c;
}
/**
@@ -396,7 +397,7 @@ public abstract class SpellAbility implements ISpellAbility {
* @return a {@link forge.Card} object.
*/
public Card getOriginalHost() {
return this.originalHost;
return this.grantorCard;
}
public String getParamOrDefault(String key, String defaultValue) {
@@ -820,32 +821,6 @@ public abstract class SpellAbility implements ISpellAbility {
return this.stackDescription.replaceAll("CARDNAME", this.getSourceCard().getName());
}
/**
* <p>
* Setter for the field <code>type</code>.
* </p>
*
* Extrinsic or Intrinsic:
*
* @param s
* a {@link java.lang.String} object.
*/
public void setType(final String s) {
this.type = s;
}
/**
* <p>
* Getter for the field <code>type</code>.
* </p>
*
* @return a {@link java.lang.String} object.
*/
public String getType() {
// Extrinsic or Intrinsic:
return this.type;
}
// setDescription() includes mana cost and everything like
// "G, tap: put target creature from your hand onto the battlefield"
/**
@@ -1731,4 +1706,20 @@ public abstract class SpellAbility implements ISpellAbility {
CostPartMana cm = payCosts != null ? getPayCosts().getCostMana() : null;
return cm != null && cm.getAmountOfX() > 0;
}
public boolean isBasicLandAbility() {
return basicLandAbility;
}
public void setBasicLandAbility(boolean basicLandAbility) {
this.basicLandAbility = basicLandAbility; // TODO: Add 0 to parameter's name.
}
public boolean isTemporary() {
return temporary;
}
public void setTemporary(boolean temporary) {
this.temporary = temporary; // TODO: Add 0 to parameter's name.
}
}

View File

@@ -284,7 +284,7 @@ public class StaticAbilityContinuous {
for (SpellAbility sa : c.getSpellAbilities()) {
if (sa instanceof AbilityActivated) {
SpellAbility newSA = ((AbilityActivated) sa).getCopy();
newSA.setType("Temporary");
newSA.setTemporary(true);
CardFactoryUtil.correctAbilityChainSourceCard(newSA, hostCard);
addFullAbs.add(newSA);
}
@@ -410,7 +410,7 @@ public class StaticAbilityContinuous {
}
if (abilty.startsWith("AB")) { // grant the ability
final SpellAbility sa = AbilityFactory.getAbility(abilty, affectedCard);
sa.setType("Temporary");
sa.setTemporary(true);
sa.setOriginalHost(hostCard);
affectedCard.addSpellAbility(sa);
}

View File

@@ -318,11 +318,6 @@ public class WrappedAbility extends Ability implements ISpellAbility {
sa.setTargetCard(card);
}
@Override
public void setType(final String s) {
sa.setType(s);
}
@Override
public void setSourceTrigger(final int id) {
sa.setSourceTrigger(id);

View File

@@ -45,12 +45,12 @@ import forge.card.TriggerReplacementBase;
import forge.card.ability.AbilityFactory;
import forge.card.ability.effects.AttachEffect;
import forge.card.cardfactory.CardFactory;
import forge.card.cardfactory.CardFactoryUtil;
import forge.card.cost.Cost;
import forge.card.mana.ManaCost;
import forge.card.replacement.ReplacementResult;
import forge.card.spellability.Ability;
import forge.card.spellability.AbilityActivated;
import forge.card.spellability.AbilityStatic;
import forge.card.spellability.SpellAbility;
import forge.card.spellability.Target;
import forge.card.staticability.StaticAbility;
@@ -72,7 +72,6 @@ import forge.game.zone.PlayerZone;
import forge.game.zone.PlayerZoneBattlefield;
import forge.game.zone.Zone;
import forge.game.zone.ZoneType;
import forge.gui.GuiChoose;
import forge.util.Aggregates;
import forge.util.maps.CollectionSuppliers;
import forge.util.maps.HashMapOfLists;
@@ -1224,47 +1223,23 @@ public class GameAction {
return false;
if (c.isEnchanted()) {
List<Card> list = new ArrayList<Card>(c.getEnchantedBy());
list = CardLists.filter(list, new Predicate<Card>() {
@Override
public boolean apply(final Card crd) {
return crd.hasKeyword("Totem armor");
}
});
CardLists.sortByCmcDesc(list);
if (list.size() != 0) {
final Card crd;
if (list.size() == 1) {
crd = list.get(0);
} else {
if (c.getController().isHuman()) {
crd = GuiChoose.oneOrNone("Select totem armor to destroy", list);
} else {
crd = list.get(0);
}
}
final Card card = c;
final AbilityStatic ability = new AbilityStatic(crd, ManaCost.ZERO) {
@Override
public void resolve() {
GameAction.this.destroy(crd, sa);
card.setDamage(0);
// Play the Destroy sound
game.fireEvent(new GameEventCardDestroyed());
}
};
final StringBuilder sb = new StringBuilder();
sb.append(crd).append(" - Totem armor: destroy this aura.");
ability.setStackDescription(sb.toString());
game.getStack().add(ability);
return false;
for( Card e : c.getEnchantedBy() ) {
CardFactoryUtil.refreshTotemArmor(e);
}
} // totem armor
}
// Replacement effects
final HashMap<String, Object> repRunParams = new HashMap<String, Object>();
repRunParams.put("Event", "Destroy");
repRunParams.put("Source", sa);
repRunParams.put("Card", c);
repRunParams.put("Affected", c);
if (game.getReplacementHandler().run(repRunParams) != ReplacementResult.NotReplaced) {
return false;
}
if (sa != null) {
activator = sa.getActivatingPlayer();
}

View File

@@ -659,7 +659,7 @@ public final class GameActionUtil {
List<SpellAbility> manaAbs = land.getCharacteristics().getManaAbility();
// will get comodification exception without a different list
for (final SpellAbility sa : origManaAbs) {
if (sa.getType().equals("BasicLandTypeMana")) {
if (sa.isBasicLandAbility()) {
manaAbs.remove(sa);
}
}
@@ -673,7 +673,7 @@ public final class GameActionUtil {
for (final Card land : lands) {
if (land.isType(landType)) {
final SpellAbility sa = AbilityFactory.getAbility(abString, land);
sa.setType("BasicLandTypeMana");
sa.setBasicLandAbility(true);
land.getCharacteristics().getManaAbility().add(sa);
}
}

View File

@@ -306,10 +306,11 @@ public class PhaseHandler implements java.io.Serializable {
case COMBAT_DECLARE_ATTACKERS:
game.getStack().freezeStack();
declateAttackTurnBasedActions();
declareAttackersTurnBasedActions();
game.getStack().unfreezeStack();
this.bCombat = !game.getCombat().getAttackers().isEmpty();
givePriorityToPlayer = bCombat;
this.nCombatsThisTurn++;
break;
@@ -317,9 +318,7 @@ public class PhaseHandler implements java.io.Serializable {
case COMBAT_DECLARE_BLOCKERS:
game.getCombat().removeAbsentCombatants();
game.getStack().freezeStack();
declareBlockersTurnBaseActions();
declareBlockersTurnBaseActions();
game.getStack().unfreezeStack();
break;
@@ -467,7 +466,7 @@ public class PhaseHandler implements java.io.Serializable {
}
}
private void declateAttackTurnBasedActions() {
private void declareAttackersTurnBasedActions() {
Player whoDeclares = playerDeclaresAttackers == null || playerDeclaresAttackers.hasLost() ? playerTurn : playerDeclaresAttackers;
whoDeclares.getController().declareAttackers(playerTurn);