diff --git a/game/modules/tome/data/talents/divine/chants.lua b/game/modules/tome/data/talents/divine/chants.lua
index b32bdf1dbd51ef7e984cd2e8dc9806b0fb585f74..fe23a2ef00c7048dfba2c9928885fa4dc72b18c1 100644
--- a/game/modules/tome/data/talents/divine/chants.lua
+++ b/game/modules/tome/data/talents/divine/chants.lua
@@ -40,13 +40,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getResists = function(self, t) return self:combatTalentSpellDamage(t, 5, 70) end,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		cancelChants(self)
-		local power = self:combatTalentSpellDamage(t, 5, 70)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
+		local power = t.getResists(self, t)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=dam}),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=t.getDamageOnMeleeHit(self, t)}),
 			phys = self:addTemporaryValue("combat_physresist", power),
 			spell = self:addTemporaryValue("combat_spellresist", power),
 			particle = self:addParticles(Particles.new("golden_shield", 1))
@@ -61,10 +62,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local saves = t.getResists(self, t)
+		local damageonmeleehit = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the sun, granting you %d physical and spell save.
 		In addition it surrounds you with a shield of light, damaging anything that attacks you for %0.2f light damage.
 		You may only have one Chant active at once.
-		The resistance and damage will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 5, 70), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 5, 25)))
+		The resistance and damage will increase with the Magic stat]]):
+		format(saves, damDesc(self, DamageType.LIGHT, damageonmeleehit))
 	end,
 }
 
@@ -82,14 +86,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getPhysicalResistance = function(self, t) return self:combatTalentSpellDamage(t, 5, 23) end,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		cancelChants(self)
-		local power = self:combatTalentSpellDamage(t, 5, 23)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=dam}),
-			phys = self:addTemporaryValue("resists", {[DamageType.PHYSICAL] = power}),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=t.getDamageOnMeleeHit(self, t)}),
+			phys = self:addTemporaryValue("resists", {[DamageType.PHYSICAL] = t.getPhysicalResistance(self, t)}),
 			particle = self:addParticles(Particles.new("golden_shield", 1))
 		}
 		return ret
@@ -101,10 +105,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local physicalresistance = t.getPhysicalResistance(self, t)
+		local damageonmeleehit = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the sun, granting you %d%% physical damage resistance.
 		In addition it surrounds you with a shield of light, damaging anything that attacks you for %0.2f light damage.
 		You may only have one Chant active at once.
-		The resistance and damage will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 5, 23), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 5, 25)))
+		The resistance and damage will increase with the Magic stat]]):
+		format(physicalresistance, damDesc(self, DamageType.LIGHT, damageonmeleehit))
 	end,
 }
 
@@ -122,13 +129,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getResists = function(self, t) return self:combatTalentSpellDamage(t, 5, 20) end,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		cancelChants(self)
-		local power = self:combatTalentSpellDamage(t, 5, 20)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
+		local power = t.getResists(self, t)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=dam}),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=t.getDamageOnMeleeHit(self, t)}),
 			res = self:addTemporaryValue("resists", {
 				[DamageType.FIRE] = power,
 				[DamageType.LIGHTNING] = power,
@@ -146,10 +154,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local resists = t.getResists(self, t)
+		local damage = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the sun, granting you %d%% elemental resistances.
 		In addition it surrounds you with a shield of light, damaging anything that attacks you for %0.2f light damage.
 		You may only have one Chant active at once.
-		The resistance and damage will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 5, 20), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 5, 25)))
+		The resistance and damage will increase with the Magic stat]]):
+		format(resists, damDesc(self, DamageType.LIGHT, damage))
 	end,
 }
 
@@ -167,14 +178,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getLightDamageIncrease = function(self, t) return self:combatTalentSpellDamage(t, 10, 50) end,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		cancelChants(self)
-		local power = self:combatTalentSpellDamage(t, 10, 50)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=dam}),
-			phys = self:addTemporaryValue("inc_damage", {[DamageType.LIGHT] = power}),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.LIGHT]=t.getDamageOnMeleeHit(self, t)}),
+			phys = self:addTemporaryValue("inc_damage", {[DamageType.LIGHT] = t.getLightDamageIncrease(self, t)}),
 			particle = self:addParticles(Particles.new("golden_shield", 1))
 		}
 		return ret
@@ -186,9 +197,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damageinc = t.getLightDamageIncrease(self, t)
+		local damage = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the sun, granting you %d%% more light damage.
 		In addition it surrounds you with a shield of light, damaging anything that attacks you for %0.2f light damage.
 		You may only have one Chant active at once.
-		The damage will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 10, 50), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 5, 25)))
+		The effects will increase with the Magic stat]]):
+		format(damageinc, damDesc(self, DamageType.LIGHT, damage))
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/circles.lua b/game/modules/tome/data/talents/divine/circles.lua
index d11e0d5d2f3774acb79a2fd6b08e5ca1a584bc32..1e770192e0c0c81030379d50c9ab113bc37408ee 100644
--- a/game/modules/tome/data/talents/divine/circles.lua
+++ b/game/modules/tome/data/talents/divine/circles.lua
@@ -29,15 +29,15 @@ newTalent{
 		ATTACK = 10,
 		BUFF = 10,
 	},
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 4, 30) end,
+	getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end,
+	getRadius = function(self, t) return 2 + math.floor(self:getTalentLevelRaw(t)/2) end,
 	action = function(self, t)
-		local duration = 3 + math.ceil(self:getTalentLevel(t))
-		radius = 2 + math.floor(self:getTalentLevelRaw(t)/2)
-		local dam = self:combatTalentSpellDamage(t, 4, 30)
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			self.x, self.y, duration,
-			DamageType.SHIFTINGSHADOWS, dam,
-			radius,
+			self.x, self.y, t.getDuration(self, t),
+			DamageType.SHIFTINGSHADOWS, t.getDamage(self, t),
+			t.getRadius(self, t),
 			5, nil,
 			engine.Entity.new{alpha=75, display='', color_br=60, color_bg=10, color_bb=60},
 			nil, self:spellFriendlyFire(true)
@@ -46,8 +46,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Creates a radius %d circle at your feet that increases your defense by %d and deals %0.2f darkness damage per turn to everyone else with in its radius.  The circle lasts %d turns.
-		The duration will increase with the Magic stat.]]):format(2 + math.floor(self:getTalentLevelRaw(t)/2), self:combatTalentSpellDamage(t, 4, 30), (damDesc (self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 4, 30))), 3 + math.ceil(self:getTalentLevel(t)))
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		local radius = t.getRadius(self, t)
+		return ([[Creates a circle of radius %d at your feet, it increase your defense by %d and deals %0.2f darkness damage per turn to everyone else with in its radius.  The circle lasts %d turns.
+		The damage will increase with the Magic stat.]]):
+		format(radius, damage, (damDesc (self, DamageType.DARKNESS, damage)), duration)
 	end,
 }
 
@@ -62,16 +66,17 @@ newTalent{
 		ATTACK = 10,
 		BUFF = 10,
 	},
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 2, 15) end,
+	getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end,
+	getRadius = function(self, t) return 2 + math.floor(self:getTalentLevelRaw(t)/2) end,
 	action = function(self, t)
-		local duration = 3 + math.ceil(self:getTalentLevel(t))
-		radius = 2 + math.floor(self:getTalentLevelRaw(t)/2)
-		local dam = self:combatTalentSpellDamage(t, 2, 15) 
+		local radius = t.getRadius(self, t)
 		local tg = {type="ball", range=0, friendlyfire=true, radius=radius, talent=t}
 		self:project(tg, self.x, self.y, DamageType.LITE, 1)
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			self.x, self.y, duration,
-			DamageType.BLAZINGLIGHT, dam,
+			self.x, self.y, t.getDuration(self, t),
+			DamageType.BLAZINGLIGHT, t.getDamage(self, t),
 			radius,
 			5, nil,
 			engine.Entity.new{alpha=75, display='', color_br=250, color_bg=200, color_bb=10},
@@ -81,8 +86,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Creates a radius %d circle at your feet that lights up affected tiles, increases your positive energy by %d each turn, and deals %0.2f light damage and %0.2f fire damage per turn to everyone else with in its radius.  The circle lasts %d turns.
-		The duration will increase with the Magic stat.]]):format(2 + math.floor(self:getTalentLevelRaw(t)/2), 1 + (self:combatTalentSpellDamage(t, 2, 15) / 4), (damDesc (self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 2, 15))), (damDesc (self, DamageType.FIRE, self:combatTalentSpellDamage(t, 2, 15))), 3 + math.ceil(self:getTalentLevel(t)))
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		local radius = t.getRadius(self, t)
+		return ([[Creates a circle of radius %d at your feet, it lights up affected tiles, increases your positive energy by %d each turn, and deals %0.2f light damage and %0.2f fire damage per turn to everyone else within its radius.  The circle lasts %d turns.
+		The damage will increase with the Magic stat.]]):
+		format(radius, 1 + (damage / 4), (damDesc (self, DamageType.LIGHT, damage)), (damDesc (self, DamageType.FIRE, damage)), duration)
 	end,
 }
 
