diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 331a181c550..239175f7a3d 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -286,6 +286,8 @@ public class AbilityUtils { list = sa.getRootAbility().getPaidList("ExiledCards"); } else if (defined.startsWith("Exiled")) { list = sa.getRootAbility().getPaidList("Exiled"); + } else if (defined.startsWith("Milled")) { + list = sa.getRootAbility().getPaidList("Milled"); } else if (defined.startsWith("TappedCards")) { list = sa.getRootAbility().getPaidList("TappedCards"); } else if (defined.startsWith("Tapped")) { diff --git a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java index b55bcc90385..8558f46272b 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ManaEffect.java @@ -195,6 +195,26 @@ public class ManaEffect extends SpellAbilityEffect { } if (colors == 0) return; abMana.setExpressChoice(ColorSet.fromMask(colors)); + } else if (type.startsWith("EachColoredManaSymbol")) { + final String res = type.split("_")[1]; + final CardCollection list = AbilityUtils.getDefinedCards(card, res, sa); + StringBuilder sb = new StringBuilder(); + for (Card c : list) { + String mana = c.getManaCost().toString(); + for (int i = 0; i < mana.length(); i++) { + char symbol = mana.charAt(i); + switch (symbol) { + case 'W': + case 'U': + case 'B': + case 'R': + case 'G': + sb.append(symbol).append(' '); + break; + } + } + } + abMana.setExpressChoice(sb.toString().trim()); } if (abMana.getExpressChoice().isEmpty()) { diff --git a/forge-game/src/main/java/forge/game/card/Card.java b/forge-game/src/main/java/forge/game/card/Card.java index 03247423175..d5b8815ecf1 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -3019,6 +3019,11 @@ public class Card extends GameEntity implements Comparable { // Play the Equip sound getGame().fireEvent(new GameEventCardAttachment(this, oldTarget, entity)); + // Run replacement effects + final Map repParams = AbilityKey.mapFromAffected(this); + repParams.put(AbilityKey.AttachTarget, entity); + getGame().getReplacementHandler().run(ReplacementType.Attached, repParams); + // run trigger final Map runParams = AbilityKey.newMap(); runParams.put(AbilityKey.AttachSource, this); diff --git a/forge-game/src/main/java/forge/game/player/Player.java b/forge-game/src/main/java/forge/game/player/Player.java index 80007185ec7..eca33a3afec 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -1670,21 +1670,22 @@ public class Player extends GameEntity implements Comparable { // Replacement effects final Map repRunParams = AbilityKey.mapFromAffected(this); repRunParams.put(AbilityKey.Number, n); - repRunParams.put(AbilityKey.Destination, destination); - - switch (getGame().getReplacementHandler().run(ReplacementType.Mill, repRunParams)) { - case NotReplaced: - break; - case Updated: - // check if this is still the affected player - if (this.equals(repRunParams.get(AbilityKey.Affected))) { - n = (int) repRunParams.get(AbilityKey.Number); - } else { - return milled; + + if (destination == ZoneType.Graveyard && !bottom) { + switch (getGame().getReplacementHandler().run(ReplacementType.Mill, repRunParams)) { + case NotReplaced: + break; + case Updated: + // check if this is still the affected player + if (this.equals(repRunParams.get(AbilityKey.Affected))) { + n = (int) repRunParams.get(AbilityKey.Number); + } else { + return milled; + } + break; + default: + return milled; } - break; - default: - return milled; } final int max = Math.min(n, lib.size()); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceAttached.java b/forge-game/src/main/java/forge/game/replacement/ReplaceAttached.java new file mode 100644 index 00000000000..6bdf445fbed --- /dev/null +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceAttached.java @@ -0,0 +1,51 @@ +package forge.game.replacement; + +import forge.game.ability.AbilityKey; +import forge.game.card.Card; +import forge.game.spellability.SpellAbility; + +import java.util.Map; + +/** + * TODO: Write javadoc for this type. + * + */ +public class ReplaceAttached extends ReplacementEffect { + + /** + * + * TODO: Write javadoc for Constructor. + * @param mapParams   HashMap + * @param host   Card + */ + public ReplaceAttached(final Map mapParams, final Card host, final boolean intrinsic) { + super(mapParams, host, intrinsic); + } + + /* (non-Javadoc) + * @see forge.card.replacement.ReplacementEffect#canReplace(java.util.HashMap) + */ + @Override + public boolean canReplace(Map runParams) { + if (hasParam("ValidCard")) { + if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidCard").split(","), this.getHostCard())) { + return false; + } + } + if (hasParam("ValidTarget")) { + if (!matchesValid(runParams.get(AbilityKey.AttachTarget), getParam("ValidTarget").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(AbilityKey.Card, runParams.get(AbilityKey.Affected)); + } + +} diff --git a/forge-game/src/main/java/forge/game/replacement/ReplaceMill.java b/forge-game/src/main/java/forge/game/replacement/ReplaceMill.java index 608081f6204..e2aa8cf2009 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplaceMill.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplaceMill.java @@ -20,8 +20,6 @@ package forge.game.replacement; import forge.game.ability.AbilityKey; import forge.game.card.Card; import forge.game.spellability.SpellAbility; -import forge.game.zone.ZoneType; - import java.util.Map; /** @@ -46,9 +44,6 @@ public class ReplaceMill extends ReplacementEffect { @Override public boolean canReplace(Map runParams) { - if (ZoneType.Graveyard != ((ZoneType) runParams.get(AbilityKey.Destination))) { - return false; - } if (hasParam("ValidPlayer")) { if (!matchesValid(runParams.get(AbilityKey.Affected), getParam("ValidPlayer").split(","), getHostCard())) { return false; diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java index 5fbcce04d8a..c13b3f172d0 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementType.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementType.java @@ -12,6 +12,7 @@ import java.util.Map; */ public enum ReplacementType { AddCounter(ReplaceAddCounter.class), + Attached(ReplaceAttached.class), Counter(ReplaceCounter.class), CreateToken(ReplaceToken.class), DamageDone(ReplaceDamage.class), diff --git a/forge-gui/res/cardsfolder/c/charmed_pendant.txt b/forge-gui/res/cardsfolder/c/charmed_pendant.txt index 96a96485ba6..062c963d7a8 100644 --- a/forge-gui/res/cardsfolder/c/charmed_pendant.txt +++ b/forge-gui/res/cardsfolder/c/charmed_pendant.txt @@ -1,14 +1,5 @@ Name:Charmed Pendant ManaCost:4 Types:Artifact -A:AB$ Mana | Cost$ T Mill<1> | Produced$ W | Amount$ ManaW | References$ ManaW | InstantSpeed$ True | SubAbility$ DBManaU | SpellDescription$ For each colored mana symbol in the milled card's mana cost, add one mana of that color. Activate this ability only any time you could cast an instant. -SVar:DBManaU:DB$ Mana | Produced$ U | Amount$ ManaU | References$ ManaU | SubAbility$ DBManaB -SVar:DBManaB:DB$ Mana | Produced$ B | Amount$ ManaB | References$ ManaB | SubAbility$ DBManaR -SVar:DBManaR:DB$ Mana | Produced$ R | Amount$ ManaR | References$ ManaR | SubAbility$ DBManaG -SVar:DBManaG:DB$ Mana | Produced$ G | Amount$ ManaG | References$ ManaG -SVar:ManaW:Milled$ChromaSource.W -SVar:ManaU:Milled$ChromaSource.U -SVar:ManaB:Milled$ChromaSource.B -SVar:ManaR:Milled$ChromaSource.R -SVar:ManaG:Milled$ChromaSource.G +A:AB$ Mana | Cost$ T Mill<1> | Produced$ Special EachColoredManaSymbol_Milled | InstantSpeed$ True | SpellDescription$ For each colored mana symbol in the milled card's mana cost, add one mana of that color. Activate this ability only any time you could cast an instant. Oracle:{T}, Mill a card: For each colored mana symbol in the milled card's mana cost, add one mana of that color. Activate this ability only any time you could cast an instant. diff --git a/forge-gui/res/cardsfolder/s/sanctuary_blade.txt b/forge-gui/res/cardsfolder/s/sanctuary_blade.txt new file mode 100644 index 00000000000..064157f8b3d --- /dev/null +++ b/forge-gui/res/cardsfolder/s/sanctuary_blade.txt @@ -0,0 +1,8 @@ +Name:Sanctuary Blade +ManaCost:2 +Types:Artifact Equipment +R:Event$ Attached | ValidCard$ Card.Self | ValidTarget$ Creature | ReplaceWith$ ChooseColor | ActiveZones$ Battlefield | Description$ As CARDNAME becomes attached to a creature, choose a color. +SVar:ChooseColor:DB$ ChooseColor | Defined$ You +S:Mode$ Continuous | Affected$ Creature.EquippedBy | AddPower$ 2 | AddKeyword$ Protection:Card.ChosenColor:Protection from ChosenColor | Description$ Equipped creature gets +2/+0 and has protection from the last chosen color. +K:Equip:3 +Oracle:As Sanctuary Blade becomes attached to a creature, choose a color.\nEquipped creature gets +2/+0 and has protection from the last chosen color.\nEquip {3}