diff --git a/forge-game/src/main/java/forge/game/Game.java b/forge-game/src/main/java/forge/game/Game.java
index 89d57e82647..179d19a3e3d 100644
--- a/forge-game/src/main/java/forge/game/Game.java
+++ b/forge-game/src/main/java/forge/game/Game.java
@@ -17,35 +17,16 @@
*/
package forge.game;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import forge.game.card.*;
-import org.apache.commons.lang3.tuple.Pair;
-
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
-import com.google.common.collect.ArrayListMultimap;
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Table;
+import com.google.common.collect.*;
import com.google.common.eventbus.EventBus;
-
import forge.GameCommand;
import forge.card.CardRarity;
import forge.card.CardStateName;
import forge.card.CardType.Supertype;
import forge.game.ability.AbilityKey;
+import forge.game.card.*;
import forge.game.combat.Combat;
import forge.game.event.Event;
import forge.game.event.GameEventDayTimeChanged;
@@ -54,11 +35,7 @@ import forge.game.phase.Phase;
import forge.game.phase.PhaseHandler;
import forge.game.phase.PhaseType;
import forge.game.phase.Untap;
-import forge.game.player.IGameEntitiesFactory;
-import forge.game.player.Player;
-import forge.game.player.PlayerCollection;
-import forge.game.player.PlayerView;
-import forge.game.player.RegisteredPlayer;
+import forge.game.player.*;
import forge.game.replacement.ReplacementHandler;
import forge.game.spellability.SpellAbility;
import forge.game.spellability.SpellAbilityStackInstance;
@@ -73,6 +50,9 @@ import forge.util.Aggregates;
import forge.util.MyRandom;
import forge.util.Visitor;
import forge.util.collect.FCollection;
+import org.apache.commons.lang3.tuple.Pair;
+
+import java.util.*;
/**
* Represents the state of a single game, a new instance is created for each game.
diff --git a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java
index e16ec8b9857..c07209ed5de 100644
--- a/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java
+++ b/forge-game/src/main/java/forge/game/ability/effects/EffectEffect.java
@@ -19,6 +19,7 @@ import forge.game.ability.AbilityUtils;
import forge.game.ability.SpellAbilityEffect;
import forge.game.card.*;
import forge.game.player.Player;
+import forge.game.player.PlayerCollection;
import forge.game.replacement.ReplacementEffect;
import forge.game.replacement.ReplacementHandler;
import forge.game.spellability.SpellAbility;
@@ -52,7 +53,6 @@ public class EffectEffect extends SpellAbilityEffect {
FCollection rememberList = null;
String effectImprinted = null;
String noteCounterDefined = null;
- List effectOwner = null;
final String duration = sa.getParam("Duration");
if (((duration != null && duration.startsWith("UntilHostLeavesPlay")) || "UntilLoseControlOfHost".equals(duration) || "UntilUntaps".equals(duration))
@@ -134,15 +134,21 @@ public class EffectEffect extends SpellAbilityEffect {
name = hostCard + (sa.hasParam("Boon") ? "'s Boon" : "'s Effect");
}
- // Unique Effects shouldn't be duplicated
- if (sa.hasParam("Unique") && game.isCardInCommand(name)) {
- return;
+ PlayerCollection effectOwner = sa.hasParam("EffectOwner") ?
+ AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("EffectOwner"), sa) :
+ new PlayerCollection(sa.getActivatingPlayer());
+
+ // Unique$ is for effects that should be one per player (e.g. Gollum, Obsessed Stalker)
+ if (sa.hasParam("Unique")) {
+ for (Player eo : effectOwner.threadSafeIterable()) {
+ if (eo.isCardInCommand(name)) {
+ effectOwner.remove(eo);
+ }
+ }
}
- if (sa.hasParam("EffectOwner")) {
- effectOwner = AbilityUtils.getDefinedPlayers(hostCard, sa.getParam("EffectOwner"), sa);
- } else {
- effectOwner = Lists.newArrayList(sa.getActivatingPlayer());
+ if (effectOwner.isEmpty()) {
+ return; // return if we don't need to make an effect
}
String image;
diff --git a/forge-game/src/main/java/forge/game/player/PlayerCollection.java b/forge-game/src/main/java/forge/game/player/PlayerCollection.java
index 784a1a60b38..37034edde38 100644
--- a/forge-game/src/main/java/forge/game/player/PlayerCollection.java
+++ b/forge-game/src/main/java/forge/game/player/PlayerCollection.java
@@ -23,6 +23,10 @@ public class PlayerCollection extends FCollection {
this.addAll(players);
}
+ public PlayerCollection(Player player) {
+ this.add(player);
+ }
+
// card collection functions
public final CardCollection getCardsIn(ZoneType zone) {
CardCollection result = new CardCollection();
diff --git a/forge-gui/res/cardsfolder/a/approach_of_the_second_sun.txt b/forge-gui/res/cardsfolder/a/approach_of_the_second_sun.txt
index 8c7a9759bf1..8c8da8e5243 100644
--- a/forge-gui/res/cardsfolder/a/approach_of_the_second_sun.txt
+++ b/forge-gui/res/cardsfolder/a/approach_of_the_second_sun.txt
@@ -1,7 +1,7 @@
Name:Approach of the Second Sun
ManaCost:6 W
Types:Sorcery
-T:Mode$ SpellCast | ValidCard$ Card.Self | Static$ True | Execute$ ApproachingSuns
+T:Mode$ SpellCast | ValidCard$ Card.Self+namedApproach of the Second Sun | Static$ True | Execute$ ApproachingSuns
SVar:ApproachingSuns:DB$ Effect | Name$ ApproachingSuns | Duration$ Permanent
A:SP$ Branch | Cost$ 6 W | BranchConditionSVar$ X | BranchConditionSVarCompare$ EQ3 | TrueSubAbility$ WinGame | FalseSubAbility$ GainLife | SpellDescription$ If this spell was cast from your hand and you've cast another spell named Approach of the Second Sun this game, you win the game. Otherwise, put CARDNAME into its owner's library seventh from the top and you gain 7 life.
SVar:WinGame:DB$ WinsGame | Defined$ You
diff --git a/forge-gui/res/cardsfolder/upcoming/gollum_obsessed_stalker.txt b/forge-gui/res/cardsfolder/upcoming/gollum_obsessed_stalker.txt
new file mode 100644
index 00000000000..3a35abf340a
--- /dev/null
+++ b/forge-gui/res/cardsfolder/upcoming/gollum_obsessed_stalker.txt
@@ -0,0 +1,12 @@
+Name:Gollum, Obsessed Stalker
+ManaCost:1 B
+Types:Legendary Creature Halfling Horror
+PT:1/1
+K:Skulk
+T:Mode$ DamageDone | CombatDamage$ True | ValidSource$ Card.namedGollum; Obsessed Stalker | ValidTarget$ Player | Static$ True | Execute$ NoteDamaged
+SVar:NoteDamaged:DB$ Effect | Name$ Damaged by Gollum, Obsessed Stalker | Duration$ Permanent | EffectOwner$ TriggeredTarget | Unique$ True
+T:Mode$ Phase | Phase$ End of Turn | ValidPlayer$ You | Execute$ TrigLoseLife | TriggerZones$ Battlefield | TriggerDescription$ At the beginning of your end step, each opponent dealt combat damage this game by a creature named Gollum, Obsessed Stalker loses life equal to the amount of life you gained this turn.
+SVar:TrigLoseLife:DB$ LoseLife | LifeAmount$ X | Defined$ Opponent.HasCardsInCommand_Effect.namedDamaged by Gollum; Obsessed Stalker_GE1
+SVar:X:Count$LifeYouGainedThisTurn
+DeckNeeds:Ability$LifeGain
+Oracle:Skulk (This creature can't be blocked by creatures with greater power.)\nAt the beginning of your end step, each opponent dealt combat damage this game by a creature named Gollum, Obsessed Stalker loses life equal to the amount of life you gained this turn.