diff --git a/game/modules/tome/ai/shadow.lua b/game/modules/tome/ai/shadow.lua
index 445f8d05541c5f021bfee7231e2f50e24ebbc63a..cb1167bf190cf04a8e5c6da7f4e1bc7e72e243fb 100644
--- a/game/modules/tome/ai/shadow.lua
+++ b/game/modules/tome/ai/shadow.lua
@@ -19,6 +19,10 @@
 
 local Astar = require "engine.Astar"
 
+local function clearTarget(self)
+	self.ai_target.actor, self.ai_target.x, self.ai_target.y, self.ai_target.blindside_chance, self.ai_target.attack_spell_chance, self.turns_on_target, self.focus_on_target = nil, nil, nil, nil, nil, 0, false
+end
+
 local function shadowChooseActorTarget(self)
 	
 	-- taken from "target_simple" but selects a target the summoner can see within the shadow's max range from the summoner
@@ -29,7 +33,7 @@ local function shadowChooseActorTarget(self)
 	local actors = {}
 	for i = 1, #arr do
 		act = self.summoner.fov.actors_dist[i]
-		if act and self.summoner:reactionToward(act) < 0 and not act.dead and
+		if act and act ~= self.summoner and self.summoner:reactionToward(act) < 0 and not act.dead and
 			(
 				-- If it has lite we can always see it
 				(act.lite > 0)
@@ -71,9 +75,18 @@ local function shadowMoveToActorTarget(self)
 			end
 		end
 	end
-		
-	-- reset target next turn if we are attacking (unless we have been focused)
-	if core.fov.distance(self.x, self.y, self.ai_target.actor.x, self.ai_target.actor.y) <= 1 then
+	
+	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
 		--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
@@ -182,7 +195,7 @@ newAI("shadow", function(self)
 	
 	-- shadow wall
 	if self.ai_state.shadow_wall then
-		self.ai_target.actor, self.ai_target.x, self.ai_target.y, self.turns_on_target, self.focus_on_target = nil, nil, nil, 0, false
+		clearTarget(self)
 	
 		if self.ai_state.shadow_wall_time <= 0 then
 			self.ai_state.shadow_wall = false
@@ -227,7 +240,7 @@ newAI("shadow", function(self)
 	if core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.ai_state.summoner_range then
 		--game.logPlayer(self.summoner, "#PINK#%s is out of range.", self.name:capitalize())
 		
-		self.ai_target.actor, self.ai_target.x, self.ai_target.y, self.turns_on_target, self.focus_on_target = nil, nil, nil, 0, false
+		clearTarget(self)
 		
 		-- phase door into range
 		self:useTalent(self.T_SHADOW_PHASE_DOOR)
@@ -239,7 +252,13 @@ newAI("shadow", function(self)
 	if (self.turns_on_target or 0) >= 10 then
 		--game.logPlayer(self.summoner, "#PINK#%s is out of time for target.", self.name:capitalize())
 		
-		self.ai_target.actor, self.ai_target.x, self.ai_target.y, self.turns_on_target, self.focus_on_target = nil, nil, nil, 0, false
+		clearTarget(self)
+	end
+	
+	-- chance to heal
+	if self.life < self.max_life * 0.75 and rng.percent(5) then
+		self:healSelf()
+		return true
 	end
 	
 	-- move to live target?
@@ -256,13 +275,14 @@ newAI("shadow", function(self)
 		end
 	end
 	
-	-- no current target..choose a new one
-	self.ai_target.actor, self.ai_target.x, self.ai_target.y, self.turns_on_target, self.focus_on_target = nil, nil, nil, 0, false
+	-- no current target..start a new action
+	clearTarget(self)
 	
-	-- choose an actor target?
-	if rng.percent(50) and shadowChooseActorTarget(self) then
+	-- choose an actor target? this determines their aggressiveness
+	if rng.percent(65) and shadowChooseActorTarget(self) then
 		--game.logPlayer(self.summoner, "#PINK#%s choose an actor.", self.name:capitalize())
 		
+		-- start moving to the target
 		if shadowMoveToActorTarget(self) then
 			return true
 		end
diff --git a/game/modules/tome/data/talents/cursed/cursed-form.lua b/game/modules/tome/data/talents/cursed/cursed-form.lua
index d0a1eb075bd6644c0c8e0704cbc6cd19abf12bc6..9e43dcfdd8302693f38214c8d6e005b8f9e1926f 100644
--- a/game/modules/tome/data/talents/cursed/cursed-form.lua
+++ b/game/modules/tome/data/talents/cursed/cursed-form.lua
@@ -70,7 +70,11 @@ newTalent{
 		local healPerKill = t.getHealPerKill(self, t)
 		local regenRate = t.getRegenRate(self, t)
 		local resist = -18 + (self:getTalentLevel(t) * 3)
-		return ([[Your body is now fed by your hatred. With each kill, you regenerate %d%% of your victim's life at a rate of %0.1f life per turn. As your hate fades and grows the damage you sustain is adjusted by %d%% to %d%%.]]):format(healPerKill, regenRate, resist, resist + 18)
+		
+		local modifier1, modifier2 = "more", "more"
+		if resist > 0 then modifier1 = "less" end
+		if resist + 18 > 0 then modifier2 = "less" end
+		return ([[Your body's strength is fed by your hatred. With each kill you regenerate %d%% of your victim's life at a rate of %0.1f life per turn. You also take %d%% %s damage (at 0 Hate) to %d%% %s damage (at 10+ Hate).]]):format(healPerKill, regenRate, math.abs(resist), modifier1, math.abs(resist + 18), modifier2)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/cursed/darkness.lua b/game/modules/tome/data/talents/cursed/darkness.lua
index 55326ffbfda74ced9ea1ae6a9fab2729b0b7416e..5ea068cd7946849232dc70df96505ca1c0085b11 100644
--- a/game/modules/tome/data/talents/cursed/darkness.lua
+++ b/game/modules/tome/data/talents/cursed/darkness.lua
@@ -22,7 +22,7 @@ local Map = require "engine.Map"
 local canCreep, doCreep, createDark
 
 local function combatTalentDamage(self, t, min, max)
-	return self:combatTalentSpellDamage(t, min, max, self.combat_spellpower + self:getMag())
+	return self:combatTalentSpellDamage(t, min, max, self.level + self:getMag())
 end
 
 function canCreep(x, y, ignoreCreepingDark)
@@ -84,7 +84,7 @@ function createDark(summoner, x, y, damage, duration, creep, creepChance, initia
 
 			-- apply damage to anything inside the darkness
 			local actor = game.level.map(self.x, self.y, Map.ACTOR)
-			if actor and actor ~= self.summoner then
+			if actor and actor ~= self.summoner and (not actor.summoner or actor.summoner ~= self.summoner) then
 				self.summoner:project(actor, actor.x, actor.y, engine.DamageType.DARKNESS, damage)
 				--DamageType:get(DamageType.DARKNESS).projector(self.summoner, actor.x, actor.y, DamageType.DARKNESS, damage)
 			end
@@ -267,10 +267,10 @@ newTalent{
 		return 3
 	end,
 	getDarkCount = function(self, t)
-		return 3 + math.floor(self:getTalentLevel(t) * 1.8)
+		return 2 + math.floor(self:getTalentLevel(t))
 	end,
 	getDamage = function(self, t)
-		return combatTalentDamage(self, t, 25, 70)
+		return combatTalentDamage(self, t, 15, 50)
 	end,
 	action = function(self, t)
 		local range = self:getTalentRange(t)
@@ -300,7 +300,7 @@ newTalent{
 			local selection = rng.range(i, #locations)
 			locations[i], locations[selection] = locations[selection], locations[i]
 
-			createDark(self, locations[i][1], locations[i][2], damage, 8, 2 + self:getMag(6), 70, 0)
+			createDark(self, locations[i][1], locations[i][2], damage, 8, 4, 70, 0)
 		end
 
 		game:playSoundNear(self, "talents/breath")
@@ -311,7 +311,7 @@ newTalent{
 		local damage = t.getDamage(self, t)
 		local darkCount = t.getDarkCount(self, t)
 		return ([[Creeping dark spreads from %d spots in a radius of %d around the targeted location. The dark deals %d damage.
-		Damage improves with the Magic stat and spellpower.]]):format(darkCount, radius, damage)
+		Damage improves with the Magic stat.]]):format(darkCount, radius, damage)
 	end,
 }
 
@@ -389,7 +389,7 @@ newTalent{
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
 		return ([[Sends a torrent of searing darkness through your foes doing %d damage with a chance to blind them for 3 turns.
-		The damage will increase with the Magic stat and spellpower.]]):format(damDesc(self, DamageType.DARKNESS, damage))
+		The damage will increase with the Magic stat.]]):format(damDesc(self, DamageType.DARKNESS, damage))
 	end,
 }
 
@@ -426,6 +426,6 @@ newTalent{
 		local pinDuration = t.getPinDuration(self, t)
 		local damage = t.getDamage(self, t)
 		return ([[Send tendrils of creeping dark out to attack your target and pin them for %d turns. The darkness does %d damage per turn.
-		The damage will increase with the Magic stat and spellpower.]]):format(pinDuration, damage)
+		The damage will increase with the Magic stat.]]):format(pinDuration, damage)
 	end,
 }
diff --git a/game/modules/tome/data/talents/cursed/endless-hunt.lua b/game/modules/tome/data/talents/cursed/endless-hunt.lua
index 07b91117a7c5e7d71090b685113e0aaf87fa8976..f5b9993648220083317f466b42cd4a6ec84f7b41 100644
--- a/game/modules/tome/data/talents/cursed/endless-hunt.lua
+++ b/game/modules/tome/data/talents/cursed/endless-hunt.lua
@@ -69,7 +69,7 @@ newTalent{
 	end,
 	info = function(self, t)
 		local damMult = 1 + self:combatTalentWeaponDamage(t, 0.1, 0.5)
-		return ([[Combine strength and will to overpower your opponent with a vicious attack. A failed save versus willpower will multiply all melee damage by %d%% for 4 turns.]]):format(damMult * 100)
+		return ([[Combine strength and will to overpower your opponent with a vicious attack. If your opponent fails to save versus willpower then all of your melee hits will do %d%% damage against them for for 4 turns.]]):format(damMult * 100)
 	end,
 }
 
@@ -84,7 +84,7 @@ newTalent{
 	end,
 	info = function(self, t)
 		local maxRange = 2 + math.floor(self:getTalentLevel(t) * 1.5)
-		return ([[Your preternatural senses aid you in your hunt for the next victim. You sense foes in a hate-based radius of %d to %d.]]):format(2, maxRange)
+		return ([[Your preternatural senses aid you in your hunt for the next victim. You sense foes in a radius of %d (at 0 Hate) to %d (at 10+ Hate).]]):format(2, maxRange)
 	end,
 }
 
@@ -123,7 +123,7 @@ newTalent{
 	end,
 	info = function(self, t)
 		local multiplier = self:combatTalentWeaponDamage(t, 0.7, 1.9)
-		return ([[With blinding speed you suddenly appear next to a target up to %d spaces away and attack for %d%% to %d%% hate-based damage.]]):format(self:getTalentRange(t), multiplier * 30, multiplier * 100)
+		return ([[With blinding speed you suddenly appear next to a target up to %d spaces away and attack for %d%% (at 0 Hate) to %d%% (at 10+ Hate) damage.]]):format(self:getTalentRange(t), multiplier * 30, multiplier * 100)
 	end,
 }
 
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 1880c80fb3a640bab06638e50e474b3353692e39..3422bb75412763393a69ccab11e3a1fb7e01afbf 100644
--- a/game/modules/tome/data/talents/cursed/force-of-will.lua
+++ b/game/modules/tome/data/talents/cursed/force-of-will.lua
@@ -17,8 +17,9 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
+
 local function combatTalentDamage(self, t, min, max)
-	return self:combatTalentSpellDamage(t, min, max, self.combat_spellpower + self:getWil())
+	return self:combatTalentSpellDamage(t, min, max, self.level + self:getWil())
 end
 
 -- damage: initial physical damage and used for fractional knockback damage
@@ -129,7 +130,7 @@ newTalent{
 		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.
-		Damage increases with the Willpower stat and spellpower but decreases with range.]]):format(damDesc(self, DamageType.PHYSICAL, damage), knockback)
+		Damage increases with the Willpower stat but decreases with range.]]):format(damDesc(self, DamageType.PHYSICAL, damage), knockback)
 	end,
 }
 