@@ -98,15 +107,14 @@ newTalent{
 		ATTACK = 10,
 		BUFF = 10,
 	},
+	getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end,
+	getRadius = function(self, t) return 2 + math.floor(self:getTalentLevelRaw(t)/2) end,
 	action = function(self, t)
-		local duration = 3 + math.ceil(self:getTalentLevel(t))
-		radius = 2 + math.floor(self:getTalentLevelRaw(t)/2)
-		local dam = 1
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			self.x, self.y, duration,
-			DamageType.SANCTITY, dam,
-			radius,
+			self.x, self.y, t.getDuration(self, t),
+			DamageType.SANCTITY, 1,
+			t.getRadius(self, t),
 			5, nil,
 			engine.Entity.new{alpha=75, display='', color_br=150, color_bg=10, color_bb=200},
 			nil, self:spellFriendlyFire(true)
@@ -115,8 +123,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Creates a radius %d circle at your feet that protects you from silence effects while you remain in its radius and silences everyone else who enters.  The circle lasts %d turns.
-		The duration will increase with the Magic stat.]]):format(2 + math.floor(self:getTalentLevelRaw(t)/2), 3 + math.ceil(self:getTalentLevel(t)))
+		local duration = t.getDuration(self, t)
+		local radius = t.getRadius(self, t)
+		return ([[Creates a circle of radius %d at your feet, it protects you from silence effects while you remain in its radius and silences everyone else who enters.  The circle lasts %d turns.]]):
+		format(radius, getDuration)
 	end,
 }
 
@@ -132,15 +142,15 @@ newTalent{
 		ATTACK = 10,
 		BUFF = 10,
 	},
+	getDuration = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)) end,
+	getRadius = function(self, t) return 2 + math.floor(self:getTalentLevelRaw(t)/2) end,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 2, 20)  end,
 	action = function(self, t)
-		local duration = 3 + math.ceil(self:getTalentLevel(t))
-		radius = 2 + math.floor(self:getTalentLevelRaw(t)/2)
-		local dam = self:combatTalentSpellDamage(t, 2, 20) 
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			self.x, self.y, duration,
-			DamageType.WARDING, dam,
-			radius,
+			self.x, self.y, t.getDuration(self, t),
+			DamageType.WARDING, t.getDamage(self, t),
+			t.getRadius(self, t),
 			5, nil,
 			engine.Entity.new{alpha=75, display='', color_br=200, color_bg=200, color_bb=200},
 			nil, self:spellFriendlyFire(true)
@@ -149,8 +159,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Creates a radius %d circle at your feet that slows incoming projectiles %d%% and attempts to push all creatures other then yourself out of its radius, inflicting %0.2f light damage and %0.2f darkness damage per turn as it does so.  The circle lasts %d turns.
-		The duration will increase with the Magic stat.]]):format(2 + math.floor(self:getTalentLevelRaw(t)/2), self:combatTalentSpellDamage(t, 2, 20), (damDesc (self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 2, 20))), (damDesc (self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 2, 20))), 3 + math.ceil(self:getTalentLevel(t)))
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		local radius = t.getRadius(self, t)
+		return ([[Creates a circle of radius %d at your feet, it slows incoming projectiles %d%% and attempts to push all creatures other then yourself out of its radius, inflicting %0.2f light damage and %0.2f darkness damage per turn as it does so.  The circle lasts %d turns.
+		The slow effect and damage will increase with the Magic stat.]]):
+		format(radius, damage, (damDesc (self, DamageType.LIGHT, damage)), (damDesc (self, DamageType.DARKNESS, damage)), duration)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/divine/combat.lua b/game/modules/tome/data/talents/divine/combat.lua
index 79be04b813a9d494e7f7592b9f6ab1a21a55a368..400c5d3803e1dba6b38eb0cca401155c96b3364e 100644
--- a/game/modules/tome/data/talents/divine/combat.lua
+++ b/game/modules/tome/data/talents/divine/combat.lua
@@ -29,6 +29,7 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getDamage = function(self, t) return 7 + self:combatSpellpower(0.092) * self:getTalentLevel(t) end,
 	activate = function(self, t)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
@@ -39,9 +40,11 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDamage(self, t)
 		return ([[Infuse your weapon of the power of the Sun, doing %0.2f light damage with each hit.
 		Each hit will drain 3 positive energy. The spell ends when energy reaches 0.
-		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.LIGHT, 7 + self:combatSpellpower(0.092) * self:getTalentLevel(t)))
+		The damage will increase with the Magic stat]]):
+		format(damDesc(self, DamageType.LIGHT, damage))
 	end,
 }
 
@@ -59,6 +62,7 @@ newTalent{
 	range = 6,
 	reflectable = true,
 	requires_target = true,
+	getReturnDamage = function(self, t) return 8 * self:getTalentLevelRaw(t) end,
 	action = function(self, t)
 		local tg = {type="bolt", range=self:getTalentRange(t), talent=t}
 		local x, y = self:getTarget(tg)
@@ -67,16 +71,16 @@ newTalent{
 		game:playSoundNear(self, "talents/spell_generic")
 		local target = game.level.map(x, y, Map.ACTOR)
 		if target and target:checkHit(self:combatSpellpower(), target:combatMentalResist(), 0, 95, 15)then
-			target:setEffect(self.EFF_MARTYRDOM, 10, {power=8 * self:getTalentLevelRaw(t)})
+			target:setEffect(self.EFF_MARTYRDOM, 10, {power=t.getReturnDamage(self, t)})
 		else
 			return
 		end
 		return true
 	end,
 	info = function(self, t)
-		return ([[Designate a target as martyr for 10 turns. When the martyr deals damage it also damages itself for %d%% of its damage dealt.
-		The damage percent will increase with the Magic stat]]):
-		format(	8 * self:getTalentLevelRaw(t))
+		local returndamage = t.getReturnDamage(self, t)
+		return ([[Designate a target as martyr for 10 turns. When the martyr deals damage it also damages itself for %d%% of its damage dealt.]]):
+		format(returndamage)
 	end,
 }
 
@@ -93,6 +97,7 @@ newTalent{
 	},
 	requires_target = true,
 	range = function(self, t) return 2 + self:getStr(12) end,
+	getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.1, 1.9) end,
 	action = function(self, t)
 		local tg = {type="bolt", range=self:getTalentRange(t), talent=t}
 		local x, y = self:getTarget(tg)
@@ -100,16 +105,17 @@ newTalent{
 		local _ _, x, y = self:canProject(tg, x, y)
 		local target = game.level.map(x, y, Map.ACTOR)
 		if target then
-			self:attackTarget(target, nil, self:combatTalentWeaponDamage(t, 1.1, 1.9), true)
+			self:attackTarget(target, nil, t.getDamage(self, t), true)
 		else
 			return
 		end
 		return true
 	end,
 	info = function(self, t)
-		return ([[In a pure display of power you project a melee attack up to a range of %d, doing %d%% damage.
+		local damage = t.getDamage(self, t)
+		return ([[In a pure display of power you project a melee attack, doing %d%% damage.
 		The range will increase with the Strength stat]]):
-		format(self:getTalentRange(t), 100 * self:combatTalentWeaponDamage(t, 1.1, 1.9))
+		format(100 * damage)
 	end,
 }
 
@@ -126,16 +132,18 @@ newTalent{
 	},
 	range = 1,
 	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.1, 1.9) end,
 	action = function(self, t)
 		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
 		if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
-		self:attackTarget(target, DamageType.LIGHT, self:combatTalentWeaponDamage(t, 1.1, 1.9), true)
+		self:attackTarget(target, DamageType.LIGHT, t.getDamage(self, t), true)
 		return true
 	end,
 	info = function(self, t)
-		return ([[Concentrate the power of the sun in a single blow doing %d%% light damage.]]):
-		format(100 * self:combatTalentWeaponDamage(t, 1.1, 1.9))
+		local damage = t.getDamage(self, t)
+		return ([[Concentrate the power of the sun in a single blow doing %d%% weapon damage as light damage.]]):
+		format(100 * damage)
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/eclipse.lua b/game/modules/tome/data/talents/divine/eclipse.lua
index bd03ccc5034c65d09f26733e4473f1c148b3f9d6..ff91fbc9bc8dd83de98531c6004a5a92e5281393 100644
--- a/game/modules/tome/data/talents/divine/eclipse.lua
+++ b/game/modules/tome/data/talents/divine/eclipse.lua
@@ -46,22 +46,26 @@ newTalent{
 	},
 	positive = 10,
 	negative = 10,
+	getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t)) end,
+	getResistancePenetration = function(self, t) return 5 + (self:getCun() / 10) * self:getTalentLevel(t) end,
+	getCooldownReduction = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
 	action = function(self, t)
