From f40551034fbb22fcc53a238187f485ae81246e74 Mon Sep 17 00:00:00 2001
From: DarkGod <darkgod@net-core.org>
Date: Mon, 26 May 2014 12:23:58 +0200
Subject: [PATCH] psi scaling

---
 game/modules/tome/class/interface/Combat.lua  |   2 +-
 .../talents/psionic/augmented-striking.lua    |  18 +--
 .../data/talents/psionic/charged-mastery.lua  |   7 +-
 .../tome/data/talents/psionic/projection.lua  |  30 ++---
 .../data/talents/psionic/psi-fighting.lua     |  35 ++---
 .../data/talents/psionic/thermal-mastery.lua  |  34 +++--
 .../tome/data/talents/psionic/voracity.lua    | 127 +++++++++---------
 .../tome/data/talents/techniques/thuggery.lua |  11 +-
 .../tome/data/timed_effects/mental.lua        |   8 +-
 9 files changed, 143 insertions(+), 129 deletions(-)

diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index 6c7e25f1bb..0a8f578986 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -1681,8 +1681,8 @@ function _M:physicalCrit(dam, weapon, target, atk, def, add_chance, crit_power_a
 
 	if self:attr("stealth") and self:knowTalent(self.T_SHADOWSTRIKE) and not target:canSee(self) then -- bug fix
 		chance = 100
-		crit_power_add = crit_power_add + self:callTalent(self.T_SHADOWSTRIKE,"getMultiplier")
 		self.turn_procs.shadowstrike_crit = self:callTalent(self.T_SHADOWSTRIKE,"getMultiplier")
+		crit_power_add = crit_power_add + self.turn_procs.shadowstrike_crit 
 	end
 
 	if self:isAccuracyEffect(weapon, "axe") then
diff --git a/game/modules/tome/data/talents/psionic/augmented-striking.lua b/game/modules/tome/data/talents/psionic/augmented-striking.lua
index 7808013602..ad316d4887 100644
--- a/game/modules/tome/data/talents/psionic/augmented-striking.lua
+++ b/game/modules/tome/data/talents/psionic/augmented-striking.lua
@@ -17,7 +17,6 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
-
 newTalent{
 	name = "Kinetic Strike",
 	type = {"psionic/augmented-striking", 1},
@@ -71,8 +70,8 @@ newTalent{
 	end,
 	info = function(self, t)
 		return ([[Focus kinetic energy and strike an enemy for %d%% weapon damage as physical.
-		They will then be thrown back by the force of the hit, taking an extra %0.2f physical damage if they hit a wall, where they will be pinned for 4 turns.
-		The knockback damage will scale with your mindpower.]]):
+		They will then be thrown back by the force of the hit, taking an extra %0.1f Physical damage if they hit a wall, where they will be pinned for 4 turns.
+		The knockback damage will scale with your Mindpower.]]):
 		format(100 * self:combatTalentWeaponDamage(t, 0.5, 2.0), damDesc(self, DamageType.PHYSICAL, t.getDam(self, t)))
 	end,
 }
@@ -119,8 +118,8 @@ newTalent{
 	end,
 	info = function(self, t)
 		return ([[Focus thermal energy and strike an enemy for %d%% weapon damage as cold.
-		A burst of cold will then engulf them, doing an extra %0.2f cold damage and also freeze them for 4 turns.
-		The cold burst damage will scale with your mindpower.]]):
+		A burst of cold will then engulf them, doing an extra %0.1f Cold damage and also freeze them for 4 turns.
+		The cold burst damage will scale with your Mindpower.]]):
 		format(100 * self:combatTalentWeaponDamage(t, 0.5, 2.0), damDesc(self, DamageType.COLD, t.getDam(self, t)))
 	end,
 }
@@ -212,8 +211,8 @@ newTalent{
 	end,
 	info = function(self, t)
 		return ([[Focus charged energy and strike an enemy for %d%% weapon damage as lightning.
-		Energy will then discharge from your weapon, doing an extra %0.2f lightning damage and blinding them for 4 turns.
-		The discharge damage will scale with your mindpower.]]):
+		Energy will then discharge from your weapon, doing an extra %0.1f Lightning damage and blinding them for 4 turns.
+		The discharge damage will scale with your Mindpower.]]):
 		format(100 * self:combatTalentWeaponDamage(t, 0.5, 2.0), damDesc(self, DamageType.LIGHTNING, t.getDam(self, t)))
 	end,
 }