@@ -195,7 +196,7 @@ newTalent{
 	info = function(self, t)
 		local maxDamage = t.getMaxDamage(self, t)
 		return ([[Deflect 50%% of incoming damage with the force of your will. You may deflect up to %d damage but first your hate must slowly feed your strength.
-		The maximum damage deflected increases with the Willpower stat and spellpower.]]):format(maxDamage)
+		The maximum damage deflected increases with the Willpower stat.]]):format(maxDamage)
 	end,
 }
 
@@ -208,10 +209,10 @@ newTalent{
 	cooldown = 10,
 	hate = 1.5,
 	range = function(self, t)
-		return math.floor(8 + self:getTalentLevel(t))
+		return 6
 	end,
 	getRadius = function(self, t)
-		return math.floor(2 + self:getTalentLevel(t) / 2)
+		return math.floor(2 + self:getTalentLevel(t) / 3)
 	end,
 	getDamage = function(self, t)
 		return combatTalentDamage(self, t, 20, 160)
@@ -253,7 +254,7 @@ newTalent{
 		local damage = t.getDamage(self, t)
 		local knockback = t.getKnockback(self, t)
 		return ([[You rage coalesces at a single point and then explodes outward blasting enemies within a radius of %d in all directions. The blast causes %d damage and %d knockback at the center that decreases with distance.
-		Damage increases with the Willpower stat and spellpower.]]):format(radius, damDesc(self, DamageType.PHYSICAL, damage), knockback)
+		Damage increases with the Willpower stat.]]):format(radius, damDesc(self, DamageType.PHYSICAL, damage), knockback)
 	end,
 }
 