-		local dur = 4 + math.ceil(self:getTalentLevel(t))
-		local power = 5 + (self:getCun() / 10) * self:getTalentLevel(t)
-		self:setEffect(self.EFF_TOTALITY, dur, {power=power})
+		self:setEffect(self.EFF_TOTALITY, t.getDuration(self, t), {power=t.getResistancePenetration(self, t)})
 		for tid, cd in pairs(self.talents_cd) do
 			local tt = self:getTalentFromId(tid)
 			if tt.type[1]:find("^divine/") then
-				self.talents_cd[tid] = cd - (1 + math.ceil(self:getTalentLevel(t)))
+				self.talents_cd[tid] = cd - t.getCooldownReduction(self, t)
 			end
 		end
 		return true
 	end,
 	info = function(self, t)
+		local penetration = t.getDuration(self, t)
+		local duration = t.getResistancePenetration(self, t)
+		local cooldownreduction = t.getCooldownReduction(self, t)
 		return ([[Increases your light and darkness resistance penetration by %d%% for %d turns and brings all your divine talents on cooldown, %d turns closer to being off cooldown.
-		The resistance penetration will increase with your Cunning stat.
-		]]):format(5 + (self:getCun() / 10) * self:getTalentLevel(t), 4 + math.ceil(self:getTalentLevel(t)), 1 + math.ceil(self:getTalentLevel(t)))
+		The resistance penetration will increase with your Cunning stat.]]):
+		format(penetration, duration, cooldownreduction)
 	end,
 }
 
@@ -75,6 +79,9 @@ newTalent{
 	range = 10,
 	sustain_negative = 10,
 	sustain_positive = 10,
+	getTargetCount = function(self, t) return math.floor(self:getTalentLevel(t)) end,
+	getLightDamage = function(self, t) return self:combatTalentSpellDamage(t, 15, 70) end,
+	getDarknessDamage = function(self, t) return self:combatTalentSpellDamage(t, 15, 70) end,
 	on_crit = function(self, t)
 		local tgts = {}
 		local grids = core.fov.circle_grids(self.x, self.y, 10, true)
@@ -87,7 +94,7 @@ newTalent{
 		
 		-- Randomly take targets
 		local tg = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_fire"}}
-		for i = 1, math.floor(self:getTalentLevel(t)) do
+		for i = 1, t.getTargetCount(self, t) do
 			if #tgts <= 0 then break end
 			local a, id = rng.table(tgts)
 			table.remove(tgts, id)
@@ -95,11 +102,11 @@ newTalent{
 		local corona = rng.range(1, 100)
 			if corona > 50 then
 				local tg = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_light"}}
-				self:projectile(tg, a.x, a.y, DamageType.LIGHT, (self:combatTalentSpellDamage(t, 15, 70)), {type="light"})
+				self:projectile(tg, a.x, a.y, DamageType.LIGHT, t.getLightDamage(self, t), {type="light"})
 				self:incPositive(-2)
 			else
 				local tg = {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_dark"}}
-				self:projectile(tg, a.x, a.y, DamageType.DARKNESS, (self:combatTalentSpellDamage(t, 15, 70)), {type="shadow"})
+				self:projectile(tg, a.x, a.y, DamageType.DARKNESS, t.getDarknessDamage(self, t), {type="shadow"})
 				self:incNegative(-2)				
 			end
 		end
@@ -113,9 +120,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local targetcount = t.getTargetCount(self, t)
+		local lightdamage = t.getLightDamage(self, t)
+		local darknessdamage = t.getDarknessDamage(self, t)
 		return ([[Each time one of your spells is a critical you project a bolt of light or shadow at %d targets in a radius of 10, doing %0.2f light damage or %0.2f darkness damage.
 		The damage scales with the Magic stat and each bolt fired will cost 2 positive or negative energy respectively.]]):
-		format(self:getTalentLevel(t), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 15, 70)), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 15, 70)))
+		format(targetcount, damDesc(self, DamageType.LIGHT, lightdamage), damDesc(self, DamageType.DARKNESS, darknessdamage))
 	end,
 }
 
@@ -130,12 +140,15 @@ newTalent{
 	tactical = {
 		DEFEND = 10,
 	},
+	getInvisibilityPower = function(self, t) return 5 + (self:getCun() / 15) * self:getTalentLevel(t) end,
+	getEnergyConvert = function(self, t) return 6 - (self:getTalentLevelRaw(t)) end,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 10, 100) end,
+	getRadius = function(self, t) return 2 + self:getTalentLevel(t) / 2 end,
 	activate = function(self, t)
-		local power = 5 + (self:getCun() / 15) * self:getTalentLevel(t)
-		local timer = 6 - (self:getTalentLevelRaw(t))
+		local timer = t.getEnergyConvert(self, t)
 		game:playSoundNear(self, "talents/heal")
 		return {
-			invisible = self:addTemporaryValue("invisible", power),
+			invisible = self:addTemporaryValue("invisible", t.getInvisibilityPower(self, t)),
 			fill = self:addTemporaryValue("positive_regen", timer),
 			drain = self:addTemporaryValue("negative_regen", - timer),
 		}
@@ -144,18 +157,23 @@ newTalent{
 		self:removeTemporaryValue("invisible", p.invisible)
 		self:removeTemporaryValue("positive_regen", p.fill)
 		self:removeTemporaryValue("negative_regen", p.drain)
-		local tg = {type="ball", range=0, friendlyfire=true, radius= 2 + self:getTalentLevel(t) / 2, talent=t}
+		local tg = {type="ball", range=0, friendlyfire=true, radius= t.getRadius(self, t), talent=t}
 		self:project(tg, self.x, self.y, DamageType.LITE, 1)
 		tg.friendlyfire = false
-		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(self:combatTalentSpellDamage(t, 10, 100) + self.positive))
+		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(t.getDamage(self, t) + self.positive))
 		game.level.map:particleEmitter(self.x, self.y, tg.radius, "sunburst", {radius=tg.radius, grids=grids, tx=self.x, ty=self.y, max_alpha=80})
 		game:playSoundNear(self, "talents/flame")
 		self.positive = 0
 		return true
 	end,
 	info = function(self, t)
+		local invisibilitypower = t.getInvisibilityPower(self, t)
+		local convert = t.getEnergyConvert(self, t)
+		local damage = t.getDamage(self, t)
+		local radius = t.getRadius(self, t)
 		return ([[This powerful spell grants you %d bonus invisibility, but converts %d negative energy into positive energy each turn.  Once your positive energy exceeds your negative energy, or you deactivate the talent, the effect ends in an explosion of light, converting all of your positive energy into damage and inflicting an additional %0.2f damage on everything in a radius of %d.
 		You may not cast Twilight while this spell is active and you should take off your light source otherwise you will still easily be spotted.
-		The invsibility bonus will increase with your Cunning stat and the explosion damage will increase with the Magic Stat..]]):format(5 + (self:getCun() / 15) * self:getTalentLevel(t), 6 - (self:getTalentLevelRaw(t)), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 10, 100)), 2 + self:getTalentLevel(t) / 2)
+		The invsibility bonus will increase with your Cunning stat and the explosion damage will increase with the Magic Stat..]]):
+		format(invisibilitypower, convert, damDesc(self, DamageType.LIGHT, damage), radius)
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/glyphs.lua b/game/modules/tome/data/talents/divine/glyphs.lua
index 3574ed710faa97a589792a783532e0c412b18fdd..25a0d6a46b4809554a962de96af340d8b8f509b2 100644
--- a/game/modules/tome/data/talents/divine/glyphs.lua
+++ b/game/modules/tome/data/talents/divine/glyphs.lua
@@ -29,6 +29,8 @@ newTalent{
 	positive = -10,
 	requires_target = true,
 	range = function(self, t) return math.floor (self:getTalentLevel(t)) end,
+	getDazeDuration = function(self, t) return 3 + self:getTalentLevelRaw(t) end,
+	getDuration = function(self, t) return 5 + self:getTalentLevel(t) end,
 	action = function(self, t)
 		local tg = {type="bolt", nowarning=true, range=self:getTalentRange(t), nolock=true, talent=t}
 		local tx, ty = self:getTarget(tg)
@@ -37,7 +39,7 @@ newTalent{
 		local trap = game.level.map(tx, ty, Map.TRAP)
 		if trap then return end
 
-		local dam = 3 + self:getTalentLevelRaw(t)
+		local dam = t.getDamage(self, t)
 		local trap = Trap.new{
 			name = "glyph of paralysis",
 			type = "elemental", id_by_type=true, unided_name = "trap",
@@ -51,7 +53,7 @@ newTalent{
 				who:setEffect(who.EFF_DAZED, self.dam, {})
 				return true
 			end,
-			temporary = 5 + self:getTalentLevel(t),
+			temporary = t.getDuration(self, t),
 			x = tx, y = ty,
 			canAct = false,
 			energy = {value=0},
@@ -74,8 +76,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local dazeduration = t.getDazeDuration(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[You bind light in a glyph on the floor. All targets passing by will be dazed for %d turns.
-		The glyph lasts for %d turns.]]):format(3 + self:getTalentLevelRaw(t), 5 + self:getTalentLevel(t))
+		The glyph lasts for %d turns.]]):format(dazeduration, duration)
 	end,
 }
 