@@ -224,11 +223,12 @@ newTalent{
 	mode = "passive",
 	points = 5,
 	require = psi_wil_req4,
+	getPsiRecover = function(self, t) return self:combatTalentScale(t, 1, 3) end,
 	passives = function(self, t, p)
-		self:talentTemporaryValue(p, "psi_regen_on_hit", self:getTalentLevel(t))
+		self:talentTemporaryValue(p, "psi_regen_on_hit", t.getPsiRecover(self, t))
 	end,
 	info = function(self, t)
-		return ([[Siphon excess energy from each weapon hit you land, gaining %d psi per hit.]]):format(self:getTalentLevel(t))
+		return ([[Siphon excess energy from each weapon hit you land, gaining %0.1f psi per hit.]]):format(t.getPsiRecover(self, t))
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/psionic/charged-mastery.lua b/game/modules/tome/data/talents/psionic/charged-mastery.lua
index 3becd15100..b16c6e0950 100644
--- a/game/modules/tome/data/talents/psionic/charged-mastery.lua
+++ b/game/modules/tome/data/talents/psionic/charged-mastery.lua
@@ -27,9 +27,10 @@ newTalent{
 	tactical = { BUFF = 3 },
 	getPower = function(self, t) return self:combatTalentMindDamage(t, 10, 30) end,
 	getPenetration = function(self, t) return self:combatLimit(self:combatTalentMindDamage(t, 10, 20), 100, 4.2, 4.2, 13.4, 13.4) end, -- Limit < 100%
+	getConfuse = function(self, t) return self:combatTalentLimit(t, 50, 15, 35) end, --Limit < 50%
 	getDuration = function(self, t) return math.floor(self:combatTalentLimit(t, 30, 5, 10)) end, --Limit < 30
 	action = function(self, t)
-		self:setEffect(self.EFF_TRANSCENDENT_ELECTROKINESIS, t.getDuration(self, t), {power=t.getPower(self, t), penetration = t.getPenetration(self, t)})
+		self:setEffect(self.EFF_TRANSCENDENT_ELECTROKINESIS, t.getDuration(self, t), {power=t.getPower(self, t), penetration = t.getPenetration(self, t), confuse=t.getConfuse(self, t)})
 		self:removeEffect(self.EFF_TRANSCENDENT_PYROKINESIS)
 		self:removeEffect(self.EFF_TRANSCENDENT_TELEKINESIS)
 		self:alterTalentCoolingdown(self.T_CHARGED_SHIELD, -1000)
@@ -46,10 +47,10 @@ newTalent{
 		Charged Aura will either increase in radius to 2, or apply its damage bonus to all of your weapons, whichever is applicable.
 		Your Charged Shield will have 100%% absorption efficiency and will absorb twice the normal amount of damage.
 		Brainstorm will also inflict blindness.
-		Charged Leech will also inflict confusion.
+		Charge Leech will also inflict confusion (%d%% effect).
 		Charged Strike will have its secondary lightning/blind burst chain to up to 3 targets in a radius of 3.
 		The damage bonus and resistance penetration scale with your Mindpower.
-		Only one Transcendent talent may be in effect at a time.]]):format(t.getDuration(self, t), t.getPower(self, t), t.getPenetration(self, t))
+		Only one Transcendent talent may be in effect at a time.]]):format(t.getDuration(self, t), t.getPower(self, t), t.getPenetration(self, t), t.getConfuse(self, t))
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/psionic/projection.lua b/game/modules/tome/data/talents/psionic/projection.lua
index f1e1ea505d..dd93752e85 100644
--- a/game/modules/tome/data/talents/psionic/projection.lua
+++ b/game/modules/tome/data/talents/psionic/projection.lua
@@ -172,11 +172,11 @@ newTalent{
 		local mast = aura_mastery(self, t)
 		local spikecost = t.getSpikeCost(self, t)
 		return ([[Fills the air around you with reactive currents of force.
-		If you have a gem or mindstar in your psionically wielded slot, this will do %0.2f physical damage to all who approach. 
-		All damage done by the aura will drain one point of energy per %0.2f points of damage dealt.
-		If you have a conventional weapon in your psionically wielded slot, this will add %0.2f physical damage to its hits.
+		If you have a gem or mindstar in your psionically wielded slot, this will do %0.1f Physical damage to all who approach. 
+		All damage done by the aura will drain one point of energy per %0.1f points of damage dealt.
+		If you have a conventional weapon in your psionically wielded slot, this will add %0.1f Physical damage to its hits.
 		When deactivated, if you have at least %d energy, a massive spike of kinetic energy is released as a range %d beam, smashing targets for up to %d physical damage and sending them flying.
-		#{bold}#Activating the aura takes no turn but de-activating it does.#{normal}#
+		#{bold}#Activating the aura takes no time but de-activating it does.#{normal}#
 		To turn off an aura without spiking it, deactivate it and target yourself.  The damage will improve with your Mindpower.]]):
 		format(damDesc(self, DamageType.PHYSICAL, dam), mast, damDesc(self, DamageType.PHYSICAL, dam), spikecost, t.getSpikedRange(self, t),
 		damDesc(self, DamageType.PHYSICAL, spikedam))
@@ -289,11 +289,11 @@ newTalent{
 		local mast = aura_mastery(self, t)
 		local spikecost = t.getSpikeCost(self, t)
 		return ([[Fills the air around you with reactive currents of furnace-like heat.
-		If you have a gem or mindstar in your psionically wielded slot, this will do %0.2f fire damage to all who approach. 
-		All damage done by the aura will drain one point of energy per %0.2f points of damage dealt.
-		If you have a conventional weapon in your psionically wielded slot, this will add %0.2f fire damage to its hits.
+		If you have a gem or mindstar in your psionically wielded slot, this will do %0.1f Fire damage to all who approach. 
+		All damage done by the aura will drain one point of energy per %0.1f points of damage dealt.
+		If you have a conventional weapon in your psionically wielded slot, this will add %0.1f Fire damage to its hits.
 		When deactivated, if you have at least %d energy, a massive spike of thermal energy is released as a conical blast (radius %d) of superheated air. Anybody caught in it will suffer up to %d fire damage over several turns.
-		#{bold}#Activating the aura takes no turn but de-activating it does.#{normal}#
+		#{bold}#Activating the aura takes no time but de-activating it does.#{normal}#
 		To turn off an aura without spiking it, deactivate it and target yourself.  The damage will improve with your Mindpower.]]):
 		format(damDesc(self, DamageType.FIRE, dam), mast, damDesc(self, DamageType.FIRE, dam), spikecost, rad,
 		damDesc(self, DamageType.FIRE, spikedam))
@@ -450,11 +450,11 @@ newTalent{
 		local spikecost = t.getSpikeCost(self, t)
 		local nb = t.getNumSpikeTargets(self, t)
 		return ([[Fills the air around you with crackling energy.
-		If you have a gem or mindstar in your psionically wielded slot, this will do %0.2f lightning damage to all who approach. 
-		All damage done by the aura will drain one point of energy per %0.2f points of damage dealt.
-		If you have a conventional weapon in your psionically wielded slot, this will add %0.2f lightning damage to its hits.
-		When deactivated, if you have at least %d energy, a massive spike of electrical energy jumps between up to %d nearby targets, doing up to %d lightning damage to each with a 50%% chance of dazing them.
-		#{bold}#Activating the aura takes no turn but de-activating it does.#{normal}#
+		If you have a gem or mindstar in your psionically wielded slot, this will do %0.1f Lightning damage to all who approach. 
+		All damage done by the aura will drain one point of energy per %0.1f points of damage dealt.
+		If you have a conventional weapon in your psionically wielded slot, this will add %0.1f Lightning damage to its hits.
+		When deactivated, if you have at least %d energy, a massive spike of electrical energy jumps between up to %d nearby targets, doing up to %0.1f Lightning damage to each with a 50%% chance of dazing them.
+		#{bold}#Activating the aura takes no time but de-activating it does.#{normal}#
 		To turn off an aura without spiking it, deactivate it and target yourself.]]):
 		format(damDesc(self, DamageType.LIGHTNING, dam), mast, damDesc(self, DamageType.LIGHTNING, dam), spikecost, nb, damDesc(self, DamageType.LIGHTNING, spikedam))
 	end,
@@ -484,8 +484,8 @@ newTalent{
 		local dur = t.duration(self,t)
 		return ([[Overcharge your psionic focus with energy for %d turns, producing a different effect depending on what it is.
 		A telekinetically wielded weapon enters a frenzy, striking up to %d targets every turn, also increases the radius by %d.
-		A mindstar will attempt to suck in all enemies in range.
-		A gem will fire an energy bolt at a random enemy in range 6, each turn for %0.2f damage. The type is determined by the colour of the gem. Damage scales with mindpower.]]):
+		A mindstar will attempt to pull in all enemies within its normal range.
+		A gem will fire an energy bolt at a random enemy in range 6, each turn for %0.1f damage. The type is determined by the colour of the gem. Damage scales with Mindpower.]]):
 		format(dur, targets, targets, t.getDamage(self,t))
 	end,
 }