@@ -269,7 +270,7 @@ newTalent{
 	},
 	direct_hit = true,
 	range = function(self, t)
-		return math.floor(5 + self:getTalentLevel(t))
+		return math.floor(4 + self:getTalentLevel(t) / 2)
 	end,
 	getDuration = function(self, t)
 		return 5 + math.floor(self:getTalentLevel(t))
@@ -334,10 +335,10 @@ newTalent{
 		local secondHitChance = t.getSecondHitChance(self, t)
 		if secondHitChance > 0 then
 			return ([[Your fury becomes an unseen force that randomly lashes out at the foes around you. For %d turns you strike one nearby target doing %d damage and %d knockback. There is a %d%% chance of a second strike.
-			Damage increases with the Willpower stat and spellpower.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage), knockback, secondHitChance)
+			Damage increases with the Willpower stat.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage), knockback, secondHitChance)
 		else
 			return ([[Your fury becomes an unseen force that randomly lashes out at the foes around you. For %d turns you strike one nearby target doing %d damage and %d knockback. At higher levels there is a chance of a second strike.
-			Damage increases with the Willpower stat and spellpower.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage), knockback, secondHitChance)
+			Damage increases with the Willpower stat.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage), knockback, secondHitChance)
 		end
 	end,
 }
diff --git a/game/modules/tome/data/talents/cursed/gloom.lua b/game/modules/tome/data/talents/cursed/gloom.lua
index c3032d033d92d5f3b0872f481b9aa1f5590049bd..66e7c1a7e6efe3ca300a05d76fe524409ef87afb 100644
--- a/game/modules/tome/data/talents/cursed/gloom.lua
+++ b/game/modules/tome/data/talents/cursed/gloom.lua
@@ -219,7 +219,7 @@ newTalent{
 		local baseDamage = 30 + self:getWil() * 0.4 * self:getTalentLevel(t)
 		local attackStrength = 0.3 + self:getTalentLevel(t) * 0.12
 		local effectiveness = getWillFailureEffectiveness(self, 30, 95, attackStrength)
-		return ([[Your rage builds within you for 20 turns, then unleashes itself for %d to %d hate-based darkness damage on the first one to enter your gloom. (%d effectiveness)]]):format(baseDamage * .5, baseDamage * 1.5, effectiveness)
+		return ([[Your rage builds within you for 20 turns, then unleashes itself for %d (at 0 Hate) to %d (at 10+ Hate) darkness damage on the first one to enter your gloom. (%d effectiveness)]]):format(baseDamage * .5, baseDamage * 1.5, effectiveness)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/cursed/punishments.lua b/game/modules/tome/data/talents/cursed/punishments.lua
index 42c2ef494f4f3e780b8f444a1539e017449744f4..2721579f8eaabe5d1d72ca23531eb997c92e9239 100644
--- a/game/modules/tome/data/talents/cursed/punishments.lua
+++ b/game/modules/tome/data/talents/cursed/punishments.lua
@@ -18,7 +18,7 @@
 -- darkgod@te4.org
 
 local function combatTalentDamage(self, t, min, max)
-	return self:combatTalentSpellDamage(t, min, max, self.combat_spellpower + self:getWil())
+	return self:combatTalentSpellDamage(t, min, max, self.level + self:getWil())
 end
 
 newTalent{
@@ -116,7 +116,7 @@ newTalent{
 		local duration = t.getDuration(self, t)
 		local maxTriggerCount = t.getMaxTriggerCount(self, t)
 		return ([[You mark the ground at your feed with a terrible curse. Anyone passing the mark suffers %d mind damage. The mark lasts for %d turns but the will weaken each time it is triggered.
-		The damage will increase with the Willpower stat and spellpower.]]):format(damDesc(self, DamageType.MIND, damage), duration, maxTriggerCount)
+		The damage will increase with the Willpower stat.]]):format(damDesc(self, DamageType.MIND, damage), duration, maxTriggerCount)
 	end,
 }
 