@@ -89,6 +93,8 @@ newTalent{
 	cooldown = 20,
 	requires_target = true,
 	range = function(self, t) return math.floor (self:getTalentLevel(t)) end,
+	getDamage = function(self, t) return 15 + self:combatSpellpower(0.12) * self:getTalentLevel(t) end,
+	getDuration = function(self, t) return 5 + self:getTalentLevel(t) end,
 	action = function(self, t)
 		local tg = {type="bolt", nowarning=true, range=self:getTalentRange(t), nolock=true, talent=t}
 		local tx, ty = self:getTarget(tg)
@@ -97,7 +103,7 @@ newTalent{
 		local trap = game.level.map(tx, ty, Map.TRAP)
 		if trap then return end
 
-		local dam = 15 + self:combatSpellpower(0.12) * self:getTalentLevel(t)
+		local dam = t.getDamage(self, t)
 		local sp = self:combatSpellpower()
 		local trap = Trap.new{
 			name = "glyph of repulsion",
@@ -116,7 +122,7 @@ newTalent{
 				self.x, self.y = ox, oy
 				return true
 			end,
-			temporary = 5 + self:getTalentLevel(t),
+			temporary = t.getDuration(self, t),
 			x = tx, y = ty,
 			canAct = false,
 			energy = {value=0},
@@ -140,9 +146,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[You bind light in a glyph on the floor. All targets passing by will be hit by a blast of light doing %0.2f damage and knocked back.
 		The glyph lasts for %d turns.
-		The damage will increase with the Magic stat]]):format(15 + self:combatSpellpower(0.12) * self:getTalentLevel(t), 5 + self:getTalentLevel(t))
+		The damage will increase with the Magic stat]]):
+		format(damage, duration)
 	end,
 }
 
@@ -156,6 +165,8 @@ newTalent{
 	positive = -10,
 	requires_target = true,
 	range = function(self, t) return math.floor (self:getTalentLevel(t)) end,
+	getDamage = function(self, t) return 15 + self:combatSpellpower(0.12) * self:getTalentLevel(t) end,
+	getDuration = function(self, t) return 5 + self:getTalentLevel(t) end,
 	action = function(self, t)
 		local tg = {type="bolt", nowarning=true, range=self:getTalentRange(t), nolock=true, talent=t}
 		local tx, ty = self:getTarget(tg)
@@ -164,7 +175,7 @@ newTalent{
 		local trap = game.level.map(tx, ty, Map.TRAP)
 		if trap then return end
 
-		local dam = 15 + self:combatSpellpower(0.12) * self:getTalentLevel(t)
+		local dam = t.getDamage(self, t)
 		local trap = Trap.new{
 			name = "glyph of explosion",
 			type = "elemental", id_by_type=true, unided_name = "trap",
@@ -179,7 +190,7 @@ newTalent{
 				game.level.map:particleEmitter(x, y, 1, "sunburst", {radius=1, tx=x, ty=y})
 				return true
 			end,
-			temporary = 5 + self:getTalentLevel(t),
+			temporary = t.getDuration(self, t),
 			x = tx, y = ty,
 			canAct = false,
 			energy = {value=0},
@@ -202,9 +213,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[You bind light in a glyph on the floor. All targets passing by will trigger a radius 1 blast of light doing %0.2f damage.
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		return ([[You bind light in a glyph on the floor. All targets passing by will trigger blast of light doing %0.2f damage.
 		The glyph lasts for %d turns.
-		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.LIGHT, 15 + self:combatSpellpower(0.12) * self:getTalentLevel(t)), 5 + self:getTalentLevel(t))
+		The damage will increase with the Magic stat]]):
+		format(damDesc(self, DamageType.LIGHT, damage), duration)
 	end,
 }
 
@@ -218,6 +232,8 @@ newTalent{
 	positive = -10,
 	requires_target = true,
 	range = function(self, t) return math.floor (self:getTalentLevel(t)) end,
+	getSlow = function(self, t) return self:getTalentLevel(t) * 0.07 + 0.2 end,
+	getDuration = function(self, t) return 5 + self:getTalentLevel(t) end,
 	action = function(self, t)
 		local tg = {type="bolt", nowarning=true, range=self:getTalentRange(t), nolock=true, talent=t}
 		local tx, ty = self:getTarget(tg)
@@ -226,7 +242,7 @@ newTalent{
 		local trap = game.level.map(tx, ty, Map.TRAP)
 		if trap then return end
 
-		local dam = -1 + 1 / (1 + (self:getTalentLevel(t) * 0.07 + 0.2))
+		local dam = -1 + 1 / (1 + (t.getSlow(self, t)))
 		local trap = Trap.new{
 			name = "glyph of fatigue",
 			type = "elemental", id_by_type=true, unided_name = "trap",
@@ -240,7 +256,7 @@ newTalent{
 				who:setEffect(who.EFF_SLOW, 5, {power=-self.dam})
 				return true
 			end,
-			temporary = 5 + self:getTalentLevel(t),
+			temporary = t.getDuration(self, t),
 			x = tx, y = ty,
 			canAct = false,
 			energy = {value=0},
@@ -263,7 +279,9 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local slow = t.getSlow(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[You bind light in a glyph on the floor. All targets passing by will be slowed by %d%%.
-		The glyph lasts for %d turns.]]):format(self:getTalentLevel(t) * 7 + 20, 5 + self:getTalentLevel(t))
+		The glyph lasts for %d turns.]]):format(100 * slow, duration)
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/guardian.lua b/game/modules/tome/data/talents/divine/guardian.lua
index c371e69ab06fc357a45ff94647fb2f03b09eb9d7..67ab876180b6790247671f394488058548efdcf6 100644
--- a/game/modules/tome/data/talents/divine/guardian.lua
+++ b/game/modules/tome/data/talents/divine/guardian.lua
@@ -29,6 +29,7 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getHeal = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		local shield = self:hasShield()
 		if not shield then
@@ -45,9 +46,11 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local heal = t.getHeal(self, t)
 		return ([[Infuse your shield with light energy, healing you for %0.2f each time you take damage.
 		Each heal will drain up to 2 positive energy. The spell ends when energy reaches 0.
-		The healing done will increase with the Magic stat]]):format(self:combatTalentSpellDamage(self.T_SHIELD_OF_LIGHT, 1, 25))
+		The healing done will increase with the Magic stat]]):
+		format(heal)
 	end,
 }
 
@@ -59,6 +62,10 @@ newTalent{
 	cooldown = 8,
 	positive = 20,
 	requires_target = true,
+	getWeaponDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.8, 1.3) end,
+	getShieldDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.8, 1.3, self:getTalentLevel(self.T_SHIELD_EXPERTISE)) end,
+	getLightDamage = function(self, t) return self:combatTalentSpellDamage(t, 20, 150) end,
+	getRadius = function(self, t) return 2 + self:getTalentLevel(t) / 2 end,
 	action = function(self, t)
 		local shield = self:hasShield()
 		if not shield then