diff --git a/game/modules/tome/data/talents/psionic/psi-fighting.lua b/game/modules/tome/data/talents/psionic/psi-fighting.lua
index 3eccf620a1..893fe4671a 100644
--- a/game/modules/tome/data/talents/psionic/psi-fighting.lua
+++ b/game/modules/tome/data/talents/psionic/psi-fighting.lua
@@ -28,7 +28,7 @@ newTalent{
 	range = 1,
 	requires_target = true,
 	tactical = { ATTACK = { PHYSICAL = 2 } },
-	duration = function(self, t) return math.floor(self:combatTalentScale(t, 2, 6, "log")) end,
+	duration = function(self, t) return math.floor(self:combatTalentScale(t, 2, 6)) end,
 	action = function(self, t)
 		local weapon = self:getInven("MAINHAND") and self:getInven("MAINHAND")[1]
 		if type(weapon) == "boolean" then weapon = nil end
@@ -41,7 +41,7 @@ newTalent{
 		if not x or not y or not target then return nil end
 		if core.fov.distance(self.x, self.y, x, y) > 1 then return nil end
 		self:attr("use_psi_combat", 1)
-		local speed, hit = self:attackTarget(target, nil, self:combatTalentWeaponDamage(t, 0.9, 1.5))
+		local hit = self:attackTarget(target, nil, self:combatTalentWeaponDamage(t, 0.9, 1.5))
 		if self:getInven(self.INVEN_PSIONIC_FOCUS) then
 			for i, o in ipairs(self:getInven(self.INVEN_PSIONIC_FOCUS)) do
 				if o.combat and not o.archery then
@@ -56,10 +56,10 @@ newTalent{
 		return true
 	end,
 	info = function(self, t)
-		return ([[Gather your will, and brutally smash the target with your mainhand weapon and then your telekinetically weilded weapon, doing %d%% weapon damage. 
+		return ([[Gather your will, and brutally smash the target with your mainhand weapon and then your telekinetically wielded weapon, doing %d%% weapon damage. 
 		If your mainhand weapon hits, you will also stun the target for %d turns.
 		This attack uses your Willpower and Cunning instead of Strength and Dexterity to determine Accuracy and damage.
-		Any active Aura damage bonusses will extend to your main weapons for this attack.]]):
+		Any active Aura damage bonusses will extend to the weapons used for this attack.]]):
 		format(100 * self:combatTalentWeaponDamage(t, 0.9, 1.5), t.duration(self,t))
 	end,
 }
@@ -109,14 +109,17 @@ newTalent{
 	psi = 15,
 	no_energy = true,
 	tactical = { BUFF = 2 },
+	getWeaponDamage = function(self, t) return self:combatTalentWeaponDamage(t, 0.75, 1.1) end,
 	action = function(self, t)
 		self:setEffect(self.EFF_WEAPON_WARDING, 1, {})
 		return true
 	end,
 	info = function(self, t)
-		return ([[Focus your telekinetically-wielded weapon to deflect melee attacks for one turn. You fully block the next melee attack used against you and strike the attacker with your telekinetically-wielded weapon for %d%% weapon damage. 
-		At talent level 3 you also disarm the attacker for 3 turns.]]):
-		format(100 * self:combatTalentWeaponDamage(t, 0.75, 1.1))
+		return ([[Assume a defensive mental state.
+		For one turn, you will fully block the next melee attack used against you with your telekinetically-wielded weapon and then strike the attacker with it for %d%% weapon damage. 
+		At talent level 3 you will also disarm the attacker for 3 turns.
+		This requires both a mainhand and a telekinetically-wielded weapon.]]):
+		format(100 * t.getWeaponDamage(self, t))
 	end,
 }
 
@@ -131,9 +134,8 @@ newTalent{
 	range = 3,
 	requires_target = true,
 	tactical = { ATTACK = { PHYSICAL = 2 } },
-	getDamage = function (self, t)
-		return math.floor(self:combatTalentMindDamage(t, 12, 340))
-	end,
+	getDamage = function (self, t) return math.floor(self:combatTalentMindDamage(t, 12, 340)) end,
+	getWeaponDamage = function(self, t) return self:combatTalentWeaponDamage(t, 1.5, 2.6) end,
 	action = function(self, t)
 		local weapon = self:getInven(self.INVEN_PSIONIC_FOCUS) and self:getInven(self.INVEN_PSIONIC_FOCUS)[1]
 		if type(weapon) == "boolean" then weapon = nil end
@@ -145,17 +147,18 @@ newTalent{
 		local x, y, target = self:getTarget(tg)
 		if not x or not y or not target then return nil end
 		if core.fov.distance(self.x, self.y, x, y) > 3 then return nil end
-		local speed, hit = self:attackTargetWith(target, weapon.combat, nil, self:combatTalentWeaponDamage(t, 1.5, 2.6))
-		if hit and target:canBe("bleed") then
+		local speed, hit = self:attackTargetWith(target, weapon.combat, nil, t.getWeaponDamage(self, t))
+		if hit and target:canBe("cut") then
 			target:setEffect(target.EFF_CUT, 4, {power=t.getDamage(self,t)/4, apply_power=self:combatMindpower()})
 		end
 		return true
 	end,
 	info = function(self, t)
-		return ([[Gather your will and thrust your telekinetically-wielded weapon into your target with such force that it impales it dealing %d%% weapon damage, then suddenly rip it out causing your target to bleed for %0.2f physical damage over four turns. 
-		This attack uses your Willpower and Cunning instead of Strength and Dexterity to determine Accuracy and damage.
-		Bleeding damage scales with Mindpower.]]):
-		format(100 * self:combatTalentWeaponDamage(t, 1.5, 2.6), damDesc(self, DamageType.PHYSICAL, t.getDamage(self,t)))
+		return ([[Focus your will into a powerful thrust of your telekinetically-wielded weapon to impale your target and then viciously rip it free.
+		This deals %d%% weapon damage and then causes the victim to bleed for %0.1f Physical damage over four turns. 
+		Your Willpower and Cunning are used instead of Strength and Dexterity to determine Accuracy and damage.
+		The bleeding damage increases with your Mindpower.]]):
+		format(100 * t.getWeaponDamage(self, t), damDesc(self, DamageType.PHYSICAL, t.getDamage(self,t)))
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/psionic/thermal-mastery.lua b/game/modules/tome/data/talents/psionic/thermal-mastery.lua
index 68cabddd91..508e982724 100644
--- a/game/modules/tome/data/talents/psionic/thermal-mastery.lua
+++ b/game/modules/tome/data/talents/psionic/thermal-mastery.lua
@@ -26,10 +26,11 @@ newTalent{
 	cooldown = 30,
 	tactical = { BUFF = 3 },
 	getPower = function(self, t) return self:combatTalentMindDamage(t, 10, 30) end,
+	getDamagePenalty = function(self, t) return self:combatTalentLimit(t, 100, 15, 50) end, --Limit < 100%
 	getPenetration = function(self, t) return self:combatLimit(self:combatTalentMindDamage(t, 10, 20), 100, 4.2, 4.2, 13.4, 13.4) end, -- Limit < 100%
 	getDuration = function(self, t) return math.floor(self:combatTalentLimit(t, 30, 5, 10)) end, --Limit < 30
 	action = function(self, t)
-		self:setEffect(self.EFF_TRANSCENDENT_PYROKINESIS, t.getDuration(self, t), {power=t.getPower(self, t), penetration=t.getPenetration(self, t)})
+		self:setEffect(self.EFF_TRANSCENDENT_PYROKINESIS, t.getDuration(self, t), {power=t.getPower(self, t), penetration=t.getPenetration(self, t), weaken=t.getDamagePenalty(self, t)})
 		self:removeEffect(self.EFF_TRANSCENDENT_TELEKINESIS)
 		self:removeEffect(self.EFF_TRANSCENDENT_ELECTROKINESIS)
 		self:alterTalentCoolingdown(self.T_THERMAL_SHIELD, -1000)
@@ -49,7 +50,7 @@ newTalent{
 		Thermal Leech will reduce enemy damage by %d%%.
 		Thermal Strike will have its secondary cold/freeze explode in radius 1.
 		The damage bonus and resistance penetration scale with your Mindpower.
-		Only one Transcendent talent may be in effect at a time.]]):format(t.getDuration(self, t), t.getPower(self, t), t.getPenetration(self, t), t.getPower(self, t))
+		Only one Transcendent talent may be in effect at a time.]]):format(t.getDuration(self, t), t.getPower(self, t), t.getPenetration(self, t), t.getDamagePenalty(self, t))
 	end,
 }
 