@@ -159,7 +159,7 @@ newTalent{
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
 		return ([[You unleash your hateful mind on any who dare approach you. %d mind damage is spread between everyone in range.
-		The damage will increase with the Willpower stat and spellpower.]]):format(damDesc(self, DamageType.MIND, damage))
+		The damage will increase with the Willpower stat.]]):format(damDesc(self, DamageType.MIND, damage))
 	end,
 }
 
@@ -204,7 +204,7 @@ newTalent{
 		local mindpower = t.getMindpower(self, t)
 		local duration = t.getDuration(self, t)
 		return ([[Unleash agony upon your target. The pain will grow as the near you inflicing up to %d damage. They will suffer for %d turns unless they manage to resist. (+%d%% mindpower)
-		The damage will increase with the Willpower stat and spellpower.]]):format(damDesc(self, DamageType.MIND, damage), duration, mindpower)
+		The damage will increase with the Willpower stat.]]):format(damDesc(self, DamageType.MIND, damage), duration, mindpower)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/cursed/rampage.lua b/game/modules/tome/data/talents/cursed/rampage.lua
index c9b728d56edd8d4d4a506b8721f3ca3e67b73ca7..99609055f9a9ce500256266e28eec64ea67cc1d2 100644
--- a/game/modules/tome/data/talents/cursed/rampage.lua
+++ b/game/modules/tome/data/talents/cursed/rampage.lua
@@ -29,7 +29,7 @@ newTalent{
 	cooldown = function(self, t)
 		local tReflexes = self:getTalentFromId(self.T_REFLEXES)
 		if tReflexes then
-			return t.getCooldown(self, t)
+			return tReflexes.getCooldown(self, tReflexes)
 		else
 			return 150
 		end
@@ -74,11 +74,11 @@ newTalent{
 	end,
 	getHateLoss = function(self, t) return 0.5 - 0.05 * self:getTalentLevelRaw(t) end,
 	getCritical = function(self, t) return 10 + 8 * self:getTalentLevel(t) end,
-	onTakeHit = function(t, self, percentDamage)
-		if percentDamage < 10 then return false end
+	onTakeHit = function(t, self, fractionDamage)
+		if fractionDamage < 0.08 then return false end
 		if self:hasEffect(self.EFF_RAMPAGE) then return false end
-		if rng.percent(1 + self:getTalentLevel(t) * 0.4) then
-			action(self, t, 0)
+		if rng.percent(3) then
+			t.action(self, t, 0)
 			return true
 		end
 	end,
@@ -90,8 +90,8 @@ newTalent{
 		end
 		local hateLoss = t.getHateLoss(self, t)
 		local critical = t.getCritical(self, t)
-		return ([[You enter into a terrible rampage for %d turns, destroying everything in your path. There is a small chance you will rampage when you take significant damage.
-		(%0.2f hate loss per turn, +%d%% to %d%% hate-based critical chance)]]):format(duration, hateLoss, critical * 0.3, critical * 1.0)
+		return ([[You enter into a terrible rampage for %d turns, destroying everything in your path. There is also a small chance when you are hit that you will rampage.
+		%0.2f hate loss per turn. +%d%% (at 0 Hate) to %d%% (at 10+ Hate) critical chance.]]):format(duration, hateLoss, critical * 0.3, critical * 1.0)
 	end,
 }
 
@@ -111,7 +111,7 @@ newTalent{
 		local duration = t.getDuration(self, t)
 		local damage = t.getDamage(self, t)
 		return ([[Add brutality to your rampage.
-		(Rampage lasts %d turns, +%d%% to %d%% hate-based damage)]]):format(duration, damage * 0.1, damage * 1.0)
+		Rampage lasts %d turns. +%d%% (at 0 Hate) to %d%% (at 10+ Hate) damage.]]):format(duration, damage * 0.1, damage * 1.0)
 	end,
 }
 
