diff --git a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java index e9a0fe75a89..68936a2f7ae 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/PumpEffect.java @@ -255,6 +255,8 @@ public class PumpEffect extends SpellAbilityEffect { replaced = host.getChosenType(); } else if (defined.equals("CardUIDSource")) { replaced = "CardUID_" + String.valueOf(host.getId()); + } else if (defined.equals("ActivatorName")) { + replaced = sa.getActivatingPlayer().getName(); } for (int i = 0; i < keywords.size(); i++) { keywords.set(i, TextUtil.fastReplace(keywords.get(i), defined, replaced)); diff --git a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java index 1f77b737737..607c18d793c 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/SacrificeEffect.java @@ -119,8 +119,9 @@ public class SacrificeEffect extends SpellAbilityEffect { if (sa.hasParam("Random")) { choosenToSacrifice = Aggregates.random(validTargets, Math.min(amount, validTargets.size()), new CardCollection()); - } - else { + } else if (sa.hasParam("OptionalSacrifice") && !p.getController().confirmAction(sa, null, "Do you want to sacrifice?")) { + choosenToSacrifice = CardCollection.EMPTY; + } else { boolean isOptional = sa.hasParam("Optional"); boolean isStrict = sa.hasParam("StrictAmount"); int minTargets = isOptional ? 0 : amount; 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 c2e9bacd4de..8f458903163 100644 --- a/forge-game/src/main/java/forge/game/card/Card.java +++ b/forge-game/src/main/java/forge/game/card/Card.java @@ -5333,6 +5333,11 @@ public class Card extends GameEntity implements Comparable { if (source.getController().equals(chosenPlayer)) { return true; } + } else if (kw.startsWith("Protection from opponent of ")) { + final String playerName = kw.substring("Protection from opponent of ".length()); + if (source.getController().isOpponentOf(playerName)) { + return true; + } } else if (kw.startsWith("Protection from ")) { final String protectType = CardType.getSingularType(kw.substring("Protection from ".length())); if (source.getType().hasStringType(protectType)) { 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 8e6caf75d02..78b040024ba 100644 --- a/forge-game/src/main/java/forge/game/player/Player.java +++ b/forge-game/src/main/java/forge/game/player/Player.java @@ -353,6 +353,17 @@ public class Player extends GameEntity implements Comparable { return other != this && other != null && (other.teamNumber < 0 || other.teamNumber != teamNumber); } + public boolean isOpponentOf(String other) { + Player otherPlayer = null; + for (Player p : game.getPlayers()) { + if (p.getName().equals(other)) { + otherPlayer = p; + break; + } + } + return isOpponentOf(otherPlayer); + } + public final boolean setLife(final int newLife, final Card source) { boolean change = false; // rule 118.5 diff --git a/forge-gui/res/cardsfolder/s/second_harvest.txt b/forge-gui/res/cardsfolder/s/second_harvest.txt index b1a032f2a97..633c67724b9 100644 --- a/forge-gui/res/cardsfolder/s/second_harvest.txt +++ b/forge-gui/res/cardsfolder/s/second_harvest.txt @@ -1,7 +1,7 @@ Name:Second Harvest ManaCost:2 G G Types:Instant -A:SP$ CopyPermanent | Cost$ 2 G G | RepeatSubAbility$ DBClone | Defined$ Valid Permanent.token+YouCtrl | AILogic$ DuplicatePerms | SpellDescription$ For each token you control, create a token that's a copy of that permanent. +A:SP$ CopyPermanent | Cost$ 2 G G | Defined$ Valid Permanent.token+YouCtrl | AILogic$ DuplicatePerms | SpellDescription$ For each token you control, create a token that's a copy of that permanent. AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/second_harvest.jpg Oracle:For each token you control, create a token that's a copy of that permanent. diff --git a/forge-gui/res/cardsfolder/upcoming/archfiend_of_spite.txt b/forge-gui/res/cardsfolder/upcoming/archfiend_of_spite.txt new file mode 100644 index 00000000000..5132226c6ac --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/archfiend_of_spite.txt @@ -0,0 +1,12 @@ +Name:Archfiend of Spite +ManaCost:5 B B +Types:Creature Demon +PT:6/6 +K:Flying +T:Mode$ DamageDone | ValidSource$ Card.OppCtrl | ValidTarget$ Card.Self | TriggerZones$ Battlefield | Execute$ TrigSacrifice | TriggerDescription$ Whenever a source an opponent controls deals damage to CARDNAME, that source’s controller loses that much life unless they sacrifice that many permanents. +SVar:TrigSacrifice:DB$ Sacrifice | Defined$ TriggeredSourceController | SacValid$ Permanent | Amount$ X | References$ X | StrictAmount$ True | OptionalSacrifice$ True | RememberSacrificed$ True | SubAbility$ DBCurseDamage +SVar:DBCurseDamage:DB$ DealDamage | Defined$ TriggeredSourceController | NumDmg$ X | References$ X | ConditionDefined$ Remembered | ConditionPresent$ Card | ConditionCompare$ EQ0 | SubAbility$ DBCleanup +SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True +SVar:X:TriggerCount$DamageAmount +K:Madness:3 B B +Oracle:Flying\nWhenever a source an opponent controls deals damage to Archfiend of Spite, that source’s controller loses that much life unless they sacrifice that many permanents.\nMadness {3}{B}{B} (If you discard this card, discard it into exile. When you do, cast it for its madness cost or put it into your graveyard.) diff --git a/forge-gui/res/cardsfolder/upcoming/cliffside_rescuer.txt b/forge-gui/res/cardsfolder/upcoming/cliffside_rescuer.txt new file mode 100644 index 00000000000..ebaad741f38 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/cliffside_rescuer.txt @@ -0,0 +1,7 @@ +Name:Cliffside Rescuer +ManaCost:1 W +Types:Creature Kor Soldier +PT:2/2 +K:Vigilance +A:AB$ Pump | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection from opponent of ActivatorName | DefinedKW$ ActivatorName | SpellDescription$ Target permanent you control gets protection from each opponent until end of turn. +Oracle:Vigilance\n{T}, Sacrifice Cliffside Rescuer: Target permanent you control gets protection from each opponent until end of turn. diff --git a/forge-gui/res/cardsfolder/upcoming/hate_mirage.txt b/forge-gui/res/cardsfolder/upcoming/hate_mirage.txt new file mode 100644 index 00000000000..5bf8166c249 --- /dev/null +++ b/forge-gui/res/cardsfolder/upcoming/hate_mirage.txt @@ -0,0 +1,5 @@ +Name:Hate Mirage +ManaCost:3 R +Types:Sorcery +A:SP$ CopyPermanent | Cost$ 3 R | ValidTgts$ Creature.YouDontCtrl | TgtPrompt$ Select up to two target creatures you don't control | TargetMin$ 0 | TargetMax$ 2 | PumpKeywords$ Haste | AtEOT$ Exile | AILogic$ BeforeCombat | SpellDescription$ Choose up to two target creatures you don't control. For each of those creatures create a token that is a copy of those creatures. These tokens gain Haste. Exile them at the beginning of the next end step. +Oracle:Choose up to two target creatures you don't control. For each of those creatures create a token that is a copy of those creatures. These tokens gain Haste. Exile them at the beginning of the next end step.