@@ -104,21 +105,30 @@ newTalent{
 	getDuration = function (self, t)
 		return math.floor(self:combatTalentMindDamage(t, 4, 8))
 	end,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 60) end,
+	getArmor = function(self, t) return self:combatTalentMindDamage(t, 10, 20) end,
 	requires_target = true,
-	target = function(self, t) return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t} end,
+	target = function(self, t) return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t, friendlyfire=false} end,
 	action = function(self, t)
-		local dur = t.getDuration(self, t)
 		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
+		local dur = t.getDuration(self, t)
+		local dam = t.getDamage(self, t)
+		local armor = t.getArmor(self, t)
 		self:project(tg, self.x, self.y, function(tx, ty)
 			local act = game.level.map(tx, ty, engine.Map.ACTOR)
 			if act then
-				if target:canBe("pin") and target:canBe("stun") and not target:attr("fly") and not target:attr("levitation") then
-					target:setEffect(target.EFF_FROZEN_FEET, dur, {apply_power=self:combatMindpower()})
+				local cold = DamageType:get("COLD").projector(self, tx, ty, DamageType.COLD, dam)
+				if act:canBe("pin") and act:canBe("stun") and not act:attr("fly") and not act:attr("levitation") then
+					act:setEffect(act.EFF_FROZEN_FEET, dur, {apply_power=self:combatMindpower()})
 				end
-				if target:canBe("disarm") then
-					target:setEffect(target.EFF_DISARMED, dur, {apply_power=self:combatMindpower()})
+				local fire = DamageType:get("FIRE").projector(self, tx, ty, DamageType.FIRE, dam)
+				if act:canBe("disarm") then
+					act:setEffect(act.EFF_DISARMED, dur, {apply_power=self:combatMindpower()})
+				end
+				if cold>0 and fire>0 then
+					act:setEffect(act.EFF_SUNDER_ARMOUR, dur, {power = armor})
 				end
 			end
 		end)