@@ -72,16 +79,16 @@ newTalent{
 		if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
 
 		-- First attack with weapon
-		self:attackTarget(target, nil, self:combatTalentWeaponDamage(t, 0.8, 1.3), true)
+		self:attackTarget(target, nil, t.getWeaponDamage(self, t), true)
 		-- Second attack with shield
-		local speed, hit = self:attackTargetWith(target, shield.special_combat, nil, self:combatTalentWeaponDamage(t, 0.8, 1.3, self:getTalentLevel(self.T_SHIELD_EXPERTISE)))
+		local speed, hit = self:attackTargetWith(target, shield.special_combat, nil, t.getShieldDamage(self, t))
 
 		-- Light Burst
 		if hit then
-			local tg = {type="ball", range=1, friendlyfire=true, radius=2 + self:getTalentLevel(t) / 2, talent=t}
+			local tg = {type="ball", range=1, friendlyfire=true, radius=t.getRadius(self, t), talent=t}
 			self:project(tg, x, y, DamageType.LITE, 1)
 			tg.friendlyfire = false
-			local grids = self:project(tg, x, y, DamageType.LIGHT, self:combatTalentSpellDamage(t, 20, 150))
+			local grids = self:project(tg, x, y, DamageType.LIGHT, t.getLightDamage(self, t))
 			game.level.map:particleEmitter(x, y, tg.radius, "sunburst", {radius=tg.radius, grids=grids, tx=x, ty=y, max_alpha=80})
 			game:playSoundNear(self, "talents/flame")
 		end
@@ -89,8 +96,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Hits the target with your weapon and a shield strike doing %d%% damage.  If the shield strike hits your shield will explode in a burst of light, inflicting %0.2f light damage on all within a radius of %d of the target, lighting up the affected grids.
-	]]):format(100 * self:combatTalentWeaponDamage(t, 0.8, 1.3, self:getTalentLevel(self.T_SHIELD_EXPERTISE)), damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 20, 150)), 2 + self:getTalentLevel(t) / 2)
+		local weapondamage = t.getWeaponDamage(self, t)
+		local shielddamage = t.getShieldDamage(self, t)
+		local lightdamage = t.getLightDamage(self, t)
+		local radius = t.getRadius(self, t)
+		return ([[Hits the target with your weapon doing %d%% damage and a shield strike doing %d%% damage.  If the shield strike hits your shield will explode in a burst of light, inflicting %0.2f light damage on all within a radius of %d of the target, lighting up the affected grids.
+		Light damage will increase with your Magic stat.]]):
+		format(100 * weapondamage, 100 * shielddamage, damDesc(self, DamageType.LIGHT, lightdamage), radius)
 	end,
 }
 
@@ -106,13 +118,14 @@ newTalent{
 	tactical = {
 		DEFEND = 10,
 	},
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 28, 170) end,
 	activate = function(self, t)
 		local shield = self:hasShield()
 		if not shield then
 			game.logPlayer(self, "You cannot use Retribution without a shield!")
 			return nil
 		end
-		local power = self:combatTalentSpellDamage(t, 28, 170)
+		local power = t.getDamage(self, t)
 		self.retribution_absorb = power
 		self.retribution_strike = power
 		game:playSoundNear(self, "talents/generic")
@@ -127,8 +140,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[You start absorbing half of all damage you take into your shield.  Once you're shield has absorbed %0.2f damage it will explode in a burst of light, inflicting damage in a radius of %d.
-		The amount absorbed will increase with the Magic stat.]]):format(damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 28, 170)), 1 + self:getTalentLevelRaw(t))
+		local damage = t.getDamage(self, t)
+		return ([[You start absorbing half of all damage you take into your shield.  Once you're shield has absorbed %0.2f damage it will explode in a burst of light, inflicting damage equal to absorbed damage in a radius of %d.
+		The amount absorbed will increase with the Magic stat.]]):
+		format(damDesc(self, DamageType.LIGHT, damage), self:getTalentRange(t))
 	end,
 }
 
@@ -146,6 +161,7 @@ newTalent{
 	tactical = {
 		DEFEND = 10,
 	},
+	getLife = function(self, t) return self.max_life * (0.05 + self:getTalentLevel(t)/25) end,
 	activate = function(self, t)
 		game:playSoundNear(self, "talents/heal")
 		local ret = {
@@ -158,7 +174,8 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Any attack that would drop you below 1 hit point triggers Second Life, deactivating the talent and setting your hit points to %d.]]):format(self.max_life * (0.05 + self:getTalentLevel(self.T_SECOND_LIFE)/25))
+		return ([[Any attack that would drop you below 1 hit point triggers Second Life, deactivating the talent and setting your hit points to %d.]]):
+		format(t.getLife(self, t))
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/divine/hymns.lua b/game/modules/tome/data/talents/divine/hymns.lua
index ee96e69da690cfbeee34fff787d8999316b8d00e..e7c84034d738d5ebfc6ab7cf6e23e19f83be496b 100644
--- a/game/modules/tome/data/talents/divine/hymns.lua
+++ b/game/modules/tome/data/talents/divine/hymns.lua
@@ -40,14 +40,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 10, 50) end,
+	getDarknessDamageIncrease = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
 	activate = function(self, t)
 		cancelHymns(self)
-		local power = self:combatTalentSpellDamage(t, 10, 50)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]=dam}),
-			phys = self:addTemporaryValue("inc_damage", {[DamageType.DARKNESS] = power}),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]= t.getDamageOnMeleeHit(self, t)}),
+			phys = self:addTemporaryValue("inc_damage", {[DamageType.DARKNESS] = t.getDarknessDamageIncrease(self, t)}),
 			particle = self:addParticles(Particles.new("darkness_shield", 1))
 		}
 		return ret
@@ -59,10 +59,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local darknessinc = t.getDarknessDamageIncrease(self, t)
+		local darknessdamage = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the moon, granting you %d%% more darkness damage.
 		In addition it surrounds you with a shield of shadows, damaging anything that attacks you for %0.2f darkness damage.
 		You may only have one Hymn active at once.
-		The damage will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 10, 50), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 5, 25)))
+		The damage and damage increase will improve with the Magic stat]]):
+		format(darknessinc, damDesc(self, DamageType.DARKNESS, darknessdamage))
 	end,
 }
 
@@ -80,13 +83,14 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 5, 25) end,
+	getInfraVisionPower = function(self, t) return math.floor(5 + self:getTalentLevel(t)) end,
 	activate = function(self, t)
 		cancelHymns(self)
-		local dam = self:combatTalentSpellDamage(t, 5, 25)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]=dam}),
-			infravision = self:addTemporaryValue("infravision", math.floor(5 + self:getTalentLevel(t))),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]= t.getDamageOnMeleeHit(self, t)}),
+			infravision = self:addTemporaryValue("infravision", t.getInfraVisionPower(self, t)),
 			particle = self:addParticles(Particles.new("darkness_shield", 1))
 		}
 		return ret
@@ -98,10 +102,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local infra = t.getInfraVisionPower(self, t)
+		local darknessdamage = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the moon, granting you infravision up to %d grids.
 		In addition it surrounds you with a shield of darkness, damaging anything that attacks you for %0.2f darkness damage.
 		You may only have one Hymn active at once.
-		The damage will increase with the Magic stat]]):format(math.floor(5 + self:getTalentLevel(t)), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 5, 25)))
+		The damage will increase with the Magic stat]]):
+		format(infra, damDesc(self, DamageType.DARKNESS, darknessdamage))
 	end,
 }
 
@@ -119,15 +126,17 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getDamageOnMeleeHit = function(self, t) return self:combatTalentSpellDamage(t, 10, 50) end,
+	getImmunities = function(self, t) return 0.2 + self:getTalentLevel(t) / 10 end,
 	activate = function(self, t)
 		cancelHymns(self)
 		local dam = self:combatTalentSpellDamage(t, 5, 25)
 		game:playSoundNear(self, "talents/spell_generic2")
 		local ret = {
-			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]=dam}),
-			stun = self:addTemporaryValue("stun_immune", 0.2 + self:getTalentLevel(t) / 10),
-			confusion = self:addTemporaryValue("confusion_immune", 0.2 + self:getTalentLevel(t) / 10),
-			blind = self:addTemporaryValue("blind_immune", 0.2 + self:getTalentLevel(t) / 10),
+			onhit = self:addTemporaryValue("on_melee_hit", {[DamageType.DARKNESS]=t.getDamageOnMeleeHit(self, t)}),
+			stun = self:addTemporaryValue("stun_immune", t.getImmunities(self, t)),
+			confusion = self:addTemporaryValue("confusion_immune", t.getImmunities(self, t)),
+			blind = self:addTemporaryValue("blind_immune", t.getImmunities(self, t)),
 			particle = self:addParticles(Particles.new("darkness_shield", 1))
 		}
 		return ret