@@ -131,7 +131,7 @@ newTalent{
 		local cooldown = t.getCooldown(self, t)
 		local speed = t.getSpeed(self, t)
 		return ([[Add reflexes to your rampage.
-		(Rampage cooldown is %d turns, +%d%% to %d%% speed)]]):format(cooldown, speed * 0.1, speed * 1.0)
+		Rampage cooldown is %d turns. +%d%% (at 0 Hate) to %d%% (at 10+ Hate) speed.]]):format(cooldown, speed * 0.1, speed * 1.0)
 	end,
 }
 
@@ -151,6 +151,6 @@ newTalent{
 		local attack = t.getAttack(self, t)
 		local evasion = t.getEvasion(self, t)
 		return ([[Add instincts to your rampage.
-		(+%d%% to %d%% hate-based attack, +%d%% to %d%% hate-based evasion)]]):format(attack * 0.1, attack * 1.0, evasion * 0.1, evasion * 1.0)
+		+%d%% (at 0 Hate) to %d%% (at 10+ Hate) attack. +%d%% (at 0 Hate) to %d%% (at 10+ Hate) evasion.]]):format(attack * 0.1, attack * 1.0, evasion * 0.1, evasion * 1.0)
 	end,
 }
diff --git a/game/modules/tome/data/talents/cursed/shadows.lua b/game/modules/tome/data/talents/cursed/shadows.lua
index dc9ef24072ab3d5da5dad1b804804c014435c6b3..0fcc2dd18f8824755462f754a43a8d30658d584a 100644
--- a/game/modules/tome/data/talents/cursed/shadows.lua
+++ b/game/modules/tome/data/talents/cursed/shadows.lua
@@ -17,7 +17,8 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
-newTalent{ short_name = "SHADOW_PHASE_DOOR",
+newTalent{
+	short_name = "SHADOW_PHASE_DOOR",
 	name = "Phase Door",
 	type = {"spell/other",1},
 	points = 5,
@@ -42,7 +43,8 @@ newTalent{ short_name = "SHADOW_PHASE_DOOR",
 	end,
 }
 
-newTalent{ short_name = "SHADOW_BLINDSIDE",
+newTalent{
+	short_name = "SHADOW_BLINDSIDE",
 	name = "Blindside",
 	type = {"spell/other", 1},
 	points = 5,
@@ -107,15 +109,19 @@ local function createShadow(self, level, duration, target)
 		},
 		combat_armor = 0, combat_def = 3 + level * 0.1,
 		combat = {
-			dam=14 + level * 2,
+			dam=8 + level * 2,
 			atk=10 + 1.5 * level * 2,
 			apr=10,
 			dammod={dex=0.3, mag=0.3}
 		},
-		evasion = 40,
+		evasion = 30,
+		mana = 100,
 		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_HEAL]=math.max(5, math.floor(1 + level * 0.1)),
 		},
 		
 		undead = 1,
@@ -129,7 +135,7 @@ local function createShadow(self, level, duration, target)
 		stun_immune = 1,
 		blind_immune = 1,
 		see_invisible = 80,
-		resists = {[DamageType.LIGHT] = -50, [DamageType.DARKNESS] = 100, [DamageType.PHYSICAL] = 30},
+		resists = {[DamageType.LIGHT] = -100, [DamageType.DARKNESS] = 100},
 		
 		ai = "shadow",
 		ai_state = {
@@ -143,13 +149,33 @@ local function createShadow(self, level, duration, target)
 			shadow_wall_time = 0,
 			
 			blindside_chance = 15,
-			phasedoor_chance = 5
+			phasedoor_chance = 5,
+			attack_spell_chance = 5,
 		},
 		ai_target = {
 			actor=target,
 			x = nil,
 			y = nil
 		},
+		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
+		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
+			else
+				return false
+			end
+		end,
 		feed = function(self, t)
 			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)})
