diff --git a/game/modules/tome/ai/shadow.lua b/game/modules/tome/ai/shadow.lua
index d4309addf9379c4dd1dbf63290763b6971611b8a..2cff0cf73c481ec40c1b9ff01d7e28bd722fd076 100644
--- a/game/modules/tome/ai/shadow.lua
+++ b/game/modules/tome/ai/shadow.lua
@@ -59,6 +59,20 @@ local function shadowChooseActorTarget(self)
 end
 
 local function shadowMoveToActorTarget(self)
+	local range = math.floor(core.fov.distance(self.x, self.y, self.ai_target.actor.x, self.ai_target.actor.y))
+	
+	if range <= 1 and self.ai_state.close_attack_spell_chance and rng.percent(self.ai_state.close_attack_spell_chance) then
+		-- chance for close spell
+		if self:closeAttackSpell() then return true end
+	elseif range <= 6 and self.ai_state.far_attack_spell_chance and rng.percent(self.ai_state.far_attack_spell_chance) then
+		-- chance for a far spell
+		if self:farAttackSpell() then return true end
+	end
+	
+	if range <= 1 and self.ai_state.dominate_chance and rng.percent(self.ai_state.dominate_chance) then
+		if self:dominate() then return true end
+	end
+	
 	-- use the target blindside chance if it was assigned; otherwise, use the normal chance
 	local blindsideChance = self.ai_target.blindside_chance or self.ai_state.blindside_chance
 	self.ai_target.blindside_chance = nil
@@ -76,17 +90,8 @@ local function shadowMoveToActorTarget(self)
 		end
 	end
 	
-	if self:canAttackSpell() then
-		-- use the attack spell chance if it was assigned; otherwise, use the normal chance
-		local attackSpellChance = self.ai_target.attack_spell_chance or self.ai_state.attack_spell_chance
-		self.ai_target.attack_spell_chance = nil
-		if rng.percent(attackSpellChance) and self:attackSpell() then
-			return true
-		end
-	end
-	
 	-- chance to reset target next turn if we are attacking (unless we have been focused)
-	if math.floor(core.fov.distance(self.x, self.y, self.ai_target.actor.x, self.ai_target.actor.y)) <= 1 and rng.percent(20) then
+	if range <= 1 and rng.percent(20) then
 		--game.logPlayer(self.summoner, "#PINK#%s is about to attack.", self.name:capitalize())
 		if not self.ai_state.focus_on_target then
 			self.ai_state.target_time = self.ai_state.target_timeout
@@ -198,32 +203,28 @@ newAI("shadow", function(self)
 		clearTarget(self)
 	end
 	
-	-- apply feed
-	if self.summoner:knowTalent(self.summoner.T_FEED_SHADOWS) then
-		local t = self.summoner:getTalentFromId(self.summoner.T_FEED_SHADOWS)
-		self:feed(t)
-	end
-	
 	-- shadow wall
 	if self.ai_state.shadow_wall then
+		
 		clearTarget(self)
+		
+		local defendant = self.ai_state.shadow_wall_target
 	
-		if self.ai_state.shadow_wall_time <= 0 then
+		if self.ai_state.shadow_wall_time <= 0 or defendant.dead then
 			self.ai_state.shadow_wall = false
 		else
 			self.ai_state.shadow_wall_time = self.ai_state.shadow_wall_time - 1
 		
-			local range = core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y)
-			if range > 3 then
+			local range = core.fov.distance(self.x, self.y, defendant.x, defendant.y)
+			if range >= 3 then
 				-- phase door into range
 				self:useTalent(self.T_SHADOW_PHASE_DOOR)
 				return true
 			elseif range > 1 then
-				self.ai_target.x = self.summoner.x
-				self.ai_target.y = self.summoner.y
+				self.ai_target.x = defendant.x
+				self.ai_target.y = defendant.y
 				if shadowMoveToLocationTarget(self) then return true end
 			end
-			
 			-- no action..look for a target to attack
 			local newX, newY
 			local start = rng.range(0, 8)
