mirror of
https://github.com/Card-Forge/forge.git
synced 2025-11-18 03:38:01 +00:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
76
src/main/java/forge/card/replacement/ReplaceDestroy.java
Normal file
76
src/main/java/forge/card/replacement/ReplaceDestroy.java
Normal 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"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user