@@ -141,10 +150,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local immunities = t.getImmunities(self, t)
+		local darknessdamage = t.getDamageOnMeleeHit(self, t)
 		return ([[Chant the glory of the moon, granting you %d%% stun, blindness and confusion resistances.
 		In addition it surrounds you with a shield of darkness, damaging anything that attacks you for %0.2f darkness damage.
 		You may only have one Hymn active at once.
-		The resistances and damage will increase with the Magic stat]]):format(100 * (0.2 + self:getTalentLevel(t) / 10), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 5, 25)))
+		The resistances and damage will increase with the Magic stat]]):
+		format(100 * (immunities), damDesc(self, DamageType.DARKNESS, darknessdamage))
 	end,
 }
 
@@ -162,6 +174,9 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 7, 80) end,
+	getTargetCount = function(self, t) return math.floor(self:getTalentLevel(t)) end,
+	getNegativeDrain = function(self, t) return -self:getTalentLevelRaw(t) end,
 	do_beams = function(self, t)
 		if self:getNegative() <= 0 then
 			local old = self.energy.value
@@ -182,12 +197,12 @@ newTalent{
 
 		-- Randomly take targets
 		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
-		for i = 1, math.floor(self:getTalentLevel(t)) do
+		for i = 1, t.getTargetCount(self, t) do
 			if #tgts <= 0 then break end
 			local a, id = rng.table(tgts)
 			table.remove(tgts, id)
 
-			self:project(tg, a.x, a.y, DamageType.DARKNESS, rng.avg(1, self:spellCrit(self:combatTalentSpellDamage(t, 7, 80)), 3))
+			self:project(tg, a.x, a.y, DamageType.DARKNESS, rng.avg(1, self:spellCrit(t.getDamage(self, t)), 3))
 			game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(a.x-self.x), math.abs(a.y-self.y)), "shadow_beam", {tx=a.x-self.x, ty=a.y-self.y})
 			game:playSoundNear(self, "talents/spell_generic")
 		end
@@ -197,7 +212,7 @@ newTalent{
 		game:playSoundNear(self, "talents/spell_generic")
 		game.logSeen(self, "#DARK_GREY#A shroud of shadow dances around %s!", self.name)
 		return {
-			drain = self:addTemporaryValue("negative_regen", -1 * self:getTalentLevelRaw(t)),
+			drain = self:addTemporaryValue("negative_regen", t.getNegativeDrain(self, t)),
 		}
 	end,
 	deactivate = function(self, t, p)
@@ -206,9 +221,13 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local targetcount = t.getTargetCount(self, t)
+		local damage = t.getDamage(self, t)
+		local drain = t.getNegativeDrain(self, t)
 		return ([[Conjures a shroud of dancing shadows with a radius of 5 that follows you as long as this spell is active.
 		Each turn a random shadow beam will hit up to %d of your foes for 1 to %0.2f damage.
 		This powerful spell will continuously drain %d negative energy while active.
-		The damage will increase with the Magic stat]]):format(self:getTalentLevel(t), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 7, 80)), self:getTalentLevelRaw(t))
+		The damage will increase with the Magic stat]]):
+		format(targetcount, damDesc(self, DamageType.DARKNESS, damage), -drain)
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/light.lua b/game/modules/tome/data/talents/divine/light.lua
index 21857d6d69425a61032398f8a78c2267b19ac174..b98d944c89fd75ac5db853445e8c7b3990e42c99 100644
--- a/game/modules/tome/data/talents/divine/light.lua
+++ b/game/modules/tome/data/talents/divine/light.lua
@@ -28,14 +28,17 @@ newTalent{
 	tactical = {
 		HEAL = 10,
 	},
+	getHeal = function(self, t) return self:combatTalentSpellDamage(t, 20, 240) end,
 	action = function(self, t)
-		self:heal(self:spellCrit(self:combatTalentSpellDamage(t, 20, 240)), self)
+		self:heal(self:spellCrit(t.getHeal(self, t)), self)
 		game:playSoundNear(self, "talents/heal")
 		return true
 	end,
 	info = function(self, t)
+		local heal = t.getHeal(self, t)
 		return ([[An invigorating ray of Sunlight shines on you, healing your body for %d life.
-		The life healed will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 20, 240))
+		The life healed will increase with the Magic stat]]):
+		format(heal)
 	end,
 }
 
@@ -50,16 +53,15 @@ newTalent{
 	tactical = {
 		HEAL = 10,
 	},
+	getHeal = function(self, t) return self:combatTalentSpellDamage(t, 4, 30) end,
+	getDuration = function(self, t) return self:getTalentLevel(t) + 2 end,
 	action = function(self, t)
-		local duration = self:getTalentLevel(t) + 2
-		local radius = 3
-		local dam = self:combatTalentSpellDamage(t, 4, 30)
 		local tg = {type="ball", range=self:getTalentRange(t), radius=radius}
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			self.x, self.y, duration,
-			DamageType.HEALING_POWER, dam,
-			radius,
+			self.x, self.y, t.getDuration(self, t),
+			DamageType.HEALING_POWER, t.getHeal(self, t),
+			3,
 			5, nil,
 			{type="healing_vapour"},
 			nil, true
@@ -68,8 +70,11 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local heal = t.getHeal(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[A magical zone of Sunlight appears around you, healing all within a radius of 3 for %0.2f per turn and increasing healing effects on those within by %d%%.  The effect lasts %d turns.
-		The life healed will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 4, 30), self:combatTalentSpellDamage(t, 4, 30), self:getTalentLevel(t) + 2)
+		The life healed will increase with the Magic stat]]):
+		format(heal, heal, duration)
 	end,
 }
 
@@ -81,13 +86,17 @@ newTalent{
 	random_ego = "defensive",
 	positive = -20,
 	cooldown = 15,
+	getAbsorb = function(self, t) return self:combatTalentSpellDamage(t, 30, 270) end,
 	action = function(self, t)
-		self:setEffect(self.EFF_DAMAGE_SHIELD, 10, {power=self:combatTalentSpellDamage(t, 30, 270)})
+		self:setEffect(self.EFF_DAMAGE_SHIELD, 10, {power=t.getAbsorb(self, t)})
 		game:playSoundNear(self, "talents/heal")
 		return true
 	end,
 	info = function(self, t)
-		return ([[A protective shield forms around you that lasts for up to 10 turns, negating %d damage.]]):format(self:combatTalentSpellDamage(t, 30, 270))
+		local absorb = t.getAbsorb(self, t)
+		return ([[A protective shield forms around you that lasts for up to 10 turns, negating %d damage.
+		Max damage barrier can absorb will increase with your Magic stat.]]):
+		format(absorb)
 	end,
 }
 
@@ -102,15 +111,19 @@ newTalent{
 	tactical = {
 		HEAL = 10,
 	},
+	getRegeneration = function(self, t) return self:combatTalentSpellDamage(t, 10, 50) end,
+	getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)) end,
 	action = function(self, t)
-		local dur = 2 + math.ceil(self:getTalentLevel(t))
-		self:setEffect(self.EFF_PROVIDENCE, dur, {power=self:combatTalentSpellDamage(t, 10, 50)})
+		self:setEffect(self.EFF_PROVIDENCE, t.getDuration(self, t), {power=t.getRegeneration(self, t)})
 		game:playSoundNear(self, "talents/heal")
 		return true
 	end,
 	info = function(self, t)
+		local regen = t.getRegeneration(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[Places you under light's protection, regenerating your body for %d life and removing a single negative effect from you each turn for %d turns.
-		The life healed will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 10, 50), math.ceil(2 + self:getTalentLevel(t)))
+		The life healed will increase with the Magic stat]]):
+		format(regen, duration)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/divine/star-fury.lua b/game/modules/tome/data/talents/divine/star-fury.lua
index cb2d3aaa0b4acd71befcf481682092223d11a4a8..514f1f8ac739597ba8e994cbefcec8da3bbfd132 100644
--- a/game/modules/tome/data/talents/divine/star-fury.lua
+++ b/game/modules/tome/data/talents/divine/star-fury.lua
@@ -32,19 +32,22 @@ newTalent{
 	direct_hit = true,
 	reflectable = true,
 	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 14, 230) end,
 	action = function(self, t)
 		local tg = {type="beam", range=self:getTalentRange(t), talent=t}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		self:project(tg, x, y, DamageType.DARKNESS, self:spellCrit(self:combatTalentSpellDamage(t, 14, 230)))
+		self:project(tg, x, y, DamageType.DARKNESS, self:spellCrit(t.getDamage(self, t)))
 		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)), "shadow_beam", {tx=x-self.x, ty=y-self.y})
 		game:playSoundNear(self, "talents/flame")
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDamage(self, t)
 		return ([[Calls the power of the Moon into a beam of shadows doing %0.2f damage.
-		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 14, 230)))
+		The damage will increase with the Magic stat]]):
+		format(damDesc(self, DamageType.DARKNESS, damage))
 	end,
 }
 