@@ -235,7 +236,7 @@ newAI("shadow", function(self)
 					self:attackTarget(target, nil, 1, true)
 					return true
 				end
-				if not newX and math.floor(core.fov.distance(x, y, self.summoner.x, self.summoner.y)) <= 1 and self:canMove(x, y, false) then
+				if not newX and math.floor(core.fov.distance(x, y, defendant.x, defendant.y)) <= 1 and self:canMove(x, y, false) then
 					newX, newY = x, y
 				end
 			end
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 90ba745840da369eeaeea4c2a7834723d4f81cea..f489cff67fa81ed1b9f56f09dc067986d26fb98f 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -943,8 +943,7 @@ function _M:onTakeHit(value, src)
 			self:forceUseTalent(self.T_SHIELD_OF_LIGHT, {ignore_energy=true})
 		end
 	end
-
-
+	
 	-- Second Life
 	if self:isTalentActive(self.T_SECOND_LIFE) and value >= self.life then
 		local sl = self.max_life * (0.05 + self:getTalentLevelRaw(self.T_SECOND_LIFE)/25)
@@ -953,6 +952,18 @@ function _M:onTakeHit(value, src)
 		game.logSeen(self, "%s has been saved by a blast of positive energy!", self.name:capitalize())
 		self:forceUseTalent(self.T_SECOND_LIFE, {ignore_energy=true})
 	end
+	
+	if value >= self.life and self.ai_state and self.ai_state.can_reform then
+		local t = self:getTalentFromId(self.T_SHADOW_REFORM)
+		if rng.percent(t.getChance(self, t)) then
+			value = 0
+			self.life = self.max_life
+			game.logSeen(self, "%s fades for a moment and then reforms whole again!", self.name:capitalize())
+			game.level.map:particleEmitter(self.x, self.y, 1, "teleport_out")
+			game:playSoundNear(self, "talents/heal")
+			game.level.map:particleEmitter(self.x, self.y, 1, "teleport_in")
+		end
+	end
 
 	if self:knowTalent(self.T_LEECH) and src.hasEffect and src:hasEffect(src.EFF_VIMSENSE) then
 		self:incVim(3 + self:getTalentLevel(self.T_LEECH) * 0.7)
diff --git a/game/modules/tome/data/birth/classes/afflicted.lua b/game/modules/tome/data/birth/classes/afflicted.lua
index 7335b31d1d206ee28aee2a17ef4aac22cd87989b..f0db10dfe30077627617158231cbc111df7fcbfd 100644
--- a/game/modules/tome/data/birth/classes/afflicted.lua
+++ b/game/modules/tome/data/birth/classes/afflicted.lua
@@ -56,7 +56,6 @@ newBirthDescriptor{
 		["cursed/slaughter"]={true, 0.0},
 		["cursed/endless-hunt"]={true, 0.0},
 		["cursed/cursed-form"]={true, 0.0},
-		["cursed/traveler"]={true, 0.0},
 		["technique/combat-training"]={true, 0.3},
 		["cunning/survival"]={false, 0.0},
 		["cursed/rampage"]={false, 0.0},
@@ -102,7 +101,7 @@ newBirthDescriptor{
 		["cursed/shadows"]={true, 0.3},
 		["cursed/darkness"]={true, 0.3},
 		["cursed/cursed-form"]={true, 0.0},
-		["cursed/traveler"]={true, 0.0},
+		["cunning/survival"]={false, 0.0},
 		["cursed/dark-figure"]={false, 0.0},
 	},
 	talents = {
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 7bfa4b2a559962fcff5104940c2c50fb63544d4d..c24f527a03ba8488ad40e17f5551bad07d3dee66 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -1301,4 +1301,19 @@ newDamageType{
 			target:setEffect(target.EFF_SPEED, 3, {power=0.6})
 		end
 	end,
-}
\ No newline at end of file
+}
+
+newDamageType{
+	name = "devour life", type = "DEVOUR_LIFE",
+	projector = function(src, x, y, type, dam)
+		if _G.type(dam) == "number" then dam = {dam=dam} end
+		local target = game.level.map(x, y, Map.ACTOR) -- Get the target first to make sure we heal even on kill
+		local realdam = DamageType:get(DamageType.PHYSICAL).projector(src, x, y, DamageType.PHYSICAL, dam.dam)
+		if target and realdam > 0 then
+			local heal = realdam * (dam.healfactor or 1)
+			src:heal(heal)
+			game.logSeen(target, "%s consumes %d life from %s!", src.name:capitalize(), heal, target.name)
+		end
+	end,
+	hideMessage=true,
+}
diff --git a/game/modules/tome/data/talents/cursed/dark-figure.lua b/game/modules/tome/data/talents/cursed/dark-figure.lua
index 7290078a142b527a2b637d66f077cebbf6adcb9f..b3c5c04ba7172d05453b1b236db5a54895d8671f 100644
--- a/game/modules/tome/data/talents/cursed/dark-figure.lua
+++ b/game/modules/tome/data/talents/cursed/dark-figure.lua
@@ -31,6 +31,7 @@ newTalent{
 	getRadius = function(self, t) return 3 + math.floor((self:getTalentLevelRaw(t) - 1) / 2) end,
 	getDuration = function(self, t) return 5 + math.floor(self:getTalentLevel(t) * 2) end,
 	tactical = { DISABLE = 2 },
+	requires_target = true,
 	range = 6,
 	action = function(self, t)
 		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
diff --git a/game/modules/tome/data/talents/cursed/dark-sustenance.lua b/game/modules/tome/data/talents/cursed/dark-sustenance.lua
index 2bfeeeecebffcb34bafd4997b0954b50c75276df..42487b89e44db4dba6e174adc29d8e6862e1c49f 100644
--- a/game/modules/tome/data/talents/cursed/dark-sustenance.lua
+++ b/game/modules/tome/data/talents/cursed/dark-sustenance.lua
@@ -17,6 +17,14 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
+local function combatTalentDamage(self, t, min, max)
+	return self:combatTalentSpellDamage(t, min, max, self.level + self:getWil())
+end
+
+local function combatPower(self, t, multiplier)
+	return (self.level + self:getWil()) * (multiplier or 1)
+end
+
 newTalent{
 	name = "Feed",
 	type = {"cursed/dark-sustenance", 1},
@@ -26,25 +34,25 @@ newTalent{
 	cooldown = 6,
 	range = 7,
 	tactical = { BUFF = 2, DEFEND = 1 },
-	requires_target = true,
+	requires_target = function(self, t) return self:getTalentLevel(t) >= 5 end,
+	direct_hit = true,
 	getHateGain = function(self, t)
 		return math.sqrt(self:getTalentLevel(t)) * 0.2 + self:getWil(0.15)
 	end,
 	action = function(self, t)
-		local tg = {type="hit", range=self:getTalentRange(t)}
+		local range = self:getTalentRange(t)
+		local tg = {type="hit", range=range}
 		local x, y, target = self:getTarget(tg)
-		if not x or not y or not target then return nil end
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range then return nil end
 
 		if self:reactionToward(target) >= 0 or target.summoner == self then
 			game.logPlayer(self, "You can only gain sustenance from your foes!");
 			return nil
 		end
 
-		print("*** targeted");
-
 		-- remove old effect
-		if self:hasEffect(self.EFF_FEED_HATE) then
-			self:removeEffect(self.EFF_FEED_HATE)
+		if self:hasEffect(self.EFF_FEED) then
+			self:removeEffect(self.EFF_FEED)
 		end
 
 		local hateGain = t.getHateGain(self, t)
@@ -53,11 +61,11 @@ newTalent{
 		local damageGain = 0
 		local resistGain = 0
 
-		local tFeedHealth = self:getTalentFromId(self.T_FEED_HEALTH)
-		if tFeedHealth and self:getTalentLevelRaw(tFeedHealth) > 0 then
-			constitutionGain = tFeedHealth.getConstitutionGain(self, tFeedHealth, target)
-			lifeRegenGain = tFeedHealth.getLifeRegenGain(self, tFeedHealth)
-		end
+		--local tFeedHealth = self:getTalentFromId(self.T_FEED_HEALTH)
+		--if tFeedHealth and self:getTalentLevelRaw(tFeedHealth) > 0 then
+		--	constitutionGain = tFeedHealth.getConstitutionGain(self, tFeedHealth, target)
+		--	lifeRegenGain = tFeedHealth.getLifeRegenGain(self, tFeedHealth)
+		--end
 
 		local tFeedPower = self:getTalentFromId(self.T_FEED_POWER)
 		if tFeedPower and self:getTalentLevelRaw(tFeedPower) > 0 then
@@ -75,11 +83,67 @@ newTalent{
 	end,
 	info = function(self, t)
 		local hateGain = t.getHateGain(self, t)
-		return ([[Feed from the essence of your enemy. Draws %0.2f hate per turn from a targeted foe as long as the foe remains in your line of sight.
+		return ([[Feed from the essence of your enemy. Draws %0.2f hate per turn from a targeted foe as long as the they remain in your line of sight.
 		Improves with the Willpower stat.]]):format(hateGain)
 	end,
 }
 
+newTalent{
+	name = "Devour Life",
+	type = {"cursed/dark-sustenance", 2},
+	require = cursed_wil_req2,
+	points = 5,
+	random_ego = "attack",
+	cooldown = 6,
+	range = 7,
+	tactical = { BUFF = 2, DEFEND = 1 },
+	direct_hit = true,
+	requires_target = true,
+	getLifeSteal = function(self, t, target)
+		return combatTalentDamage(self, t, 20, 120)
+	end,
+	action = function(self, t)
+		local effect = self:hasEffect(self.EFF_FEED)
+		if not effect then
+			if self:getTalentLevel(t) >= 5 then
+				local tFeed = self:getTalentFromId(self.T_FEED)
+				if not tFeed.action(self, tFeed) then return nil end
+				
+				effect = self:hasEffect(self.EFF_FEED)
+			else
+				game.logPlayer(self, "You must begin feeding before you can Devour Life.");
+				return nil
+			end
+		end
+		local target = effect.target
+		
+		if target and not target.dead then
+			local lifeSteal = t.getLifeSteal(self, t)
+			self:project({type="hit", x=target.x,y=target.y}, target.x, target.y, DamageType.DEVOUR_LIFE, { dam=lifeSteal })
+			
+			game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(target.x-self.x), math.abs(target.y-self.y)), "dark_torrent", {tx=target.x-self.x, ty=target.y-self.y})
+			--local dx, dy = target.x - self.x, target.y - self.y
+			--game.level.map:particleEmitter(self.x, self.y,math.max(math.abs(dx), math.abs(dy)), "feed_hate", { tx=dx, ty=dy })
+			game:playSoundNear(self, "talents/fire")
+			
+			return true
+		end
+		
+		return nil
+	end,
+	info = function(self, t)
+		local lifeSteal = t.getLifeSteal(self, t)
+		if self:getTalentLevel(t) >= 5 then
+			return ([[Devours life from the target of your feeding. %d life from the victim will be added to your own. Devour Life can be used like the Feed talent to begin feeding.
+			Improves with the Willpower stat.]]):format(lifeSteal)
+		else
+			return ([[Devours life from the target of your feeding. %d life from the victim will be added to your own. At level 5 Devour Life can be used like the Feed talent to begin feeding.
+			Improves with the Willpower stat.]]):format(lifeSteal)
+		end
+	end,
+}
+
+--[[
 newTalent{
 	name = "Feed Health",
 	type = {"cursed/dark-sustenance", 2},
@@ -102,11 +166,11 @@ newTalent{
 	info = function(self, t)
 		local constitutionGain = t.getConstitutionGain(self, t)
 		local lifeRegenGain = t.getLifeRegenGain(self, t)
-		return ([[Enhances your feeding by transferring %d constitution and %0.1f life per turn from a targeted foe to you.
-		Improves with the Willpower stat.]]):format(constitutionGain, lifeRegenGain)
+		return ([Enhances your feeding by transferring %d constitution and %0.1f life per turn from a targeted foe to you.
+		Improves with the Willpower stat.]):format(constitutionGain, lifeRegenGain)
 	end,
 }
-
+]]
 newTalent{
 	name = "Feed Power",
 	type = {"cursed/dark-sustenance", 3},
diff --git a/game/modules/tome/data/talents/cursed/darkness.lua b/game/modules/tome/data/talents/cursed/darkness.lua
index 04ef6baf0922fc6c6fd120381b6d6a692b262dfc..51dd4a84449db48e3bf82f1497bcc28a09938219 100644
--- a/game/modules/tome/data/talents/cursed/darkness.lua
+++ b/game/modules/tome/data/talents/cursed/darkness.lua
@@ -46,7 +46,7 @@ local function createDarkTendrils(summoner, x, y, target, damage, duration, pinD
 			local done = false
 			local hitTarget = false
 
-			local tCreepingDarkness = self.summoner:getTalentFromId(summoner.T_CREEPING_DARKNESS)
+			local tCreepingDarkness = self.summoner:getTalentFromId(self.summoner.T_CREEPING_DARKNESS)
 
 			if self.finalizing then
 				if self.duration <= 0 or self.target.dead or self.x ~= self.target.x or self.y ~= self.target.y then
@@ -295,7 +295,6 @@ newTalent{
 		local locations = {}
 		local grids = core.fov.circle_grids(x, y, radius, true)
 		for darkX, yy in pairs(grids) do for darkY, _ in pairs(grids[darkX]) do
-			print("*** pairs", darkX, darkY)
 			local l = line.new(x, y, darkX, darkY)
 			local lx, ly = l()
 			while lx and ly do
@@ -307,7 +306,6 @@ newTalent{
 
 			if lx == darkX and ly == darkY and t.canCreep(darkX, darkY) then
 				locations[#locations+1] = {darkX, darkY}
-				print("*** locations", darkX, darkY)
 			end
 		end end
 
@@ -349,6 +347,17 @@ newTalent{
 
 		return 5 + (level - 3) * 3
 	end,
+	hasLOS = function(x1, y1, x2, y2)
+		local l = line.new(x1, y1, x2, y2)
+		local lx, ly = l()
+		while lx and ly do
+			local entity = game.level.map:checkAllEntities(lx, ly, "block_sight")
+			if entity and not game.level.map:checkAllEntities(lx, ly, "creepingDark") then return false end
+
+			lx, ly = l()
+		end
+		return true
+	end,
 	info = function(self, t)
 		local damageIncrease = t.getDamageIncrease(self, t)
 		if damageIncrease <= 0 then
@@ -369,7 +378,6 @@ newTalent{
 	cooldown = 6,
 	tactical = { ATTACK = 2, DISABLE = 1 },
 	range = 5,
-	direct_hit = true,
 	reflectable = true,
 	requires_target = true,
 	getDamage = function(self, t)
@@ -422,6 +430,8 @@ newTalent{
 	hate =  1.2,
 	range = 6,
 	tactical = { ATTACK = 2, DISABLE = 2 },
+	direct_hit = true,
+	requires_target = true,
 	getPinDuration = function(self, t)
 		return 1 + math.floor(self:getTalentLevel(t) / 2)
 	end,
@@ -431,9 +441,10 @@ newTalent{
 	action = function(self, t)
 		if self.dark_tendrils then return false end
 
-		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local range = self:getTalentRange(t)
+		local tg = {type="hit", range=range, talent=t}
 		local x, y, target = self:getTarget(tg)
-		if not x or not y or not target then return nil end
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range then return nil end
 
 		local pinDuration = t.getPinDuration(self, t)
 		local damage = t.getDamage(self, t)
diff --git a/game/modules/tome/data/talents/cursed/force-of-will.lua b/game/modules/tome/data/talents/cursed/force-of-will.lua
index feaf482bb068f8767ac1225fd28604c2002faadc..79ba231536302f6c381cdb081b0751c5ee76ea98 100644
--- a/game/modules/tome/data/talents/cursed/force-of-will.lua
+++ b/game/modules/tome/data/talents/cursed/force-of-will.lua
@@ -103,6 +103,8 @@ newTalent{
 	cooldown = 4,
 	hate = 0.5,
 	tactical = { ATTACK = 2 },
+	direct_hit = true,
+	requires_target = true,
 	range = function(self, t)
 		return 4
 	end,
@@ -117,11 +119,10 @@ newTalent{
 
 		local tg = {type="hit", range=self:getTalentRange(t)}
 		local x, y, target = self:getTarget(tg)
-		if not x or not y or not target then return nil end
-
-		local distance = math.max(1, math.floor(core.fov.distance(self.x, self.y, x, y)))
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range then return nil end
 
-		local power = (1 - ((distance - 1) / range))
+		--local distance = math.max(1, math.floor(core.fov.distance(self.x, self.y, x, y)))
+		local power = 1 --(1 - ((distance - 1) / range))
 		local damage = t.getDamage(self, t) * power
 		local knockback = t.getKnockback(self, t)
 		forceHit(self, target, self.x, self.y, damage, knockback, 15, power)
@@ -130,7 +131,7 @@ newTalent{
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
 		local knockback = t.getKnockback(self, t)
-		return ([[Focusing your hate you strike your foe with unseen force for up to %d damage and %d knockback at a range of 1. Damage decreases the further you are from your target.
+		return ([[Focusing your hate you strike your foe with unseen force for %d damage and %d knockback.
 		Damage increases with the Willpower stat.]]):format(damDesc(self, DamageType.PHYSICAL, damage), knockback)
 	end,
 }
@@ -145,7 +146,6 @@ newTalent{
 	cooldown = 12,
 	tactical = { DEFEND = 2 },
 	no_sustain_autoreset = true,
-	direct_hit = true,
 	getMaxDamage = function(self, t)
 		return combatTalentDamage(self, t, 20, 200)
 	end,
@@ -210,6 +210,7 @@ newTalent{
 	random_ego = "attack",
 	cooldown = 10,
 	tactical = { ATTACK = 2 },
+	requires_target = true,
 	hate = 1.5,
 	range = function(self, t)
 		return 4
@@ -231,7 +232,7 @@ newTalent{
 
 		local tg = {type="ball", nolock=true, pass_terrain=false, friendly_fire=false, nowarning=true, range=range, radius=radius, talent=t}
 		local blastX, blastY = self:getTarget(tg)
-		if not blastX or not blastY then return nil end
+		if not blastX or not blastY or core.fov.distance(self.x, self.y, blastX, blastY) > range then return nil end
 
 		local grids = self:project(tg, blastX, blastY,
 			function(x, y, target, self)
@@ -269,7 +270,6 @@ newTalent{
 	hate = 2,
 	cooldown = 50,
 	tactical = { ATTACKAREA = 2 },
-	direct_hit = true,
 	range = function(self, t)
 		return math.floor(4 + self:getTalentLevel(t) / 2.3)
 	end,
diff --git a/game/modules/tome/data/talents/cursed/punishments.lua b/game/modules/tome/data/talents/cursed/punishments.lua
index 780c6cdf0b6b76655c157c0dd4389dce2855683d..7eed24bbca6a58af678377675abf291cb96b3406 100644
--- a/game/modules/tome/data/talents/cursed/punishments.lua
+++ b/game/modules/tome/data/talents/cursed/punishments.lua
@@ -84,6 +84,8 @@ newTalent{
 	hate =  0.8,
 	range = 7,
 	tactical = { ATTACK = 2 },
+	direct_hit = true,
+	requires_target = true,
 	getDuration = function(self, t)
 		return 10
 	end,
@@ -103,7 +105,7 @@ newTalent{
 		local range = self:getTalentRange(t)
 		local tg = {type="hit", range=range}
 		local x, y, target = self:getTarget(tg)
-		if not x or not y or not target or target:hasEffect(target.EFF_HATEFUL_WHISPER) then return nil end
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range or target:hasEffect(target.EFF_HATEFUL_WHISPER) then return nil end
 
 		local duration = t.getDuration(self, t)
 		local damage = t.getDamage(self, t)
@@ -260,6 +262,8 @@ newTalent{
 	hate =  0.5,
 	range = 7,
 	tactical = { ATTACK = 2 },
+	direct_hit = true,
+	requires_target = true,
 	getDuration = function(self, t)
 		return 5
 	end,
@@ -273,7 +277,7 @@ newTalent{
 		local range = self:getTalentRange(t)
 		local tg = {type="hit", range=range}
 		local x, y, target = self:getTarget(tg)
-		if not x or not y or not target then return nil end
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range then return nil end
 
 		local damage = t.getDamage(self, t)
 		local mindpower = t.getMindpower(self, t)
diff --git a/game/modules/tome/data/talents/cursed/shadows.lua b/game/modules/tome/data/talents/cursed/shadows.lua
index 39ecc72c0d2303fd17246367135da743f4e33038..b0502d8f92747fb2dbc89e4064e755dfea9b8a29 100644
--- a/game/modules/tome/data/talents/cursed/shadows.lua
+++ b/game/modules/tome/data/talents/cursed/shadows.lua
@@ -27,7 +27,7 @@ newTalent{
 	action = function(self, t)
 		local x, y, range
 		if self.ai_state.shadow_wall then
-			x, y, range = self.summoner.x, self.summoner.y, 1
+			x, y, range = self.ai_state.shadow_wall_target.x, self.ai_state.shadow_wall_target.y, 1
 		elseif self.ai_target.x and self.ai_target.y then
 			x, y, range = self.ai_target.x, self.ai_target.y, 1
 		else
@@ -82,6 +82,82 @@ newTalent{
 	end,
 }
 
+newTalent{
+	short_name = "SHADOW_LIGHTNING",
+	name = "Shadow Lightning",
+	type = {"spell/other", 1},
+	require = { },
+	points = 5,
+	random_ego = "attack",
+	range = 1,
+	direct_hit = true,
+	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 20, 200) end,
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local dam = self:spellCrit(t.getDamage(self, t))
+		self:project(tg, x, y, DamageType.LIGHTNING, rng.avg(dam / 3, dam, 3))
+		local _ _, x, y = self:canProject(tg, x, y)
+		game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(x-self.x), math.abs(y-self.y)), "lightning", {tx=x-self.x, ty=y-self.y})
+		game:playSoundNear(self, "talents/lightning")
+		return true
+	end,
+	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		return ([[Strikes the target with a spark of lightning doing %0.2f to %0.2f damage.
+		The damage will increase with the Magic stat]]):
+		format(damDesc(self, DamageType.LIGHTNING, damage / 3),
+		damDesc(self, DamageType.LIGHTNING, damage))
+	end,
+}
+
+newTalent{
+	short_name = "SHADOW_FLAMES",
+	name = "Shadow Flames",
+	type = {"spell/other", 1},
+	require = { },
+	points = 5,
+	random_ego = "attack",
+	range = 6,
+	direct_hit = true,
+	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 20, 140) end,
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local dam = self:spellCrit(t.getDamage(self, t))
+		self:project(tg, x, y, DamageType.FIRE, dam)
+		game.level.map:particleEmitter(x, y, 1, "flame")
+		game:playSoundNear(self, "talents/fire")
+		return true
+	end,
+	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		return ([[Bathes the target in flames doing %0.2f damage
+		The damage will increase with the Magic stat]]):
+		format(damDesc(self, DamageType.FIREBURN, damage))
+	end,
+}
+
+newTalent{
+	short_name = "SHADOW_REFORM",
+	name = "Reform",
+	type = {"spell/other", 1},
+	require = { },
+	points = 5,
+	getChance = function(self, t)
+		return 50 --10 + self:getMag() * 0.25 + self:getTalentLevel(t) * 2
+	end,
+	info = function(self, t)
+		local chance = t.getChance(self, t)
+		return ([[When a shadow is hit and killed, there is a %d%% chance it will reform unhurt."
+		The chance will increase with the Magic stat]]):format(chance)
+	end,
+}
+
 local function createShadow(self, level, duration, target)
 	return require("mod.class.NPC").new{
 		type = "undead", subtype = "shadow",
@@ -105,8 +181,8 @@ local function createShadow(self, level, duration, target)
 		stats = {
 			str=10 + math.floor(level * 0.2),
 			dex=15 + math.floor(level * 0.8),
-			mag=15 + math.floor(level * 0.5),
-			wil=10 + math.floor(level * 0.4),
+			mag=15 + math.floor(level * 0.6),
+			wil=10 + math.floor(level * 0.6),
 			cun=10 + math.floor(level * 0.2),
 			con=5,
 		},
@@ -119,12 +195,15 @@ local function createShadow(self, level, duration, target)
 		},
 		evasion = 30,
 		mana = 100,
+		summoner_hate_per_kill = 0.8,
 		resolvers.talents{
 			[self.T_SHADOW_PHASE_DOOR]=math.max(5, math.floor(1 + level * 0.1)),
 			[self.T_SHADOW_BLINDSIDE]=math.max(5, math.floor(1 + level * 0.1)),
-			[self.T_LIGHTNING]=math.max(5, math.floor(1 + level * 0.1)),
-			[self.T_SHOCK]=math.max(5, math.floor(1 + level * 0.1)),
+			[self.T_SHADOW_LIGHTNING]=math.max(5, math.floor(1 + level * 0.1)),
+			[self.T_SHADOW_FLAMES]=math.max(5, math.floor(1 + level * 0.1)),
+			[self.T_SHADOW_REFORM]=math.max(5, math.floor(1 + level * 0.1)),
 			[self.T_HEAL]=math.max(5, math.floor(1 + level * 0.1)),
+			[self.T_DOMINATE]=math.max(5, math.floor(1 + level * 0.1)),
 		},
 
 		undead = 1,
@@ -153,7 +232,10 @@ local function createShadow(self, level, duration, target)
 
 			blindside_chance = 15,
 			phasedoor_chance = 5,
-			attack_spell_chance = 5,
+			close_attack_spell_chance = 0,
+			far_attack_spell_chance = 0,
+			can_reform = false,
+			dominate_chance = 0,
 
 			feed_level = 0
 		},
@@ -166,46 +248,40 @@ local function createShadow(self, level, duration, target)
 		healSelf = function(self)
 			self:useTalent(self.T_HEAL)
 		end,
-		canAttackSpell = function(self)
-			local target = self.ai_target.actor
-			return target and math.floor(core.fov.distance(self.x, self.y, target.x, target.y)) <= 1
+		closeAttackSpell = function(self)
+			return self:useTalent(self.T_SHADOW_LIGHTNING)
 		end,
-		attackSpell = function(self)
-			if self:canAttackSpell() then
-				local choice = rng.range(1, 2)
-				if choice == 1 then
-					return self:useTalent(self.T_LIGHTNING)
-				else
-					return self:useTalent(self.T_SHOCK)
-				end
+		farAttackSpell = function(self)
+			return self:useTalent(self.T_SHADOW_FLAMES)
+		end,
+		dominate = function(self)
+			return self:useTalent(self.T_DOMINATE)
+		end,
+		feed = function(self)
+			if self.summoner:knowTalent(self.summoner.T_SHADOW_MAGES) then
+				local tShadowMages = self.summoner:getTalentFromId(self.summoner.T_SHADOW_MAGES)
+				self.ai_state.close_attack_spell_chance = tShadowMages.getCloseAttackSpellChance(self.summoner, tShadowMages)
+				self.ai_state.far_attack_spell_chance = tShadowMages.getFarAttackSpellChance(self.summoner, tShadowMages)
+				self.ai_state.can_reform = self.summoner:getTalentLevel(tShadowMages) >= 5
 			else
-				return false
+				self.ai_state.close_attack_spell_chance = 0
+				self.ai_state.far_attack_spell_chance = 0
+				self.ai_state.can_reform = false
 			end
-		end,
-		feed = function(self, t)
-			local level = self.summoner:getTalentLevel(t)
-			if self.ai_state.feed_level == level then return end
 
-			self.ai_state.feed_level = level
-
-			-- clear old values
 			if self.ai_state.feed_temp1 then self:removeTemporaryValue("combat_atk", self.ai_state.feed_temp1) end
 			self.ai_state.feed_temp1 = nil
 			if self.ai_state.feed_temp2 then self:removeTemporaryValue("inc_damage", self.ai_state.feed_temp2) end
 			self.ai_state.feed_temp2 = nil
-			self.summoner_hate_per_kill = nil
-
-			if level and level > 0 then
-				-- set new values
-				self.ai_state.feed_temp1 = self:addTemporaryValue("combat_atk", t.getCombatAtk(self.summoner, t))
-				self.ai_state.feed_temp2 = self:addTemporaryValue("inc_damage", {all=t.getIncDamage(self.summoner, t)})
-				self.summoner_hate_per_kill = t.getHatePerKill(self.summoner, t)
+			if self.summoner:knowTalent(self.summoner.T_SHADOW_WARRIORS) then
+				local tShadowWarriors = self.summoner:getTalentFromId(self.summoner.T_SHADOW_WARRIORS)
+				self.ai_state.feed_temp1 = self:addTemporaryValue("combat_atk", tShadowWarriors.getCombatAtk(self.summoner, tShadowWarriors))
+				self.ai_state.feed_temp2 = self:addTemporaryValue("inc_damage", {all=tShadowWarriors.getIncDamage(self.summoner, tShadowWarriors)})
+				self.ai_state.dominate_chance = tShadowWarriors.getDominateChance(self.summoner, tShadowWarriors)
+			else
+				self.ai_state.dominate_chance = 0
 			end
 		end,
-		shadowWall = function(self, t, duration)
-			self.ai_state.shadow_wall = true
-			self.ai_state.shadow_wall_time = duration
-		end,
 	}
 end
 
@@ -279,6 +355,7 @@ newTalent{
 		shadow:resolve(nil, true)
 		shadow:forceLevelup(level)
 		game.zone:addEntity(game.level, shadow, "actor", x, y)
+		shadow:feed()
 		game.level.map:particleEmitter(x, y, 1, "teleport_in")
 
 		game:playSoundNear(self, "talents/spell_generic")
@@ -294,7 +371,7 @@ newTalent{
 	info = function(self, t)
 		local maxShadows = t.getMaxShadows(self, t)
 		local level = t.getLevel(self, t)
-		return ([[While this ability is active you will continually call up to %d level %d shadows to aid you in battle. Each shadow costs 1 hate to summon and will be equal in level to you when it appears.]]):format(maxShadows, level)
+		return ([[While this ability is active you will continually call up to %d level %d shadows to aid you in battle. Shadows are weak combatants that can Heal themselves, Blindside their opponents and Phase Door from place to place. Each shadow costs 1 hate to summon and will be equal in level to you when it appears.]]):format(maxShadows, level)
 	end,
 }
 
@@ -305,71 +382,98 @@ newTalent{
 	points = 5,
 	random_ego = "attack",
 	cooldown = 10,
-	hate = 1,
+	hate = 0.5,
 	range = 6,
 	requires_target = true,
 	tactical = { ATTACK = 2 },
-	getDuration = function(self, t)
-		return self:getTalentLevel(t)
+	getDefenseDuration = function(self, t)
+		return 3 + math.floor(self:getTalentLevel(t) * 1.5)
 	end,
 	getBlindsideChance = function(self, t)
 		return math.min(100, 30 + self:getTalentLevel(t) * 10)
 	end,
-	getAttackSpellChance = function(self, t)
-		return math.min(100, 5 + self:getTalentLevel(t) * 5)
-	end,
 	action = function(self, t)
-		local target = { type="hit", range=self:getTalentRange(t) }
+		local range = self:getTalentRange(t)
+		local target = { type="hit", range=range, nowarning=true }
 		local x, y, target = self:getTarget(target)
-		if not x or not y or not target then return nil end
-
-		local blindsideChance = t.getBlindsideChance(self, t)
-		local attackSpellChance = t.getAttackSpellChance(self, t)
-		local shadowCount = 0
-		for _, e in pairs(game.level.entities) do
-			if e.summoner and e.summoner == self and e.subtype == "shadow" then
-				-- reset target and set to focus
-				e.ai_target.x = nil
-				e.ai_target.y = nil
-				e.ai_target.actor = target
-				e.ai_target.focus_on_target = true
-				e.ai_target.blindside_chance = blindsideChance
-				e.ai_target.attack_spell_chance = attackSpellChance
-
-				shadowCount = shadowCount + 1
+		if not x or not y or not target or core.fov.distance(self.x, self.y, x, y) > range then return nil end
+		
+		if self:reactionToward(target) < 0 then
+			-- attack the target
+			local blindsideChance = t.getBlindsideChance(self, t)
+			local shadowCount = 0
+			for _, e in pairs(game.level.entities) do
+				if e.summoner and e.summoner == self and e.subtype == "shadow" then
+					-- reset target and set to focus
+					e.ai_target.x = nil
+					e.ai_target.y = nil
+					e.ai_target.actor = target
+					e.ai_target.focus_on_target = true
+					e.ai_target.blindside_chance = blindsideChance
+
+					shadowCount = shadowCount + 1
+				end
 			end
-		end
 
-		if shadowCount > 0 then
-			game.logPlayer(self, "#PINK#The shadows converge on %s!", target.name)
-			return true
+			if shadowCount > 0 then
+				game.logPlayer(self, "#PINK#The shadows converge on %s!", target.name)
+				return true
+			else
+				game.logPlayer(self, "Their are no shadows to heed the call!")
+				return false
+			end
 		else
-			game.logPlayer(self, "Their are no shadows to heed the call!")
-			return false
+			-- defend the target
+			local defenseDuration = t.getDefenseDuration(self, t)
+			local shadowCount = 0
+			for _, e in pairs(game.level.entities) do
+				if e.summoner and e.summoner == self and e.subtype == "shadow" then
+					e.ai_state.shadow_wall = true
+					e.ai_state.shadow_wall_target = target
+					e.ai_state.shadow_wall_time = defenseDuration
+
+					shadowCount = shadowCount + 1
+				end
+			end
+
+			if shadowCount > 0 then
+				game.logPlayer(self, "#PINK#The shadows form around %s!", target.name)
+				return true
+			else
+				game.logPlayer(self, "Their are no shadows to heed the call!")
+				return false
+			end
 		end
 	end,
 	info = function(self, t)
-		local duration = t.getDuration(self, t)
+		local defenseDuration = t.getDefenseDuration(self, t)
 		local blindsideChance = t.getBlindsideChance(self, t)
-		local attackSpellChance = t.getAttackSpellChance(self, t)
-		return ([[Focus your shadows on a single target. There is a %d%% chance they will blindside the target and a %d%% chance they will use an attack spell.]]):format(blindsideChance, attackSpellChance)
+		return ([[Focus your shadows on a single target. Friendly targets will be defended for %d turns. Hostile targets will be attacked with a %d%% chance they will blindside the target.]]):format(defenseDuration, blindsideChance)
 	end,
 }
 
 newTalent{
-	name = "Feed Shadows",
+	name = "Shadow Mages",
 	type = {"cursed/shadows", 3},
 	mode = "passive",
 	require = cursed_mag_req3,
 	points = 5,
-	getIncDamage = function(self, t)
-		return math.floor((math.sqrt(self:getTalentLevel(t)) - 0.5) * 17)
+	getCloseAttackSpellChance = function(self, t)
+		if self:getTalentLevelRaw(t) > 0 then
+			return math.min(100, math.sqrt(self:getTalentLevel(t)) * 5)
+		else
+			return 0
+		end
 	end,
-	getCombatAtk = function(self, t)
-		return math.floor((math.sqrt(self:getTalentLevel(t)) - 0.5) * 17)
+	getFarAttackSpellChance = function(self, t)
+		if self:getTalentLevelRaw(t) >= 3 then
+			return math.min(100, math.sqrt(self:getTalentLevel(t)) * 5)
+		else
+			return 0
+		end
 	end,
-	getHatePerKill = function(self, t)
-		return (self:getTalentLevel(t) / 8) * self.hate_per_kill
+	canReform = function(self, t)
+		return self:getTalentLevelRaw(t) >= 5
 	end,
 	on_learn = function(self, t)
 		if game and game.level and game.level.entities then
@@ -394,46 +498,73 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		local combatAtk = t.getCombatAtk(self, t)
-		local incDamage = t.getIncDamage(self, t)
-		local hatePerKill = t.getHatePerKill(self, t)
-		return ([[Your hatred of all living things begins to feed your shadows. Their new viciousness gives them %d%% extra attack and %d%% extra damage and each kill they make transfers %0.2f hatred back to you.]]):format(combatAtk, incDamage, hatePerKill)
+		local closeAttackSpellChance = t.getCloseAttackSpellChance(self, t)
+		local farAttackSpellChance = t.getFarAttackSpellChance(self, t)
+		
+		local level = self:getTalentLevelRaw(t)
+		if level < 3 then
+			return ([[Infuse magic into your shadows to give them fearsome spells.
+			Your shadows can strike adjacent foes with Lightning (%d%% chance at range 1).
+			At 3 talent points they will gain Flames and at 5 talent points they will gain Reform.]]):format(closeAttackSpellChance)
+		elseif level < 5 then
+			return ([[Infuse magic into your shadows to give them fearsome spells.
+			Your shadows can strike adjacent foes with Lightning (%d%% chance at range 1).
+			Your shadows can sear their enemies from a distance with Flames (%d%% chance at range 2 to 6).
+			At 5 talent points they will gain Reform.]]):format(closeAttackSpellChance, farAttackSpellChance)
+		else
+			return ([[Infuse magic into your shadows to give them fearsome spells.
+			Your shadows can strike adjacent foes with Lightning (%d%% chance at range 1).
+			Your shadows can sear their enemies from a distance with Flames (%d%% chance at range 2 to 6).
+			When your shadows are struck down they will attempt to Reform becoming whole again.]]):format(closeAttackSpellChance, farAttackSpellChance)
+		end
 	end,
 }
 
 newTalent{
-	name = "Shadow Wall",
+	name = "Shadow Warriors",
 	type = {"cursed/shadows", 4},
+	mode = "passive",
 	require = cursed_mag_req4,
 	points = 5,
-	cooldown = 10,
-	hate = 1,
-	tactical = { DEFEND = 2 },
-	getDuration = function(self, t)
-		return 2 + self:getTalentLevel(t) * 2
+	getIncDamage = function(self, t)
+		return math.floor((math.sqrt(self:getTalentLevel(t)) - 0.5) * 23)
 	end,
-	action = function(self, t)
-
-		local duration = t.getDuration(self, t)
-		local shadowCount = 0
-		for _, e in pairs(game.level.entities) do
-			if e.summoner and e.summoner == self and e.subtype == "shadow" then
-				e:shadowWall(t, duration)
-
-				shadowCount = shadowCount + 1
+	getCombatAtk = function(self, t)
+		return math.floor((math.sqrt(self:getTalentLevel(t)) - 0.5) * 23)
+	end,
+	getDominateChance = function(self, t)
+		if self:getTalentLevelRaw(t) > 0 then
+			return math.min(100, math.sqrt(self:getTalentLevel(t)) * 5)
+		else
+			return 0
+		end
+	end,
+	on_learn = function(self, t)
+		if game and game.level and game.level.entities then
+			for _, e in pairs(game.level.entities) do
+				if e.summoner and e.summoner == self and e.subtype == "shadow" then
+					e:feed(t)
+				end
 			end
 		end
-
-		if shadowCount > 0 then
-			game.logPlayer(self, "#PINK#The shadows form around %s!", self.name)
-			return true
-		else
-			game.logPlayer(self, "Their are no shadows to heed the call!")
-			return false
+		
+		return { }
+	end,
+	on_unlearn = function(self, t, p)
+		if game and game.level and game.level.entities then
+			for _, e in pairs(game.level.entities) do
+				if e.summoner and e.summoner == self and e.subtype == "shadow" then
+					e:feed(t)
+				end
+			end
 		end
+
+		return true
 	end,
 	info = function(self, t)
-		local duration = t.getDuration(self, t)
-		return ([[Summon your shadows to your side to form a wall against danger. Your shadows will stay beside you for %d turns and attack anyone nearby.]]):format(duration)
+		local combatAtk = t.getCombatAtk(self, t)
+		local incDamage = t.getIncDamage(self, t)
+		local dominateChance = t.getDominateChance(self, t)
+		return ([[Instill hate in your shadows strengthening their attacks. They gain %d%% extra attack and %d%% extra damage. The fury of their attacks gives them the ability to try to Dominate their foes, increasing all damage taken by that foe for 4 turns. (%d%% chance at range 1)]]):format(combatAtk, incDamage, dominateChance)
 	end,
 }
diff --git a/game/modules/tome/data/talents/cursed/slaughter.lua b/game/modules/tome/data/talents/cursed/slaughter.lua
index a6e338758e9a72215d06b4371923caebe413ef96..88dac4a048ec09c704c7ec0026eeb744036b8af3 100644
--- a/game/modules/tome/data/talents/cursed/slaughter.lua
+++ b/game/modules/tome/data/talents/cursed/slaughter.lua
@@ -50,7 +50,8 @@ newTalent{
 	end,
 	info = function(self, t)
 		local multiplier = (0.17 + .23 * self:getTalentLevel(t))
-		return ([[Slashes wildly at your target for 100%% (at 0 Hate) to %d%% (at 10+ Hate) damage.]]):format(multiplier * 100 + 100)
+		return ([[Slashes wildly at your target for 100%% (at 0 Hate) to %d%% (at 10+ Hate) damage.
+		Requires a one or two handed axe.]]):format(multiplier * 100 + 100)
 	end,
 }
 
@@ -96,7 +97,8 @@ newTalent{
 	end,
 	info = function(self, t)
 		local multiplier = self:combatTalentWeaponDamage(t, 0.2, 0.7)
-		return ([[Assault nearby foes with 4 fast attacks for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage each.]]):format(multiplier * 50, multiplier * 100)
+		return ([[Assault nearby foes with 4 fast attacks for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage each.
+		Requires a one or two handed axe.]]):format(multiplier * 50, multiplier * 100)
 	end,
 }
 
@@ -201,7 +203,8 @@ newTalent{
 		else
 			size = "Small"
 		end
-		return ([[Charge through your opponents, attacking anyone near your path for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage. %s opponents may be knocked from your path.]]):format(multiplier * 30, multiplier * 100, size)
+		return ([[Charge through your opponents, attacking anyone near your path for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage. %s opponents may be knocked from your path.
+		Requires a one or two handed axe.]]):format(multiplier * 30, multiplier * 100, size)
 	end,
 }
 
@@ -242,6 +245,7 @@ newTalent{
 	info = function(self, t)
 		local chance = 28 + self:getTalentLevel(t) * 7
 		local multiplier = self:combatTalentWeaponDamage(t, 0.2, 0.7)
-		return ([[Every swing of your axe has a %d%% chance of striking a second target for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage.]]):format(chance, multiplier * 50, multiplier * 100)
+		return ([[Every swing of your axe has a %d%% chance of striking a second target for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage.
+		Requires a one or two handed axe.]]):format(chance, multiplier * 50, multiplier * 100)
 	end,
 }
diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua
index 9d5b8add06a15e5c221e6bba2abe3399981a5c2d..a53c522062a1c503e3eff64c15a2ea76768264b3 100644
--- a/game/modules/tome/data/timed_effects.lua
+++ b/game/modules/tome/data/timed_effects.lua
@@ -2507,9 +2507,25 @@ newEffect{
 			if eff.extension <= 0 then
 				self:removeEffect(self.EFF_FEED)
 			end
-		elseif eff.target.dead or not self:hasLOS(eff.target.x, eff.target.y, "block_move") then
+			return
+		end
+		
+		if eff.target.dead then
 			eff.isSevered = true
-
+		else
+			local t = self:getTalentFromId(self.T_DARK_VISION)
+			if t then
+				if not t.hasLOS(self.x, self.y, eff.target.x, eff.target.y) then
+					eff.isSevered = true
+				end
+			else
+				if not self:hasLOS(eff.target.x, eff.target.y) then
+					eff.isSevered = true
+				end
+			end
+		end
+		
+		if eff.isSevered then
 			if eff.particles then
 				-- remove old particle emitter
 				eff.particles.x = nil