@@ -127,10 +137,12 @@ newTalent{
 	info = function(self, t)
 		local dur = t.getDuration(self, t)
 		local rad = self:getTalentRadius(t)
-		return ([[Transfer heat from a group (radius %d) of enemies bodies to their weapons, freezing them to the floor while forcing them to drop their too weapons.
-		Attempts to inflict Frozen Feet and Disarmed to target enemies for %d turns.
+		local dam = t.getDamage(self, t)
+		return ([[Within radius %d, transfer heat from a group of enemies bodies to their equipment, freezing them to the floor while the excess heat disables their weapons and armor.
+		Those afflicted will be dealt %0.1f Cold and %0.1f Fire damage, and be pinned (Frozen Feet) and disarmed for %d turns.
+		Targets suffering both types of damage will also have have their Armour and saves reduced by %d.
 		The chance to apply the effects and the duration increase with your Mindpower.]]):
-		format(rad, dur)
+		format(rad, damDesc(self, DamageType.COLD, dam), damDesc(self, DamageType.FIRE, dam), dur, t.getArmor(self, t))
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/psionic/voracity.lua b/game/modules/tome/data/talents/psionic/voracity.lua
index a8407bfab8..d0e379af15 100644
--- a/game/modules/tome/data/talents/psionic/voracity.lua
+++ b/game/modules/tome/data/talents/psionic/voracity.lua
@@ -34,19 +34,22 @@ newTalent{
 	target = function(self, t)
 		return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t}
 	end,
-	getLeech = function(self, t)
-		return self:combatTalentScale(t, 10, 27)
+	getLeech = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentScale(t, 10, 27)*math.max(0.5, (1.5-psi/self:getMaxPsi()))
 	end,
-	getDam = function(self, t)
-		return self:combatTalentMindDamage(t, 20, 200)
+	getDam = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentMindDamage(t, 20, 200)*math.max(0.5, (1.5-psi/self:getMaxPsi())) --this looks high
 	end,
-	getSlow = function(self, t)
-		return math.min(5 * self:getTalentLevel(t) + 15, 50)
+	getSlow = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentLimit(self:getTalentLevel(t)*math.max(0.5, (1.5-psi/self:getMaxPsi())), 0.50, 0.16, 0.20) -- Limit < 50%
 	end,
 	action = function(self, t)
-		local en = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local dam = t.getDam(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local slow = t.getSlow(self, t)/100 * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
+		local en = t.getLeech(self, t)
+		local dam = t.getDam(self, t)
+		local slow = t.getSlow(self, t)
 		local psi = en
 		local tg = self:getTalentTarget(t)
 		local trans = self:hasEffect(self.EFF_TRANSCENDENT_TELEKINESIS)
@@ -72,21 +75,14 @@ newTalent{
 	end,
 	info = function(self, t)
 		local range = self:getTalentRadius(t)
-		local slow = t.getSlow(self, t)
-		local dam = t.getDam(self, t)
-		local en = t.getLeech(self, t)
-		local cen = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local cdam = t.getDam(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local cslow = t.getSlow(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		return ([[You suck the kinetic energy out of your surroundings, slowing all targets in a radius of %d by %d%% (now %d%%) for four turns and draining %0.2f (now %0.2f) stamina from them.
-		For each target drained, you gain psi. The first target gives %d (now %d) psi and each additional one reduces the gain by 20%%.
-		The slow effect will improve with your Mindpower.
-		The strength of these effects also scales with your current psi. Ranging from -50%% at full psi to +50%% at 0 psi.]])
-		:format(range, slow, cslow, dam, cdam, en, cen)
+		return ([[You draw kinetic energy from your surroundings to replenish your Psi.
+		This will slow all targets within radius %d by %d%% (max %d%%) for four turns, draining %0.1f (max %0.1f) stamina from each.
+		You replenish %d (max %d) Psi from the first target, with each additional target restoring 20%% less than the one before it.
+		The strength of these effects increases as your Psi depletes.]])
+		:format(range, t.getSlow(self, t)*100, t.getSlow(self, t, 0)*100, t.getDam(self, t), t.getDam(self, t, 0), t.getLeech(self, t), t.getLeech(self, t, 0))
 	end,
 }
 
-
 newTalent{
 	name = "Thermal Leech",
 	type = {"psionic/voracity", 1},
@@ -102,17 +98,22 @@ newTalent{
 	target = function(self, t)
 		return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t}
 	end,
-	getLeech = function(self, t)
-		return self:combatTalentScale(t, 10, 27)
+	getLeech = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentScale(t, 10, 27)*math.max(0.5, (1.5-psi/self:getMaxPsi()))
+	end,
+	getDam = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentMindDamage(t, 20, 200)*math.max(0.5, (1.5-psi/self:getMaxPsi()))
 	end,
-	getDam = function(self, t)
-		return self:combatTalentMindDamage(t, 20, 200)
+	getDur = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return math.ceil(self:combatTalentScale(self:getTalentLevel(t)*math.max(0.5, (1.5-psi/self:getMaxPsi())), 1.3, 3.2))
 	end,
-	getDur = function(self, t) return math.ceil(self:combatTalentScale(t, 1.3, 3.2)) end, -- Duration
 	action = function(self, t)
-		local en = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local dam = self:mindCrit(t.getDam(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi()))
-		local dur = t.getDur(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
+		local en = t.getLeech(self, t)
+		local dam = self:mindCrit(t.getDam(self, t))
+		local dur = t.getDur(self, t)
 		local psi = en
 		local tg = self:getTalentTarget(t)
 		local trans = self:hasEffect(self.EFF_TRANSCENDENT_PYROKINESIS)
@@ -122,28 +123,21 @@ newTalent{
 				self:incPsi(psi)
 				psi = psi * 0.8
 				if trans then
-					act:setEffect(act.EFF_WEAKENED, 4, {power=en, apply_power=self:combatMindpower()})
+					act:setEffect(act.EFF_WEAKENED, 4, {power=trans.weaken, apply_power=self:combatMindpower()})
 				end
 			end
 			DamageType:get(DamageType.COLD).projector(self, tx, ty, DamageType.COLD, dam)
 			DamageType:get(DamageType.MINDFREEZE).projector(self, tx, ty, DamageType.MINDFREEZE, dur)
-			
 		end)
 		return true
 	end,
 	info = function(self, t)
 		local range = self:getTalentRadius(t)
-		local dam = damDesc(self, DamageType.COLD, t.getDam(self, t))
-		local dur = t.getDur(self, t)
-		local en = t.getLeech(self, t)
-		local cen = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local cdam = damDesc(self, DamageType.COLD, t.getDam(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi()))
-		local cdur = t.getDur(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		return ([[You leech the heat out of all targets in a radius of %d, freezing them for up to %d (now %d) turns and doing %0.2f (now %0.2f) cold damage. 
-		For each target drained, you gain psi. The first target gives %d (now %d) psi and each additional one reduces the gain by 20%%.
-		The damage will improve with your Mindpower.
-		The strength of these effects also scales with your current psi. Ranging from -50%% at full psi to +50%% at 0 psi.]]):
-		format(range, dur, cdur, dam, cdam, en, cen)
+		return ([[You draw thermal energy from your surroundings to replenish your Psi.
+		This will freeze all targets within radius %d for %d (max %d) turns, and deal %0.1f (max %0.1f) Cold damage.
+		You replenish %d (max %d) Psi from the first target, with each additional target restoring 20%% less than the one before it.
+		The damage and the strength of these effects increases as your Psi depletes.]])
+		:format(range, t.getDur(self, t), t.getDur(self, t, 0), damDesc(self, DamageType.COLD, t.getDam(self, t)), damDesc(self, DamageType.COLD, t.getDam(self, t, 0)), t.getLeech(self, t), t.getLeech(self, t, 0))
 	end,
 }
 
@@ -163,15 +157,21 @@ newTalent{
 	target = function(self, t)
 		return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false, talent=t}
 	end,
-	getLeech = function(self, t)
-		return self:combatTalentScale(t, 10, 27)
+	getLeech = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentScale(t, 10, 27)*math.max(0.5, (1.5-psi/self:getMaxPsi()))
 	end,
-	getDam = function(self, t)
-		return self:combatTalentMindDamage(t, 20, 200)
+	getDam = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentMindDamage(t, 20, 200)*math.max(0.5, (1.5-psi/self:getMaxPsi()))
+	end,
+	getDaze = function(self, t, psi)
+		local psi = psi or self:getPsi()
+		return self:combatTalentLimit(self:getTalentLevel(t)*math.max(0.5, (1.5-psi/self:getMaxPsi())), 100, 25, 50) -- Limit < 100%
 	end,
 	action = function(self, t)
-		local en = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local dam = self:mindCrit(t.getDam(self, t)) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
+		local en = t.getLeech(self, t)
+		local dam = self:mindCrit(t.getDam(self, t))
 		local tg = self:getTalentTarget(t)
 		local psi = en
 		local trans = self:hasEffect(self.EFF_TRANSCENDENT_ELECTROKINESIS)
@@ -181,11 +181,10 @@ newTalent{
 				self:incPsi(psi)
 				psi = psi * 0.8
 				if trans then
-					DamageType:get(DamageType.CONFUSION).projector(self, tx, ty, DamageType.CONFUSION, {power_check=self.combatMindpower, dam=en, dur=4})
+					DamageType:get(DamageType.CONFUSION).projector(self, tx, ty, DamageType.CONFUSION, {power_check=self.combatMindpower, dam=trans.confuse, dur=4})
 				end
 			end
-			DamageType:get(DamageType.LIGHTNING_DAZE).projector(self, tx, ty, DamageType.LIGHTNING_DAZE, {power_check=self:combatMindpower(), dam=dam})
-			
+			DamageType:get(DamageType.LIGHTNING_DAZE).projector(self, tx, ty, DamageType.LIGHTNING_DAZE, {power_check=self:combatMindpower(), dam=dam, daze = t.getDaze(self, t)})
 		end)
 		-- Lightning ball gets a special treatment to make it look neat
 		local sradius = (tg.radius + 0.5) * (engine.Map.tile_w + engine.Map.tile_h) / 2
@@ -197,21 +196,16 @@ newTalent{
 			local ty = self.y + math.floor(math.sin(a) * tg.radius)
 			game.level.map:particleEmitter(x, y, tg.radius, "lightning", {radius=tg.radius, grids=grids, tx=tx-self.x, ty=ty-self.y, nb_particles=25, life=8})
 		end
-
 		game:playSoundNear(self, "talents/lightning")
 		return true
 	end,
-	info = function(self, t)
+	info = function(self, t) -- could this use another effect?
 		local range = self:getTalentRadius(t)
-		local en = t.getLeech(self, t)
-		local dam = damDesc(self, DamageType.LIGHTNING, t.getDam(self, t))
-		local cen = t.getLeech(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi())
-		local cdam = damDesc(self, DamageType.LIGHTNING, t.getDam(self, t) * (0.5 + (self:getMaxPsi() - self:getPsi()) / self:getMaxPsi()))
-		return ([[You pull electric potential from all targets around you in a radius of %d, giving them a nasty shock in the process. Deals %0.2f (now %0.2f) damage lightning, and has a 25%% chance to daze. 
-		For each target drained, you gain psi. The first target gives %d (now %d) psi and each additional one reduces the gain by 20%%.
-		The damage will improve with your Mindpower.
-		The strength of these effects also scales with your current psi. Ranging from -50%% at full psi to +50%% at 0 psi.]]):
-		format(range, dam, cdam, en, cen)
+		return ([[You draw electical potential energy from your surroundings to replenish your Psi.
+		This deals %0.1f (max %0.1f) Lightning damage to all targets around you within radius %d, and has a %d%% (max %d%%) chance to daze them for 3 turns.
+		You replenish %d (max %d) Psi from the first target, with each additional target restoring 20%% less than the one before it.
+		The strength of these effects increases as your Psi depletes.]])
+		:format(t.getDam(self, t), t.getDam(self, t, 0), range, t.getDaze(self, t), t.getDaze(self, t, 0), t.getLeech(self, t), t.getLeech(self, t, 0))
 	end,
 }
 
@@ -221,13 +215,16 @@ newTalent{
 	mode = "passive",
 	points = 5,
 	require = psi_wil_req4,
+	getPsiRecover = function(self, t) return self:combatTalentScale(t, 1.5, 5, 0.75) end,
 	passives = function(self, t, p)
+		local recover = t.getPsiRecover(self, t)
 		self:talentTemporaryValue(p, "max_psi", self:getTalentLevel(t)*10)
-		self:talentTemporaryValue(p, "psi_per_kill", self:getTalentLevel(t))
-		self:talentTemporaryValue(p, "psi_on_crit", self:getTalentLevel(t) * 0.5)
+		self:talentTemporaryValue(p, "psi_per_kill", recover)
+		self:talentTemporaryValue(p, "psi_on_crit", recover*0.5)
 	end,
 	info = function(self, t)
-		return ([[Increases your maximum energy by %d. You also gain %d psi on kill and %0.1f psi per mind critical.]]):format(10 * self:getTalentLevel(t), self:getTalentLevel(t), self:getTalentLevel(t)/2)
+		local recover = t.getPsiRecover(self, t)
+		return ([[Increases your maximum energy by %d. You also gain %0.1f Psi for each kill and %0.1f Psi for each mind critical.]]):format(10 * self:getTalentLevel(t), recover, 0.5*recover)
 	end,
 }
 
diff --git a/game/modules/tome/data/talents/techniques/thuggery.lua b/game/modules/tome/data/talents/techniques/thuggery.lua
index b7ba3ce062..d41ddf25b0 100644
--- a/game/modules/tome/data/talents/techniques/thuggery.lua
+++ b/game/modules/tome/data/talents/techniques/thuggery.lua
@@ -29,6 +29,7 @@ newTalent{
 	require = techs_req1,
 	requires_target = true,
 	getDuration = function(self, t) return math.ceil(self:combatTalentScale(t, 3.2, 5.3)) end,
+	getConfusion = function(self, t) return self:combatStatLimit("dex", 50, 25, 45) end, --Limit < 50%
 	getDamage = function(self, t)
 		local o = self:getInven(self.INVEN_HEAD) and self:getInven(self.INVEN_HEAD)[1]
 
@@ -56,7 +57,7 @@ newTalent{
 
 		if hitted then
 			if target:canBe("confusion") then
-				target:setEffect(target.EFF_CONFUSED, t.getDuration(self, t), {power=30 + self:getDex(70), apply_power=self:combatAttack()})
+				target:setEffect(target.EFF_CONFUSED, t.getDuration(self, t), {power=t.getConfusion(self, t), apply_power=self:combatAttack()})
 			else
 				game.logSeen(target, "%s resists the headblow!", target.name:capitalize())
 			end
@@ -64,16 +65,16 @@ newTalent{
 				world:gainAchievement("HEADBANG", self, target)
 			end
 		end
-
 		return true
 	end,
 	info = function(self, t)
-		local dam = t.getDamage(self, t)
+		local dam = damDesc(self, DamageType.PHYSICAL, t.getDamage(self, t))
 		local duration = t.getDuration(self, t)
-		return ([[You smack your forehead against your enemy's head (or whatever sensitive part you can find), causing %0.2f physical damage. If the attack hits, the target is confused for %d turns.
+		return ([[You smack your forehead against your enemy's head (or whatever sensitive part you can find), causing %0.1f Physical damage.
+		If the attack hits, the target is confused (%d%% effect) for %d turns.
 		Damage done increases with the quality of your headgear, your Strength, and your physical damage bonuses.
 		Confusion power and chance increase with your Dexterity and Accuracy.]]):
-		format(dam, duration)
+		format(dam, t.getConfusion(self, t), duration)
 	end,
 }
 
diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua
index 902de2bac8..da91f24f65 100644
--- a/game/modules/tome/data/timed_effects/mental.lua
+++ b/game/modules/tome/data/timed_effects/mental.lua
@@ -3048,7 +3048,7 @@ newEffect{
 newEffect{
 	name = "WEAPON_WARDING", image = "talents/warding_weapon.png",
 	desc = "Weapon Warding",
-	long_desc = function(self, eff) return ("Block then next melee attack and retaliate."):format() end,
+	long_desc = function(self, eff) return ("Target is using %s telekinetically wielded weapon defensively and will block the next melee attack and retaliate."):format(string.his_her(self)) end,
 	type = "mental",
 	subtype = { tactic=true },
 	status = "beneficial",
@@ -3064,7 +3064,8 @@ newEffect{
 			local t = self:getTalentFromId(self.T_WARDING_WEAPON)
 			for i, o in ipairs(self:getInven(self.INVEN_PSIONIC_FOCUS)) do
 				if o.combat and not o.archery then
-					self:attackTargetWith(target, o.combat, nil, self:combatTalentWeaponDamage(t, 0.75, 1.1))
+					self:logCombat(target, "#CRIMSON##Source# blocks #Target#'s attack and retaliates with %s telekinetically wielded weapon!#LAST#", string.his_her(self))
+					self:attackTargetWith(target, o.combat, nil, t.getWeaponDamage(self, t))
 				end
 			end
 			if self:getTalentLevelRaw(t) >= 3 and target:canBe("disarmed") then
@@ -3172,7 +3173,7 @@ newEffect{
 	type = "mental",
 	subtype = { fire=true, cold=true },
 	status = "beneficial",
-	parameters = { power=10, penetration = 0 },
+	parameters = { power=10, penetration = 0, weaken = 0},
 	activate = function(self, eff)
 		self:effectTemporaryValue(eff, "inc_damage", {[DamageType.FIRE]=eff.power, [DamageType.COLD]=eff.power})
 		self:effectTemporaryValue(eff, "resists_pen", {[DamageType.FIRE]=eff.penetration, [DamageType.COLD]=eff.penetration})
@@ -3205,7 +3206,6 @@ newEffect{
 	end,
 }
 
-
 newEffect{
 	name = "PSI_DAMAGE_SHIELD", image = "talents/barrier.png",
 	desc = "Psionic Damage Shield",
-- 
GitLab