@@ -62,20 +65,20 @@ newTalent{
 	range = 6,
 	direct_hit = true,
 	requires_target = true,
+	getDamageOnSpot = function(self, t) return self:combatTalentSpellDamage(t, 4, 50) end,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 5, 120) end,
+	getDuration = function(self, t) return self:getTalentLevel(t) + 2 end,
 	action = function(self, t)
-		local duration = self:getTalentLevel(t) + 2
-		local radius = 3
-		local dam = self:combatTalentSpellDamage(t, 4, 50)
-		local tg = {type="ball", range=self:getTalentRange(t), radius=radius, friendlyfire=self:spellFriendlyFire()}
+		local tg = {type="ball", range=self:getTalentRange(t), radius=3, friendlyfire=self:spellFriendlyFire()}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
 		local _ _, x, y = self:canProject(tg, x, y)
-		local grids = self:project(tg, x, y, DamageType.DARKNESS, self:spellCrit(self:combatTalentSpellDamage(t, 5, 120)), {type="shadow"})
+		local grids = self:project(tg, x, y, DamageType.DARKNESS, self:spellCrit(t.getDamage(self, t)), {type="shadow"})
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
-			x, y, duration,
-			DamageType.DARKNESS, dam,
-			radius,
+			x, y, t.getDuration(self, t),
+			DamageType.DARKNESS, t.getDamage(self, t),
+			3,
 			5, nil,
 			{type="shadow_zone"},
 			nil, self:spellFriendlyFire()
@@ -87,13 +90,12 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDuration(self, t)
+		local damageonspot = t.getDamageOnSpot(self, t)
+		local duration = t.getDuration(self, t)
 		return ([[Invokes a blast of shadows dealing %0.2f darkness damage and leaving a field that does %0.2f darkness damage per turn for %d turns.
 		The damage will increase with the Magic stat]]):
-		format(
-			damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 5, 120)),
-			damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 4, 50)),
-			self:getTalentLevel(t) + 2
-		)
+		format(damDesc(self, DamageType.DARKNESS, damage),damDesc(self, DamageType.DARKNESS, damageonspot),duration)
 	end,
 }
 
@@ -111,24 +113,24 @@ newTalent{
 	},
 	range = 2,
 	direct_hit = true,
+	getLightDamage = function(self, t) return 10 + self:combatSpellpower(0.2) * self:getTalentLevel(t) end,
+	getDarknessDamage = function(self, t) return 10 + self:combatSpellpower(0.2) * self:getTalentLevel(t) end,
 	action = function(self, t)
 		local tg = {type="ball", range=0, radius=self:getTalentRange(t), talent=t, friendlyfire=false}
-		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(10 + self:combatSpellpower(0.2) * self:getTalentLevel(t)))
-		self:project(tg, self.x, self.y, DamageType.DARKNESS, self:spellCrit(10 + self:combatSpellpower(0.2) * self:getTalentLevel(t)))
+		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(t.getLightDamage(self, t)))
+		self:project(tg, self.x, self.y, DamageType.DARKNESS, self:spellCrit(t.getDarknessDamage(self, t)))
 		game.level.map:particleEmitter(self.x, self.y, tg.radius, "shadow_flash", {radius=tg.radius, grids=grids, tx=self.x, ty=self.y})
 
 		game:playSoundNear(self, "talents/flame")
 		return true
 	end,
 	info = function(self, t)
-		return ([[A surge of twilight pulses from you, doing %0.2f light and %0.2f darkness damage in a radius of %d.
+		local lightdam = t.getLightDamage(self, t)
+		local darknessdam = t.getDarknessDamage(self, t)
+		return ([[A surge of twilight pulses from you, doing %0.2f light and %0.2f darkness damage.
 		It also regenerates both your negative and positive energies.
 		The damage will increase with the Magic stat]]):
-		format(
-			damDesc(self, DamageType.LIGHT, 10 + self:combatSpellpower(0.2) * self:getTalentLevel(t)),
-			damDesc(self, DamageType.DARKNESS, 10 + self:combatSpellpower(0.2) * self:getTalentLevel(t)),
-			self:getTalentRange(t)
-		)
+		format(damDesc(self, DamageType.LIGHT, lightdam),damDesc(self, DamageType.DARKNESS, darknessdam))
 	end,
 }
 
@@ -146,11 +148,13 @@ newTalent{
 	range = 10,
 	direct_hit = true,
 	requires_target = true,
+	getRadius = function(self, t) return 1 + math.floor(self:getTalentLevelRaw(t) / 3) end,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 28, 170) end,
 	action = function(self, t)
-		local tg = {type="ball", range=self:getTalentRange(t), radius=1 + math.floor(self:getTalentLevelRaw(t) / 3), friendlyfire=self:spellFriendlyFire(), talent=t}
+		local tg = {type="ball", range=self:getTalentRange(t), radius=t.getRadius(self, t), friendlyfire=self:spellFriendlyFire(), talent=t}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		local grids = self:project(tg, x, y, DamageType.DARKSTUN, self:spellCrit(self:combatTalentSpellDamage(t, 28, 170)))
+		local grids = self:project(tg, x, y, DamageType.DARKSTUN, self:spellCrit(t.getDamage(self, t)))
 
 		local _ _, x, y = self:canProject(tg, x, y)
 		game.level.map:particleEmitter(x, y, tg.radius, "shadow_flash", {radius=tg.radius, grids=grids, tx=x, ty=y})
@@ -158,8 +162,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local radius = t.getRadius(self, t)
+		local damage = t.getDamage(self, t)
 		return ([[A star falls into area of radius %d, stunning all for 4 turns and doing %0.2f darkness damage.
-		The damage will increase with the Magic stat
-		]]):format(1 + math.floor(self:getTalentLevelRaw(t) / 3), damDesc(self, DamageType.DARKNESS, self:combatTalentSpellDamage(t, 28, 170)))
+		The damage will increase with the Magic stat.]]):
+		format(radius, damDesc(self, DamageType.DARKNESS, damage))
    end,
    }
diff --git a/game/modules/tome/data/talents/divine/sun.lua b/game/modules/tome/data/talents/divine/sun.lua
index a1bcaf1b2517914b477f4658dea7fe6c9379b4bb..0b552c6a3a0db136474c82898c2e72c8542451a5 100644
--- a/game/modules/tome/data/talents/divine/sun.lua
+++ b/game/modules/tome/data/talents/divine/sun.lua
@@ -32,17 +32,19 @@ newTalent{
 	direct_hit = true,
 	reflectable = true,
 	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 6, 160) end,
+	getDamageOnSpot = function(self, t) return self:combatTalentSpellDamage(t, 6, 80) 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
-		self:project(tg, x, y, DamageType.LIGHT, self:spellCrit(self:combatTalentSpellDamage(t, 6, 160)), {type="light"})
+		self:project(tg, x, y, DamageType.LIGHT, self:spellCrit(t.getDamage(self, t)), {type="light"})
 
 		local _ _, x, y = self:canProject(tg, x, y)
 		-- Add a lasting map effect
 		game.level.map:addEffect(self,
 			x, y, 4,
-			DamageType.LIGHT, self:combatTalentSpellDamage(t, 6, 80),
+			DamageType.LIGHT, t.getDamageOnSpot(self, t),
 			0,
 			5, nil,
 			{type="light_zone"},
@@ -53,8 +55,11 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Calls the power of the Sun into a searing lance doing %0.2f damage and leaving a spot on the ground for 4 turns doing %0.2f damage.
-		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 6, 160)), self:combatTalentSpellDamage(t, 6, 80))
+		local damage = t.getDamage(self, t)
+		local damageonspot = t.getDamageOnSpot(self, t)
+		return ([[Calls the power of the Sun into a searing lance doing %0.2f damage and leaving a spot on the ground for 4 turns doing %0.2f light damage.
+		The damage will increase with the Magic stat.]]):
+		format(damDesc(self, DamageType.LIGHT, damage), damageonspot)
 	end,
 }
 
@@ -71,22 +76,26 @@ newTalent{
 	},
 	range = 6,
 	direct_hit = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 4, 80) end,
+	getRadius = function(self, t) return 2 + self:getTalentLevel(t) / 2 end,
 	action = function(self, t)
-		local tg = {type="ball", range=0, friendlyfire=true, radius=2 + self:getTalentLevel(t) / 2, talent=t}
+		local tg = {type="ball", range=0, friendlyfire=true, radius=t.getRadius(self, t), talent=t}
 		self:project(tg, self.x, self.y, DamageType.LITE, 1)
 		tg.friendlyfire = false
 		local grids = self:project(tg, self.x, self.y, DamageType.BLIND, 3 + self:getTalentLevel(t))
 		if self:getTalentLevel(t) >= 3 then