@@ -273,15 +299,18 @@ newTalent{
 		return self:getTalentLevel(t)
 	end,
 	getBlindsideChance = function(self, t)
-		return math.min(100, 15 + self:getTalentLevel(t) * 12)
+		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 x, y, target = self:getTarget(target)
 		if not x or not y or not target then return nil end
 
-		local duration = t.getDuration(self, t)
 		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
@@ -290,8 +319,8 @@ newTalent{
 				e.ai_target.y = nil
 				e.ai_target.actor = target
 				e.ai_target.focus_on_target = true
-				e.ai_target.turns_on_target = duration
 				e.ai_target.blindside_chance = blindsideChance
+				e.ai_target.attack_spell_chance = attackSpellChance
 				
 				shadowCount = shadowCount + 1
 			end
@@ -308,7 +337,8 @@ newTalent{
 	info = function(self, t)
 		local duration = t.getDuration(self, t)
 		local blindsideChance = t.getBlindsideChance(self, t)
-		return ([[Focus your shadows on a single target for %d turns. There is a %d%% chance they will blindside the target.]]):format(duration, blindsideChance)
+		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)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/cursed/slaughter.lua b/game/modules/tome/data/talents/cursed/slaughter.lua
index 475142404b0c6212fe088e809c6a1488818b6186..aea601ff4de8285cd46dfe154690062d21ca359b 100644
--- a/game/modules/tome/data/talents/cursed/slaughter.lua
+++ b/game/modules/tome/data/talents/cursed/slaughter.lua
@@ -49,7 +49,7 @@ newTalent{
 	end,
 	info = function(self, t)
 		local multiplier = (0.17 + .23 * self:getTalentLevel(t))
-		return ([[Slashes wildly at your target adding up to %d%% hate-based damage.]]):format(multiplier * 100)
+		return ([[Slashes wildly at your target for 100%% (at 0 Hate) to %d%% (at 10+ Hate) damage.]]):format(multiplier * 100 + 100)
 	end,
 }
 
@@ -94,7 +94,7 @@ 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%% to %d%% hate-based 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.]]):format(multiplier * 50, multiplier * 100)
 	end,
 }
 
@@ -198,7 +198,7 @@ newTalent{
 		else
 			size = "Small"
 		end
-		return ([[Charge through your opponents, attacking anyone near your path for %d%% to %d%% hate-based 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.]]):format(multiplier * 30, multiplier * 100, size)
 	end,
 }
 
@@ -239,6 +239,6 @@ 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%% to %d%% hate-based 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.]]):format(chance, multiplier * 50, multiplier * 100)
 	end,
 }