diff --git a/.gitattributes b/.gitattributes index 246dcfce667..6dc97c506b4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -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 diff --git a/src/main/java/forge/StaticEffects.java b/src/main/java/forge/StaticEffects.java index e9304681405..366a70bd6fd 100644 --- a/src/main/java/forge/StaticEffects.java +++ b/src/main/java/forge/StaticEffects.java @@ -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); } } diff --git a/src/main/java/forge/card/CardCharacteristics.java b/src/main/java/forge/card/CardCharacteristics.java index 5e96c196fb2..e71568ecc11 100644 --- a/src/main/java/forge/card/CardCharacteristics.java +++ b/src/main/java/forge/card/CardCharacteristics.java @@ -321,13 +321,6 @@ public class CardCharacteristics { return replacementEffects; } - /** - * @param replacementEffects0 the replacementEffects to set - */ - public void setReplacementEffects(ArrayList replacementEffects0) { - this.replacementEffects = replacementEffects0; - } - /** *

* getSVar. diff --git a/src/main/java/forge/card/ability/effects/DamageDealEffect.java b/src/main/java/forge/card/ability/effects/DamageDealEffect.java index 179cc480d50..fc7f1674ab4 100644 --- a/src/main/java/forge/card/ability/effects/DamageDealEffect.java +++ b/src/main/java/forge/card/ability/effects/DamageDealEffect.java @@ -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 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); } diff --git a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java index acf5f19729e..4cda6d8ab19 100644 --- a/src/main/java/forge/card/cardfactory/CardFactoryUtil.java +++ b/src/main/java/forge/card/cardfactory/CardFactoryUtil.java @@ -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 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 diff --git a/src/main/java/forge/card/replacement/ReplaceDestroy.java b/src/main/java/forge/card/replacement/ReplaceDestroy.java new file mode 100644 index 00000000000..474bcef83e5 --- /dev/null +++ b/src/main/java/forge/card/replacement/ReplaceDestroy.java @@ -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 . + */ +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 params, final Card host) { + super(params, host); + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) + */ + @Override + public boolean canReplace(Map 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 runParams, SpellAbility sa) { + sa.setReplacingObject("Card", runParams.get("Card")); + } + +} diff --git a/src/main/java/forge/card/replacement/ReplacementType.java b/src/main/java/forge/card/replacement/ReplacementType.java index c185c7a1e26..036146a9785 100644 --- a/src/main/java/forge/card/replacement/ReplacementType.java +++ b/src/main/java/forge/card/replacement/ReplacementType.java @@ -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), diff --git a/src/main/java/forge/card/spellability/SpellAbility.java b/src/main/java/forge/card/spellability/SpellAbility.java index 096642465b6..f0bf48c4df1 100644 --- a/src/main/java/forge/card/spellability/SpellAbility.java +++ b/src/main/java/forge/card/spellability/SpellAbility.java @@ -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 splicedCards = null; // private List 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()); } - /** - *

- * Setter for the field type. - *

- * - * Extrinsic or Intrinsic: - * - * @param s - * a {@link java.lang.String} object. - */ - public void setType(final String s) { - this.type = s; - } - - /** - *

- * Getter for the field type. - *

- * - * @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. + } } diff --git a/src/main/java/forge/card/staticability/StaticAbilityContinuous.java b/src/main/java/forge/card/staticability/StaticAbilityContinuous.java index b2094098930..dd43daf9acd 100644 --- a/src/main/java/forge/card/staticability/StaticAbilityContinuous.java +++ b/src/main/java/forge/card/staticability/StaticAbilityContinuous.java @@ -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); } diff --git a/src/main/java/forge/card/trigger/WrappedAbility.java b/src/main/java/forge/card/trigger/WrappedAbility.java index 5d2d788db1d..5a083f67b32 100644 --- a/src/main/java/forge/card/trigger/WrappedAbility.java +++ b/src/main/java/forge/card/trigger/WrappedAbility.java @@ -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); diff --git a/src/main/java/forge/game/GameAction.java b/src/main/java/forge/game/GameAction.java index 40d281a8977..d17e8520228 100644 --- a/src/main/java/forge/game/GameAction.java +++ b/src/main/java/forge/game/GameAction.java @@ -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 list = new ArrayList(c.getEnchantedBy()); - list = CardLists.filter(list, new Predicate() { - @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 repRunParams = new HashMap(); + 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(); } diff --git a/src/main/java/forge/game/GameActionUtil.java b/src/main/java/forge/game/GameActionUtil.java index 2242644f1af..b6e8b3ac5fe 100644 --- a/src/main/java/forge/game/GameActionUtil.java +++ b/src/main/java/forge/game/GameActionUtil.java @@ -659,7 +659,7 @@ public final class GameActionUtil { List 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); } } diff --git a/src/main/java/forge/game/phase/PhaseHandler.java b/src/main/java/forge/game/phase/PhaseHandler.java index 9a3203e83dd..1a4fafceb18 100644 --- a/src/main/java/forge/game/phase/PhaseHandler.java +++ b/src/main/java/forge/game/phase/PhaseHandler.java @@ -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);