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 5fce377cdf4..512224fb39f 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1004,6 +1004,14 @@ public class AbilityUtils { players.addAll(tc.getTargetPlayers()); } } + else if (defined.startsWith("PlayerUID_")) { + int id = Integer.parseInt(defined.split("PlayerUID_")[1]); + for (Player p : game.getRegisteredPlayers()) { + if (p.getId() == id) { + players.add(p); + } + } + } else if (defined.equals("ParentTarget") && sa instanceof SpellAbility) { final SpellAbility parent = ((SpellAbility)sa).getParentTargetingPlayer(); if (parent != null) { 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 6a04823abda..f5c2959f137 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 @@ -3,6 +3,8 @@ package forge.game.ability.effects; import java.util.Arrays; import java.util.List; +import org.apache.commons.lang3.StringUtils; + import com.google.common.base.Function; import com.google.common.base.Predicate; import com.google.common.collect.ImmutableList; @@ -298,39 +300,47 @@ public class PumpEffect extends SpellAbilityEffect { if (sa.hasParam("DefinedKW")) { String defined = sa.getParam("DefinedKW"); - String replaced = ""; - String name = ""; if (defined.equals("ChosenType")) { - replaced = host.getChosenType(); - } else if (defined.equals("ActivatorName")) { - replaced = activator.getName(); + if (!host.hasChosenType()) { + return; + } + String replaced = host.getChosenType(); + for (int i = 0; i < keywords.size(); i++) { + String s = keywords.get(i); + s = s.replaceAll(defined, replaced); + keywords.set(i, s); + } } else if (defined.equals("ChosenPlayer")) { - replaced = host.getChosenPlayer().getName(); - } else if (defined.endsWith("Player")) { + if (!host.hasChosenPlayer()) { + return; + } + Player cp = host.getChosenPlayer(); + for (int i = 0; i < keywords.size(); i++) { + String s = keywords.get(i); + s = s.replaceAll("ChosenPlayerUID", String.valueOf(cp.getId())); + s = s.replaceAll("ChosenPlayerName", cp.getName()); + keywords.set(i, s); + } + } else if (defined.equals("You") || defined.endsWith("Player")) { PlayerCollection players = AbilityUtils.getDefinedPlayers(host, defined, sa); if (players.isEmpty()) return; - replaced = "PlayerUID_" + players.get(0).getId(); - name = players.get(0).getName(); + String replacedID = String.valueOf(players.get(0).getId()); + String replacedName = players.get(0).getName(); + for (int i = 0; i < keywords.size(); i++) { + String s = keywords.get(i); + s = s.replaceAll("ChosenPlayerUID", replacedID); + s = s.replaceAll("ChosenPlayerName", replacedName); + keywords.set(i, s); + } } else if (defined.equals("ChosenColor")) { - String color = host.getChosenColor(); - replaced = color.substring(0, 1).toUpperCase() + color.substring(1); - } - for (int i = 0; i < keywords.size(); i++) { - keywords.set(i, TextUtil.fastReplace(keywords.get(i), defined, replaced)); - if (keywords.get(i).startsWith("Protection:") && !name.equals("")) { - List parts = Arrays.asList(keywords.get(i).split(":")); - String desc = parts.get(2); - if (desc.contains("PlayerUID")) { - parts.set(2, TextUtil.fastReplace(desc, replaced, name)); - StringBuilder mod = new StringBuilder(); - for (int n = 0; n < parts.size(); n++) { - mod.append(parts.get(n)); - if (n + 1 < parts.size()) { - mod.append(":"); - } - } - keywords.set(i, mod.toString()); - } + if (!host.hasChosenColor()) { + return; + } + for (int i = 0; i < keywords.size(); i++) { + String s = keywords.get(i); + s = s.replaceAll("ChosenColor", StringUtils.capitalize(host.getChosenColor())); + s = s.replaceAll("chosenColor", host.getChosenColor().toLowerCase()); + keywords.set(i, s); } } } diff --git a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java index de058f5f264..b61d5223081 100644 --- a/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java +++ b/forge-game/src/main/java/forge/game/card/CardFactoryUtil.java @@ -721,9 +721,6 @@ public class CardFactoryUtil { validSource = "nonColorless" + (damage ? "Source" : ""); } else if (protectType.equals("everything")) { return ""; - } else if (protectType.startsWith("opponent of ")) { - final String playerName = protectType.substring("opponent of ".length()); - validSource = "ControlledBy Player.OpponentOf PlayerNamed_" + playerName; } else { validSource = CardType.getSingularType(protectType); } @@ -2599,7 +2596,7 @@ public class CardFactoryUtil { if (isCombat) { rep += "| IsCombat$ True"; } - rep += "| Secondary$ True | TiedToKeyword$ " + keyword + " | Description$ " + keyword; + rep += "| Secondary$ True | Description$ " + keyword; if (from) { String fromRep = rep + " | ValidSource$ Card.Self"; @@ -2621,7 +2618,7 @@ public class CardFactoryUtil { if (!validSource.isEmpty()) { rep += " | ValidSource$ " + validSource; } - rep += " | Secondary$ True | TiedToKeyword$ " + keyword + " | Description$ " + keyword; + rep += " | Secondary$ True | Description$ " + keyword; ReplacementEffect re = ReplacementHandler.parseReplacement(rep, host, intrinsic, card); inst.addReplacement(re); diff --git a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java index 1cf69adee3f..8d4a120d6ca 100644 --- a/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java +++ b/forge-game/src/main/java/forge/game/replacement/ReplacementHandler.java @@ -143,15 +143,6 @@ public class ReplacementHandler { } for (final ReplacementEffect replacementEffect : c.getReplacementEffects()) { - // Replacement effects that are tied to keywords (e.g. damage prevention effects - if the keyword is removed, the replacement - // effect should be inactive) - if (replacementEffect.hasParam("TiedToKeyword")) { - String kw = replacementEffect.getParam("TiedToKeyword"); - if (!c.hasKeyword(kw)) { - continue; - } - } - if (!replacementEffect.hasRun() && !hasRun.contains(replacementEffect) && (layer == null || replacementEffect.getLayer() == layer) && event.equals(replacementEffect.getMode()) diff --git a/forge-gui/res/cardsfolder/c/cliffside_rescuer.txt b/forge-gui/res/cardsfolder/c/cliffside_rescuer.txt index 5cca96b081d..e14f22c8ba6 100644 --- a/forge-gui/res/cardsfolder/c/cliffside_rescuer.txt +++ b/forge-gui/res/cardsfolder/c/cliffside_rescuer.txt @@ -3,5 +3,5 @@ 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 gains protection from each of your opponents until end of turn. (It can't be blocked, targeted, dealt damage, enchanted, or equipped by anything controlled by those players.) +A:AB$ Pump | Cost$ T Sac<1/CARDNAME> | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection:Card.ControlledBy Player.OpponentOf PlayerUID_ChosenPlayerUID,Emblem.ControlledBy Player.OpponentOf PlayerUID_ChosenPlayerUID:Protection from all opponents of ChosenPlayerName | DefinedKW$ You | SpellDescription$ Target permanent you control gains protection from each of your opponents until end of turn. (It can't be blocked, targeted, dealt damage, enchanted, or equipped by anything controlled by those players.) Oracle:Vigilance\n{T}, Sacrifice Cliffside Rescuer: Target permanent you control gains protection from each of your opponents until end of turn. (It can't be blocked, targeted, dealt damage, enchanted, or equipped by anything controlled by those players.) diff --git a/forge-gui/res/cardsfolder/e/eon_frolicker.txt b/forge-gui/res/cardsfolder/e/eon_frolicker.txt index 8f9af698b3a..c10bbdf0dcb 100644 --- a/forge-gui/res/cardsfolder/e/eon_frolicker.txt +++ b/forge-gui/res/cardsfolder/e/eon_frolicker.txt @@ -5,6 +5,6 @@ PT:5/5 K:Flying T:Mode$ ChangesZone | ValidCard$ Card.wasCastByYou+Self | Destination$ Battlefield | Execute$ DBAddTurn | TriggerDescription$ When CARDNAME enters the battlefield, if you cast it, target opponent takes an extra turn after this one. Until your next turn, you and planeswalkers you control gain protection from that player. (You and planeswalkers you control can't be targeted, dealt damage, or enchanted by anything controlled by that player.) SVar:DBAddTurn:DB$ AddTurn | ValidTgts$ Opponent | TgtPrompt$ Select target opponent | NumTurns$ 1 | SubAbility$ DBPump -SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection:Player.TargetedPlayer:Protection from TargetedPlayer | DefinedKW$ TargetedPlayer | Duration$ UntilYourNextTurn | SubAbility$ DBPumpWalkers -SVar:DBPumpWalkers:DB$ Pump | Defined$ Valid Planeswalker.YouCtrl | KW$ Protection:Player.TargetedPlayer:Protection from TargetedPlayer | DefinedKW$ TargetedPlayer | Duration$ UntilYourNextTurn +SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | DefinedKW$ TargetedPlayer | Duration$ UntilYourNextTurn | SubAbility$ DBPumpWalkers +SVar:DBPumpWalkers:DB$ Pump | Defined$ Valid Planeswalker.YouCtrl | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | DefinedKW$ TargetedPlayer | Duration$ UntilYourNextTurn Oracle:Flying\nWhen Eon Frolicker enters the battlefield, if you cast it, target opponent takes an extra turn after this one. Until your next turn, you and planeswalkers you control gain protection from that player. (You and planeswalkers you control can't be targeted, dealt damage, or enchanted by anything controlled by that player.) diff --git a/forge-gui/res/cardsfolder/g/guardian_archon.txt b/forge-gui/res/cardsfolder/g/guardian_archon.txt index 41f8a876109..1e3f3c153c4 100644 --- a/forge-gui/res/cardsfolder/g/guardian_archon.txt +++ b/forge-gui/res/cardsfolder/g/guardian_archon.txt @@ -5,6 +5,6 @@ PT:5/5 K:Flying K:ETBReplacement:Other:ChooseP SVar:ChooseP:DB$ ChoosePlayer | Defined$ You | Choices$ Player.Opponent | ChoiceTitle$ Choose an opponent | Secretly$ True | SpellDescription$ As CARDNAME enters the battlefield, secretly choose an opponent. -A:AB$ Pump | Cost$ RevealChosenPlayer | Defined$ You | KW$ Protection:Player.ChosenPlayer:Protection from ChosenPlayer | DefinedKW$ ChosenPlayer | SubAbility$ DBPump | GameActivationLimit$ 1 | StackDescription$ {p:You} and | SpellDescription$ You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once. -SVar:DBPump:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection:Player.ChosenPlayer:Protection from ChosenPlayer | DefinedKW$ ChosenPlayer | StackDescription$ {c:Targeted} each gain protection from {p:ChosenPlayer} until end of turn. Activate only once. +A:AB$ Pump | Cost$ RevealChosenPlayer | Defined$ You | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | DefinedKW$ ChosenPlayer | SubAbility$ DBPump | GameActivationLimit$ 1 | StackDescription$ {p:You} and | SpellDescription$ You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once. +SVar:DBPump:DB$ Pump | ValidTgts$ Permanent.YouCtrl | TgtPrompt$ Select target permanent you control | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | DefinedKW$ ChosenPlayer | StackDescription$ {c:Targeted} each gain protection from {p:ChosenPlayer} until end of turn. Activate only once. Oracle:Flying\nAs Guardian Archon enters the battlefield, secretly choose an opponent.\nReveal the player you chose: You and target permanent you control each gain protection from the chosen player until end of turn. Activate only once. diff --git a/forge-gui/res/cardsfolder/n/noble_heritage.txt b/forge-gui/res/cardsfolder/n/noble_heritage.txt index 63cc0487d15..34f274f3778 100644 --- a/forge-gui/res/cardsfolder/n/noble_heritage.txt +++ b/forge-gui/res/cardsfolder/n/noble_heritage.txt @@ -9,6 +9,6 @@ SVar:DBChoice:DB$ ChooseCard | Defined$ Player.IsRemembered | Amount$ 1 | MinAmo SVar:DBPutCounter:DB$ PutCounterAll | ValidCards$ Creature.IsRemembered | CounterType$ P1P1 | CounterNum$ 2 | SubAbility$ DBRememberPlayer SVar:DBRememberPlayer:DB$ Pump | RememberObjects$ RememberedController | SubAbility$ DBRepeatEach SVar:DBRepeatEach:DB$ RepeatEach | RepeatPlayers$ Opponent.IsRemembered | RepeatSubAbility$ DBPump | SubAbility$ DBCleanup -SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection:Player.RememberedPlayer:Protection from RememberedPlayer | DefinedKW$ RememberedPlayer | Duration$ UntilYourNextTurn +SVar:DBPump:DB$ Pump | Defined$ You | KW$ Protection:Player.PlayerUID_ChosenPlayerUID:Protection from ChosenPlayerName | DefinedKW$ RememberedPlayer | Duration$ UntilYourNextTurn SVar:DBCleanup:DB$ Cleanup | ClearChosenCard$ True | ClearRemembered$ True Oracle:Commander creatures you own have "When this creature enters the battlefield and at the beginning of your upkeep, each player may put two +1/+1 counters on a creature they control. For each opponent who does, you gain protection from that player until your next turn." (You can't be targeted, dealt damage, or enchanted by anything controlled by that player.)