-			self:project(tg, self.x, self.y, DamageType.LIGHT, self:combatTalentSpellDamage(t, 4, 80))
+			self:project(tg, self.x, self.y, DamageType.LIGHT, t.getDamage(self, t))
 		end
 		game.level.map:particleEmitter(self.x, self.y, tg.radius, "sunburst", {radius=tg.radius, grids=grids, tx=self.x, ty=self.y, max_alpha=80})
 		game:playSoundNear(self, "talents/flame")
 		return true
 	end,
 	info = function(self, t)
-		return ([[Invokes a radius %d Sun flare, blinding your foes for %d turns and lighting up your immediate area.
+		local radius = t.getRadius(self, t)
+		local damage = t.getDamage(self, t)
+		return ([[Invokes Sun flare with radius of %d, blinding your foes for %d turns and lighting up your immediate area.
 		At level 3 it will start dealing %0.2f light damage.
-		The damage will increase with the Magic stat]]):
+		The damage will increase with the Magic stat.]]):
 		format(2 + self:getTalentLevel(t) / 2, 3 + self:getTalentLevel(t),damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 4, 80)))
    end,
 }
@@ -105,11 +114,12 @@ newTalent{
 	range = 10,
 	direct_hit = true,
 	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 10, 200) end,
 	action = function(self, t)
 		local tg = {type="beam", range=self:getTalentRange(t), talent=t}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		self:project(tg, x, y, DamageType.FIRE, self:spellCrit(self:combatTalentSpellDamage(t, 10, 200)))
+		self:project(tg, x, y, DamageType.FIRE, self:spellCrit(t.getDamage(self, t)))
 		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)), "light_beam", {tx=x-self.x, ty=y-self.y})
 
@@ -117,9 +127,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDamage(self, t)
 		return ([[Fire a beam of Sun flames at your foes, burning all those in line for %0.2f fire damage.
-		The damage will increase with the Magic stat]]):
-		format(damDesc(self, DamageType.FIRE, self:combatTalentSpellDamage(t, 10, 200)))
+		The damage will increase with the Magic stat.]]):
+		format(damDesc(self, DamageType.FIRE, damage))
 	end,
 }
 
@@ -136,9 +147,10 @@ newTalent{
 	},
 	range = 3,
 	direct_hit = true,
+	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 10, 160) end,
 	action = function(self, t)
 		local tg = {type="ball", range=0, radius=3, friendlyfire=false, talent=t}
-		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(self:combatTalentSpellDamage(t, 10, 160)))
+		local grids = self:project(tg, self.x, self.y, DamageType.LIGHT, self:spellCrit(t.getDamage(self, t)))
 
 		game.level.map:particleEmitter(self.x, self.y, tg.radius, "sunburst", {radius=tg.radius, grids=grids, tx=self.x, ty=self.y})
 
@@ -146,7 +158,8 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local damage = t.getDamage(self, t)
 		return ([[Conjures a furious burst of Sunlight, dealing %0.2f light damage to all those around you in a radius of 3.
-		The damage will increase with the Magic stat]]):format(damDesc(self, DamageType.LIGHT, self:combatTalentSpellDamage(t, 10, 160)))
+		The damage will increase with the Magic stat.]]):format(damDesc(self, DamageType.LIGHT, damage))
 	end,
 }
diff --git a/game/modules/tome/data/talents/divine/twilight.lua b/game/modules/tome/data/talents/divine/twilight.lua
index 6c0e47c29336d8e85b27a59d4d0f072d7d3f530b..045b44aa27bb3e6712e917189e0ae1df6514bb80 100644
--- a/game/modules/tome/data/talents/divine/twilight.lua
+++ b/game/modules/tome/data/talents/divine/twilight.lua
@@ -30,19 +30,21 @@ newTalent{
 		BUFF = 10,
 	},
 	range = 20,
+	getNegativeGain = function(self, t) return 20 + self:getTalentLevel(t) * self:getCun(40) end,
 	action = function(self, t)
 		if self:isTalentActive(self.T_DARKEST_LIGHT) then
 			game.logPlayer(self, "You can't use Twilight while Darkest Light is active.")
 			return
 		end
-		self:incNegative(20 + self:getTalentLevel(t) * self:getCun(40))
+		self:incNegative(t.getNegativeGain(self, t))
 		game:playSoundNear(self, "talents/spell_generic")
 		return true
 	end,
 	info = function(self, t)
+		local neggain = t.getNegativeGain(self, t)
 		return ([[You stand between the darkness and the light, allowing you to convert 15 positive energy into %d negative energy.
 		The effect will increase with the Cunning stat.]]):
-		format(20 + self:getTalentLevel(t) * self:getCun(40))
+		format(neggain)
 	end,
 }
 
@@ -159,16 +161,19 @@ newTalent{
 	range = 3,
 	direct_hit = true,
 	requires_target = true,
+	getConfuseDuration = function(self, t) return math.floor(self:getTalentLevel(t) + self:getCun(5)) + 2 end,
+	getConfuseEfficency = function(self, t) return 50 + self:getTalentLevelRaw(t)*10 end,
 	action = function(self, t)
 		local tg = {type="ball", range=0, radius=self:getTalentRange(t), talent=t, friendlyfire=false}
 		self:project(tg, self.x, self.y, DamageType.CONFUSION, {
-			dur = math.floor(self:getTalentLevel(t) + self:getCun(5)) + 2,
-			dam = 50 + self:getTalentLevelRaw(t)*10
+			dur = t.getConfuseDuration(self, t),
+			dam = t.getConfuseEfficency(self, t)
 		})
 		game:playSoundNear(self, "talents/flame")
 		return true
 	end,
 	info = function(self, t)
+		local duration = t.getConfuseDuration(self, t)
 		return ([[Let out a mental cry that shatters the will of your targets, confusing them for %d turns.
 		The duration will improve with the Cunning stat.]]):
 		format(math.floor(self:getTalentLevel(t) + self:getCun(5)) + 2)
@@ -189,6 +194,7 @@ newTalent{
 	requires_target = true,
 	range = 10,
 	no_npc_use = true,
+	getDuration = function(self, t) return math.ceil(self:getTalentLevel(t)+self:getCun(10)) + 3 end,
 	action = function(self, t)
 		local tg = {type="bolt", range=self:getTalentRange(t), talent=t}
 		local tx, ty, target = self:getTarget(tg)
@@ -220,7 +226,7 @@ newTalent{
 			no_drops = true,
 			faction = self.faction,
 			summoner = self, summoner_gain_exp=true,
-			summon_time = math.ceil(self:getTalentLevel(t)+self:getCun(10)) + 3,
+			summon_time = t.getDuration(self, t),
 			ai_target = {actor=target},
 			ai = "summoned", ai_real = target.ai,
 			resists = { all = modifier, [DamageType.DARKNESS] = 50, [DamageType.LIGHT] = - 50, },
@@ -246,6 +252,7 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
+		local duration = t.getDuration(self, t)
 		local allowed = 2 + math.ceil(self:getTalentLevelRaw(t) / 2 )
 		if allowed < 4 then
 			size = "medium"
@@ -254,8 +261,9 @@ newTalent{
 		else
 			size = "huge"
 		end
-		return ([[Creates a shadowy copy of a target up to size %s. The copy will attack its progenitor immediately.
-		It stays for %d turns and its duration, life, and resistances scale with the Cunning stat.]]):format(size, math.ceil(self:getTalentLevel(t)+self:getCun(10)) + 3)
+		return ([[Creates a shadowy copy of a target up to %s size. The copy will attack its progenitor immediately.
+		It stays for %d turns and its duration, life and resistances scale with the Cunning stat.]]):
+		format(size, duration)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/spells/water.lua b/game/modules/tome/data/talents/spells/water.lua
index 12bb3c086da44789070d081ecc16ff67534e89a2..2330d612ab0de42f1be81ff9200a15060ea6353f 100644
--- a/game/modules/tome/data/talents/spells/water.lua
+++ b/game/modules/tome/data/talents/spells/water.lua
@@ -34,7 +34,7 @@ newTalent{
 	getDamage = function(self, t) return self:combatTalentSpellDamage(t, 4, 50) end,
 	getDuration = function(self, t) return self:getTalentLevel(t) + 2 end,
 	action = function(self, t)
-		local tg = {type="ball", range=self:getTalentRange(t), radius=radius}
+		local tg = {type="ball", range=self:getTalentRange(t), radius=3}
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
 		local _ _, x, y = self:canProject(tg, x, y)