diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 149d0aec5b66dc4c5792c97ac941a18a4c72a5fa..b47bc0ede7cb02c31486176071c3a78e29f4dff1 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -625,17 +625,16 @@ function _M:playerFOV()
 	end
 
 	--Handle Mark Prey Vision
-	if self:knowTalent(self.T_MARK_PREY) then
-		local t = self:getTalentFromId(self.T_MARK_PREY)
-		for i = 1, t.getCount(self, t) do
-			local e = table.get(self, "marked_prey_tbl", i)
-			if e then
+	if self:hasEffect(self.EFF_PREDATOR) then
+		local uid, e = next(game.level.entities)
+		while uid do
+			if e.marked_prey then
 				game.level.map.seens(e.x, e.y, 0.6)
 			end
+			uid, e = next(game.level.entities, uid)
 		end
 	end
 
-
 	if self:knowTalent(self.T_SHADOW_SENSES) then
 		local t = self:getTalentFromId(self.T_SHADOW_SENSES)
 		local range = self:getTalentRange(t)
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 89186247a8503c7e2ab6c25bc0ea547914b24cf5..deccc1ffab3ec7e3c60a956c21e7c577f6d833c2 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -457,19 +457,13 @@ setDefaultProjector(function(src, x, y, type, dam, state)
 		end
 
 		-- Mark Prey: reduces damage from subtype of marked prey
-		if target.knowTalent and target:knowTalent(target.T_MARK_PREY) and src.subtype then
-			local tMarkPrey = target:getTalentFromId(target.T_MARK_PREY)
-			for i = 1, tMarkPrey.getCount(target, tMarkPrey) do
-				local etype = table.get(target, "mark_prey2", game.level.id, i)
-				if etype and etype == src.subtype then
-					dam = dam * (100 - tMarkPrey.getPower(target, tMarkPrey)) / 100
-					break
-				end
+		if target.hasEffect and target:hasEffect(target.EFF_PREDATOR) and src.subtype then
+			if table.get(target, "mark_prey2", game.level.id, src.subtype) then
+				dam = dam * (100 - target:callTalent(target.T_MARK_PREY, "getPower")) / 100
+				print("[PROJECTOR] predator reduction dam", dam)
 			end
 		end
 
-
-
 		-- Psychic Projection
 		if src.attr and src:attr("is_psychic_projection") and not game.zone.is_dream_scape then
 			if (target.subtype and target.subtype == "ghost") or mind_linked then
diff --git a/game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png b/game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png
new file mode 100644
index 0000000000000000000000000000000000000000..b064dd115c12f05e619d49316d434ed11ec03445
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/terrain/spell_stonewall_01.png differ
diff --git a/game/modules/tome/data/talents/cursed/predator.lua b/game/modules/tome/data/talents/cursed/predator.lua
index cf6c4ff446b9522ba3aee01b6218fb3930c15ba8..992e68273c1ae873a8c2f8ee4692afbe3767ff24 100644
--- a/game/modules/tome/data/talents/cursed/predator.lua
+++ b/game/modules/tome/data/talents/cursed/predator.lua
@@ -275,34 +275,47 @@ newTalent{
 	getPower = function(self, t) return self:combatTalentScale(t, 5, 15) end, --damage reduction handled in damage-types.lua
 	getCount = function(self, t) return math.floor(1 + self:getTalentLevel(t) / 2) end, --vision handled in player.lua
 	doMarkPrey = function(self, t)
-		self.marked_prey_tbl = {}
-		for __, e in pairs(game.level.entities) do
-			if e.marked_prey then
-				self.marked_prey_tbl[#self.marked_prey_tbl+1] = e
-			end
+		local ok = false
+		for _, e in pairs(game.level.entities) do
+			if e.marked_prey then ok = true break end
+		end
+		if ok then self:setEffect(self.EFF_PREDATOR, 1, {power=t.getPower(self, t)})
+		else self:removeEffect(self.EFF_PREDATOR, true, true) end
+	end,
+	on_learn = function(self, t)
+		if self:getTalentLevelRaw(t) == 1 then
+			t.callbackOnChangeLevel(self, t)
+		end
+		t.doMarkPrey(self, t)
+	end,
+	on_unlearn = function(self, t)
+		if self:getTalentLevelRaw(t) == 0 then
+			self:removeEffect(self.EFF_PREDATOR, true, true)
+		else
+			t.doMarkPrey(self, t)
 		end
-		self:setEffect(self.EFF_PREDATOR, 1, {power=t.getPower(self, t), count=t.getCount(self, t)})
 	end,
 	callbackOnChangeLevel = function(self, t)
 		self.mark_prey2 = self.mark_prey2 or {}
 		if self.mark_prey2[game.level.id] then t.doMarkPrey(self, t) return end
 
 		local marks = {}
-		for __, e in pairs(game.level.entities) do
-			if e.rank and e.subtype and e.rank >= 3.2 and self:reactionToward(e) < 0 then
-				marks[#marks+1] = {e=e, rank=e.rank, subtype=e.subtype}
+		for _, e in pairs(game.level.entities) do
+			if e.rank and e.subtype and e.rank and self:reactionToward(e) < 0 then
+				marks[#marks+1] = {e=e, rank=e.rank or 0, max_life=e.max_life or 1, subtype=tostring(e.subtype)}
 			end
 		end
+		table.sort(marks, function(a, b)
+			if a.rank == b.rank then return a.max_life < b.max_life
+			else return a.rank < b.rank end
+		end)
 
-		if #marks > 0 then table.sort(marks, "rank") else return end
 		self.mark_prey2[game.level.id] = {}
-		for i = 1, t.getCount(self, t) do
-			if #marks > 0 then
-				marks[#marks].e.marked_prey = true
-				self.mark_prey2[game.level.id][i] = marks[#marks].subtype
-				table.remove(marks)
-			else break
-			end
+		local nb = t.getCount(self, t)
+		while #marks > 0 and nb > 0 do
+			local m = table.remove(marks); nb = nb - 1
+			self.mark_prey2[game.level.id][m.subtype] = true
+			m.e.marked_prey = true
 		end
 
 		t.doMarkPrey(self, t)
diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua
index b5bf3908db7641ec2571cabf09615db465331148..14cbd32648e4294ee478b885465a42871a5a0b80 100644
--- a/game/modules/tome/data/timed_effects/other.lua
+++ b/game/modules/tome/data/timed_effects/other.lua
@@ -1917,27 +1917,25 @@ newEffect{
 	decrease = 0,
 	cancel_on_level_change = true,
 	long_desc = function(self, eff)
-		local desc = ("Hunting:")
-		local desc2 = ("\n%d%% Received damage reduction against SubType:"):format(eff.power)
-		if not game.level then return desc..desc2
-		else for i = 1, eff.count do
-			local e = table.get(self, "marked_prey_tbl", i)
-			local etype = table.get(self, "mark_prey2", game.level.id, i)
-			if e and e.name and not e.dead then
-				local mprank, mpcolour = e:TextRank()
-				desc = desc..("\n%s%s.#LAST#"):format(mpcolour, e.name:capitalize())
-			end
-			if etype then
-				for j = 1, i do
-					local etype2 = table.get(self, "mark_prey2", game.level.id, j)
-					if etype2 and j ~= i and etype == etype2 then eff.unique_subtype = nil break
-					else eff.unique_subtype = true end
-				end
-				if eff.unique_subtype then
-					desc2 = desc2..("\n#ffa0ff#%s.#LAST#"):format(etype:capitalize())
-				end
-			end
+		local desc = "Hunting:"
+		local desc2 = ("\n%d%% Received damage reduction against:"):format(eff.power)
+		if not game.level then return desc..desc2 end
+
+		local preys = {}
+		for uid, e in pairs(game.level.entities) do if e.marked_prey then
+			preys[#preys+1] = e
 		end end
+		table.sort(preys, "rank")
+		for _, p in ripairs(preys) do
+			local mprank, mpcolour = p:TextRank()
+			desc = desc..("\n- %s%s#LAST#"):format(mpcolour, p.name:capitalize())
+		end
+
+		local subtypes_list = table.get(self, "mark_prey2", game.level.id)
+		for st, _ in pairs(subtypes_list) do
+			desc2 = desc2..("\n- #ffa0ff#%s#LAST#"):format(tostring(st):capitalize())
+		end
+
 		return desc..desc2
 	end,
 	type = "other",