diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index d088b22fbc54396ab682fb40edb0b67d26d559e7..e43de959bf04faac3a70f50bc860cf930adc9b83 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -73,7 +73,7 @@ _M.temporary_values_conf.global_speed_add = "newest"
 _M.temporary_values_conf.movement_speed = "mult0"
 _M.temporary_values_conf.combat_physspeed = "mult0"
 _M.temporary_values_conf.combat_spellspeed = "mult0"
-_M.temporary_values_conf.combat_mentalspeed = "mult0"
+_M.temporary_values_conf.combat_mindspeed = "mult0"
 
 -- Damage cap takes the lowest
 _M.temporary_values_conf.flat_damage_cap = "lowest"
@@ -97,7 +97,7 @@ function _M:init(t, no_default)
 	self.combat_physcrit = 0
 	self.combat_physspeed = 1
 	self.combat_spellspeed = 1
-	self.combat_mentalspeed = 1
+	self.combat_mindspeed = 1
 	self.combat_spellcrit = 0
 	self.combat_spellpower = 0
 	self.combat_mindpower = 0
@@ -329,7 +329,7 @@ function _M:useEnergy(val)
 end
 
 function _M:actBase()
-	-- Solipsism speed effects; calculated before the actor gets 
+	-- Solipsism speed effects; calculated before the actor gets energy
 	local current_psi_percentage = self:getPsi() / self:getMaxPsi()
 	if self:attr("solipsism_threshold") and current_psi_percentage < self:attr("solipsism_threshold") then
 		if self:hasEffect(self.EFF_CLARITY) then
@@ -340,7 +340,7 @@ function _M:actBase()
 		if self:hasEffect(self.EFF_SOLIPSISM) then
 			self:removeEffect(self.EFF_SOLIPSISM)
 		end
-		self:setEffect(self.EFF_CLARITY, 1, {power = math.max(0.5, current_psi_percentage - self:attr("clarity_threshold"))})
+		self:setEffect(self.EFF_CLARITY, 1, {power = math.min(0.5, current_psi_percentage - self:attr("clarity_threshold"))})
 	elseif self:hasEffect(self.EFF_SOLIPSISM) then
 		self:removeEffect(self.EFF_SOLIPSISM)
 	elseif self:hasEffect(self.EFF_CLARITY) then
@@ -560,7 +560,7 @@ function _M:act()
 	end
 	if self:attr("stoned") then self.energy.value = 0 end
 	if self:attr("dazed") then self.energy.value = 0 end
-	if self:attr("sleep") then self.energy.value = 0 end
+	if self:attr("sleep") and not self:attr("lucid_dreamer") then self.energy.value = 0 end
 	if self:attr("time_stun") then self.energy.value = 0 end
 	if self:attr("time_prison") then self.energy.value = 0 end
 
@@ -1297,8 +1297,10 @@ function _M:tooltip(x, y, seen_by)
 
 	local resists = {}
 	for t, v in pairs(self.resists) do
-		if t ~= "all" then v = self:combatGetResist(t) end
-		if v ~= 0 then resists[#resists+1] = string.format("%d%% %s", v, t == "all" and "all" or DamageType:get(t).name) end
+		if v ~= 0 then 
+			if t ~= "all" then v = self:combatGetResist(t) end
+			resists[#resists+1] = string.format("%d%% %s", v, t == "all" and "all" or DamageType:get(t).name)
+		end
 	end
 
 	local ts = tstring{}
@@ -1469,14 +1471,6 @@ function _M:onTakeHit(value, src)
 	if self:hasEffect(self.EFF_SPACETIME_TUNING) then
 		self:removeEffect(self.EFF_SPACETIME_TUNING)
 	end
-	if self:hasEffect(self.EFF_SLEEP) then
-		local p = self:hasEffect(self.EFF_SLEEP)
-		if p.power * p.dur < value then
-			self:removeEffect(self.EFF_SLEEPING)
-		else
-			p.dur = p.dur - math.ceil(value/p.power)
-		end
-	end
 
 	-- Remove domination hex
 	if self:hasEffect(self.EFF_DOMINATION_HEX) and src and src == self:hasEffect(self.EFF_DOMINATION_HEX).src then
@@ -1676,7 +1670,7 @@ function _M:onTakeHit(value, src)
 	end
 	
 	-- Feedback pool: Stores damage as energy to use later
-	if self:getMaxFeedback() > 0 and src ~= self then
+	if self:getMaxFeedback() > 0 and src ~= self and src ~= self.summoner then
 		local ratio = 0.5
 		if self:knowTalent(self.T_AMPLIFICATION) then
 			local t = self:getTalentFromId(self.T_AMPLIFICATION)
@@ -1684,6 +1678,10 @@ function _M:onTakeHit(value, src)
 		end
 		local feedback_gain = value * ratio
 		self:incFeedback(feedback_gain)
+		-- Give feedback to summoner
+		if self.summoner and self.summoner:getTalentLevel(self.summoner.T_TF_UNITY) >=1 and self.summoner:getMaxFeedback() > 0 then
+			self.summoner:incFeedback(feedback_gain)
+		end
 		-- Trigger backlash retribution damage
 		if self:knowTalent(self.T_BACKLASH) then
 			if src.y and src.x and not src.dead and self:reactionToward(src) < 0 then
@@ -1707,6 +1705,29 @@ function _M:onTakeHit(value, src)
 			self:removeEffect(self.EFF_RESONANCE_FIELD)
 		end
 	end
+	
+	-- Reduce sleep durations
+	if self:attr("sleep") then
+		local effs = {}
+		for eff_id, p in pairs(self.tmp) do
+			local e = self.tempeffect_def[eff_id]
+			if e.subtype.sleep then
+				effs[#effs+1] = {"effect", eff_id}
+			end
+		end
+		for i = 1, #effs do
+			if #effs == 0 then break end
+			local eff = rng.tableRemove(effs)
+			if eff[1] == "effect" then
+				local e = self:hasEffect(eff[2])
+				if e.power * e.dur < value then
+					game:onTickEnd(function() self:removeEffect(eff[2]) end) -- Happens on tick end so Night Terror can work properly
+				else
+					e.dur = e.dur - math.ceil(value/e.power)
+				end
+			end
+		end
+	end
 		
 	-- Solipsism
 	if self:knowTalent(self.T_SOLIPSISM) then
@@ -2168,6 +2189,11 @@ function _M:die(src, death_note)
 			t.spawn_ghoul(p.src, self, t)
 		end
 	end
+	
+	if src and self:attr("sleep") and src.isTalentActive and src:isTalentActive(src.T_NIGHT_TERROR) then
+		local t = src:getTalentFromId(src.T_NIGHT_TERROR) 
+		t.summonNightTerror(src, self, t)
+	end
 
 	-- Curse of Corpses: Corpselight
 	-- Curse of Corpses: Reprieve from Death
@@ -2531,15 +2557,6 @@ function _M:onWear(o, bypass_set)
 	o:check("on_wear", self)
 	if o.wielder then
 		for k, e in pairs(o.wielder) do
-			-- Apply Psychometry
-			if self:knowTalent(self.T_PSYCHOMETRY) and o.power_source and (o.power_source.psionic or o.power_source.nature or o.power_source.antimagic) then
-				local multiplier = 0.05 + (self:getTalentLevel(self.T_PSYCHOMETRY) / 33)
-				if e >= 1 then
-					e = math.ceil(e * (1 + multiplier))
-				else
-					e = e * (1 + multiplier)
-				end
-			end
 			o.wielded[k] = self:addTemporaryValue(k, e)
 		end
 	end
@@ -2564,7 +2581,13 @@ function _M:onWear(o, bypass_set)
 		self:attr("spellpower_reduction", 1)
 		self:attr("spell_failure", (o.material_level or 1) * 10)
 	end
-
+	
+	-- Apply Psychometry
+	if self:knowTalent(self.T_PSYCHOMETRY) then
+		local t = self:getTalentFromId(self.T_PSYCHOMETRY)
+		t.updatePsychometryCount(self, t)
+	end
+	
 	-- Learn Talent
 	if o.wielder and o.wielder.learn_talent then
 		for tid, level in pairs(o.wielder.learn_talent) do
@@ -2633,6 +2656,12 @@ function _M:onTakeoff(o, bypass_set)
 		self:attr("spellpower_reduction", -1)
 		self:attr("spell_failure", -(o.material_level or 1) * 10)
 	end
+	
+	-- Apply Psychometry
+	if self:knowTalent(self.T_PSYCHOMETRY) then
+		local t = self:getTalentFromId(self.T_PSYCHOMETRY)
+		t.updatePsychometryCount(self, t)
+	end
 
 	if o.wielder and o.wielder.learn_talent then
 		for tid, level in pairs(o.wielder.learn_talent) do
@@ -2670,7 +2699,7 @@ function _M:checkMindstar(o)
 		local nm = {}
 		for s, v in pairs(o.combat.dammod) do nm[s] = v * (1.3 + pv / 10) end
 		o.combat.dammod = nm
-		o.combat.apr = o.combat.apr * (1 + pv / 6.3)
+		o.combat.apr = math.floor(o.combat.apr * (1 + pv / 6.3))
 
 		print("Activating psiblade", o.name)
 	elseif not new and old then
@@ -2679,7 +2708,7 @@ function _M:checkMindstar(o)
 		local nm = {}
 		for s, v in pairs(o.combat.dammod) do nm[s] = v / (1.3 + pv / 10) end
 		o.combat.dammod = nm
-		o.combat.apr = o.combat.apr / (1 + pv / 6.3)
+		o.combat.apr = math.floor(o.combat.apr / (1 + pv / 6.3))
 
 		o.moddable_tile_ornament = nil
 		o.psiblade_active = false
@@ -3316,7 +3345,7 @@ function _M:postUseTalent(ab, ret)
 		elseif ab.type[1]:find("^technique/") then
 			self:useEnergy(game.energy_to_act * self:combatSpeed())
 		elseif ab.type[1]:find("^psionic/") then
-			self:useEnergy(game.energy_to_act * self:combatMentalSpeed())
+			self:useEnergy(game.energy_to_act * self:combatMindSpeed())
 		else
 			self:useEnergy()
 		end
@@ -3422,7 +3451,7 @@ function _M:postUseTalent(ab, ret)
 			trigger = true; self:incEquilibrium(ab.equilibrium)
 		end
 		-- Paradox is not affected by fatigue but it's cost does increase exponentially
-		if ab.paradox and not self:attr("zero_resource_cost") then
+		if ab.paradox and not (self:attr("zero_resource_cost") or game.zone.no_anomalies) then
 			trigger = true; self:incParadox(ab.paradox * (1 + (self.paradox / 300)))
 		end
 		if ab.psi and not self:attr("zero_resource_cost") then
@@ -3541,6 +3570,9 @@ function _M:breakPsionicChannel(talent)
 	if self:isTalentActive(self.T_MIND_STORM) and talent ~= self.T_MIND_STORM then
 		self:forceUseTalent(self.T_MIND_STORM, {ignore_energy=true})
 	end
+	if self:isTalentActive(self.T_DREAM_PRISON) and talent ~= self.T_DREAM_PRISON then
+		self:forceUseTalent(self.T_DREAM_PRISON, {ignore_energy=true})
+	end
 end
 
 --- Return the full description of a talent
@@ -3918,12 +3950,6 @@ function _M:on_set_temporary_effect(eff_id, e, p)
 		if not p.no_ct_effect and not e.no_ct_effect and e.status == "detrimental" then self:crossTierEffect(eff_id, p.apply_power, p.apply_save or save_for_effects[e.type]) end
 		p.total_dur = p.dur
 
-		-- Bonus save for schism
-		if self:attr("psionic_schism") and rng.percent(self:attr("psionic_schism")) and e.status == "detrimental" and save_type == "combatMentalResist" and self:checkHit(save, p.apply_power, 0, 95) then
-			game.logSeen(self, "#ORANGE#%s mental clone shrugs off the effect '%s'!", self.name:capitalize(), e.desc)
-			p.dur = 0
-		end
-		
 		if e.status == "detrimental" and self:checkHit(save, p.apply_power, 0, 95) and p.dur > 0 then
 			game.logSeen(self, "#ORANGE#%s shrugs off the effect '%s'!", self.name:capitalize(), e.desc)
 			p.dur = 0
diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index 4111003c0d9c33daf5a1f2e7816c9d9e7935535b..9514b3f0b6cd85961ee45009a61de3dc39b0a201 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -1014,6 +1014,9 @@ function _M:combatPhysicalpower(mod, weapon, add)
 		local t = self:getTalentFromId(self.T_EMPTY_HAND)
 		add = add + t.getDamage(self, t)
 	end
+	if self:attr("psychometry_power") then
+		add = add + self:attr("psychometry_power")
+	end
 
 	if not weapon then
 		local inven = self:getInven(self.INVEN_MAINHAND)
@@ -1125,8 +1128,8 @@ function _M:combatSpellSpeed()
 end
 
 -- Gets mental speed
-function _M:combatMentalSpeed()
-	return 1 / self.combat_mentalspeed
+function _M:combatMindSpeed()
+	return 1 / self.combat_mindspeed
 end
 
 --- Gets summon speed
@@ -1274,6 +1277,9 @@ function _M:combatMindpower(mod, add)
 		local t = self:getTalentFromId(self.T_GESTURE_OF_POWER)
 		add = add + t.getMindpowerChange(self, t)
 	end
+	if self:attr("psychometry_power") then
+		add = add + self:attr("psychometry_power")
+	end
 
 	return self:rescaleCombatStats((self.combat_mindpower > 0 and self.combat_mindpower or 0) + add + self:getWil() * 0.7 + self:getCun() * 0.4) * mod
 end
diff --git a/game/modules/tome/data/birth/classes/chronomancer.lua b/game/modules/tome/data/birth/classes/chronomancer.lua
index ec5fd15e30ac3d436144c0c299651776f0686115..1fb8903dc7f00b25b915f551fd5db84c6473c7cb 100644
--- a/game/modules/tome/data/birth/classes/chronomancer.lua
+++ b/game/modules/tome/data/birth/classes/chronomancer.lua
@@ -75,7 +75,7 @@ newBirthDescriptor{
 		[ActorTalents.T_DIMENSIONAL_STEP] = 1,
 		[ActorTalents.T_DUST_TO_DUST] = 1,
 		[ActorTalents.T_TURN_BACK_THE_CLOCK] = 1,
-		},
+	},
 	copy = {
 		max_life = 90,
 		resolvers.equip{ id=true,
@@ -128,7 +128,7 @@ newBirthDescriptor{
 		[ActorTalents.T_DUAL_STRIKE] = 1,
 		[ActorTalents.T_CELERITY] = 1,
 		[ActorTalents.T_STRENGTH_OF_PURPOSE] = 1,
-		},
+	},
 	copy = {
 		max_life = 100,
 		resolvers.equip{ id=true,
diff --git a/game/modules/tome/data/birth/classes/psionic.lua b/game/modules/tome/data/birth/classes/psionic.lua
index 48b9e75ce56eb3b15084cb835f495a7c410fbe9b..7d62f8086272279de92bbe44063e326f0ef4f07a 100644
--- a/game/modules/tome/data/birth/classes/psionic.lua
+++ b/game/modules/tome/data/birth/classes/psionic.lua
@@ -168,26 +168,27 @@ newBirthDescriptor{
 	talents_types = {
 		-- class
 		["psionic/distortion"]={true, 0.3},
+		["psionic/psychic-assault"]={true, 0.3},
 		["psionic/slumber"]={true, 0.3},
 		["psionic/solipsism"]={true, 0.3},
 		["psionic/thought-forms"]={true, 0.3},
 		
 		-- generic
+		["psionic/dreaming"]={true, 0.3},
 		["psionic/feedback"]={true, 0.3},
 		["psionic/mentalism"]={true, 0.3},
 		["cunning/survival"]={true, 0},
 		
 		-- locked trees
 		["psionic/discharge"]={false, 0.3},
-		["psionic/nightmare"]={true, 0.3},
-		-- generic
-		["psionic/trance"]={false, 0.3},
-		
+		["psionic/nightmare"]={false, 0.3},
 	},
 	talents = {
-		[ActorTalents.T_BIOFEEDBACK] = 1,
-		[ActorTalents.T_MIND_SEAR] = 1,
+		[ActorTalents.T_SLEEP] = 1,
+		
+		[ActorTalents.T_SUNDER_MIND] = 1,
 		[ActorTalents.T_SOLIPSISM] = 1,
+		[ActorTalents.T_THOUGHT_FORMS] = 1,
 	},
 	copy = {
 		max_life = 90,
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 145726ebe34ed3cfe9fb0bdb823533cae5223135..874e8d436a0e3279a5c8d870eba9e4daeaea5bd4 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -58,6 +58,7 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
 		end
 
 		-- Increases damage
+		local mind_linked = false
 		if src.inc_damage then
 			local inc = (src.inc_damage.all or 0) + (src.inc_damage[type] or 0)
 
@@ -66,10 +67,30 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
 				local incEntity = src.inc_damage_actor_type[target.type]
 				if incEntity and incEntity ~= 0 then
 					print("[PROJECTOR] before inc_damage_actor_type", dam + (dam * inc / 100))
-					local inc = inc + src.inc_damage_actor_type[target.type]
+					inc = inc + src.inc_damage_actor_type[target.type]
 					print("[PROJECTOR] after inc_damage_actor_type", dam + (dam * inc / 100))
 				end
 			end
+			
+			-- Increases damage to sleeping targets
+			if target:attr("sleep") and src.attr and src:attr("night_terror") then
+				inc = inc + src:attr("night_terror")
+				print("[PROJECTOR] after night_terror", dam + (dam * inc / 100))
+			end
+			-- Increases damage to targets with Insomnia
+			if src.attr and src:attr("lucid_dreamer") and target:hasEffect(target.EFF_INSOMNIA) then
+				inc = inc + src:attr("lucid_dreamer")
+				print("[PROJECTOR] after lucid_dreamer", dam + (dam * inc / 100))
+			end
+			-- Mind Link
+			if type == DamageType.MIND and target:hasEffect(target.EFF_MIND_LINK_TARGET) then
+				local eff = target:hasEffect(target.EFF_MIND_LINK_TARGET)
+				if eff.src == src then
+					mind_linked = true
+					inc = inc + eff.power
+					print("[PROJECTOR] after mind_link", dam + (dam * inc / 100))
+				end
+			end
 
 			dam = dam + (dam * inc / 100)
 		end
@@ -175,8 +196,9 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
 			if src.resists_pen then pen = (src.resists_pen.all or 0) + (src.resists_pen[type] or 0) end
 			local dominated = target:hasEffect(target.EFF_DOMINATED)
 			if dominated and dominated.source == src then pen = pen + (dominated.resistPenetration or 0) end
+			if target:attr("sleep") and src.attr and src:attr("night_terror") then pen = pen + src:attr("night_terror") end
 			local res = target:combatGetResist(type)
-			pen = util.bound(0, pen, 100)
+			pen = util.bound(pen, 0, 100)
 			if res > 0 then	res = res * (100 - pen) / 100 end
 			print("[PROJECTOR] res", res, (100 - res) / 100, " on dam", dam)
 			if res >= 100 then dam = 0
@@ -250,20 +272,10 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
 				end
 			end
 		end
-		
-		-- Mind Link
-		local mind_linked_damage = 0
-		if type == DamageType.MIND and target.hasEffect and target:hasEffect(target.EFF_MIND_LINK_TARGET) then
-			local eff = target:hasEffect(target.EFF_MIND_LINK_TARGET)
-			if eff.src == src then
-				mind_linked_damage = eff.power/100
-			end
-		end
+
 		-- Psychic Projection
-		if src.attr and src:attr("is_psychic_projection")then
-			if mind_linked_damage > 0 then
-				dam = dam * (1 + mind_linked_damage)
-			elseif target.subtype and target.subtype == "ghost" then
+		if src.attr and src:attr("is_psychic_projection") and not game.zone.is_dream_scape then
+			if (target.subtype and target.subtype == "ghost") or mind_linked then
 				dam = dam
 			else
 				dam = 0
@@ -472,10 +484,9 @@ newDamageType{
 	projector = function(src, x, y, type, dam)
 		local target = game.level.map(x, y, Map.ACTOR)
 		if target then
-			local mindpower, mentalresist
+			local mindpower, mentalresist, alwaysHit
 			if _G.type(dam) == "table" then dam, mindpower, mentalresist, alwaysHit, crossTierChance = dam.dam, dam.mindpower, dam.mentalresist, dam.alwaysHit, dam.crossTierChance end
 			local hit_power = mindpower or src:combatMindpower()
-			if src.attr and src:attr("psionic_schism") then hit_power = hit_power * (1 + src:attr("psionic_schism")/100) end
 			if alwaysHit or target:checkHit(hit_power, mentalresist or target:combatMentalResist(), 0, 95, 15) then
 				if crossTierChance and rng.percent(crossTierChance) then
 					target:crossTierEffect(target.EFF_BRAINLOCKED, src:combatMindpower())
@@ -2068,3 +2079,61 @@ newDamageType{
 		end
 	end,
 }
+
+-- Distortion; Includes knockback, penetrate, stun, and explosion paramters
+newDamageType{
+	name = "distortion", type = "DISTORTION",
+	projector = function(src, x, y, type, dam, tmp)
+		local target = game.level.map(x, y, Map.ACTOR)
+		if not target then return end
+		tmp = tmp or {}
+		if target and not tmp[target] then
+			tmp[target] = true
+			local old_pen = 0
+			-- Spike resists pen
+			if dam.penetrate then 
+				old_pen = src.resists_pen and src.resists_pen[engine.DamageType.PHYSICAL] or 0
+				src.resists_pen[engine.DamageType.PHYSICAL] = 100
+			end
+			-- Handle distortion effects
+			if target:hasEffect(target.EFF_DISTORTION) then
+				-- Explosive?
+				if dam.explosion then
+					src:project({type="ball", target.x, target.y, radius=dam.radius}, target.x, target.y, engine.DamageType.DISTORTION, {dam=src:mindCrit(dam.explosion), knockback=dam.radius}, {type="mind"})
+					dam.explosion_done = true
+				end
+				-- Stun?
+				if dam.stun then
+					dam.do_stun = true
+				end
+			end
+			-- Our damage
+			target:setEffect(target.EFF_DISTORTION, 1, {})
+			if not dam.explosion_done then
+				DamageType:get(DamageType.PHYSICAL).projector(src, x, y, DamageType.PHYSICAL, dam.dam)
+			end
+			-- Do knockback
+			if dam.knockback then
+				if target:checkHit(src:combatMindpower(), target:combatPhysicalResist(), 0, 95, 15) and target:canBe("knockback") then 
+					target:knockback(src.x, src.y, dam.knockback)
+					target:crossTierEffect(target.EFF_OFFBALANCE, src:combatMindpower())
+					game.logSeen(target, "%s is knocked back!", target.name:capitalize())
+				else
+					game.logSeen(target, "%s resists the knockback!", target.name:capitalize())
+				end
+			end
+			-- Do stun
+			if dam.do_stun then
+				if target:canBe("stun") then
+					target:setEffect(target.EFF_STUNNED, dam.stun, {apply_power=src:combatMindpower()})
+				else
+					game.logSeen(target, "%s resists the stun!", target.name:capitalize())
+				end
+			end
+			-- Reset resists pen
+			if dam.penetrate then
+				src.resists_pen[engine.DamageType.PHYSICAL] = old_pen
+			end
+		end
+	end,
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/general/objects/boss-artifacts.lua b/game/modules/tome/data/general/objects/boss-artifacts.lua
index dbd7b36cf79a3351440f1f3f27be23e7d6593419..60c02c1c0352e8b32372bc2018e9545d96310d5a 100644
--- a/game/modules/tome/data/general/objects/boss-artifacts.lua
+++ b/game/modules/tome/data/general/objects/boss-artifacts.lua
@@ -1395,12 +1395,11 @@ newEntity{ base = "BASE_GREATMAUL", define_as="ROTTING_MAUL",
 		dam = 96,
 		apr = 22,
 		physcrit = 10,
-		combat_critical_power = 40,
 		physspeed=1.2,
 		dammod = {str=1.4},
 		convert_damage = {[DamageType.BLIGHT] = 20},
 		melee_project={[DamageType.CORRUPTED_BLOOD] = 30},
-		special_on_hit = {desc="25% to damage nearby foes", fct=function(combat, who, target)
+		special_on_hit = {desc="25% to damage nearby foes", on_kill=true, fct=function(combat, who, target)
 			if rng.percent(25) then
 			local o, item, inven_id = who:findInAllInventoriesBy("define_as", "ROTTING_MAUL")
 				local dam = rng.avg(1,2) * (70+ who:getStr() * 1.8)
@@ -1413,6 +1412,7 @@ newEntity{ base = "BASE_GREATMAUL", define_as="ROTTING_MAUL",
 	wielder = {
 		inc_damage={[DamageType.PHYSICAL] = 12,},
 		knockback_immune=0.3,
+		combat_critical_power = 40,
 	},
 	max_power = 50, power_regen = 1,
 	use_power = { name = "knock away nearby foes", power = 50,
diff --git a/game/modules/tome/data/general/objects/egos/weapon.lua b/game/modules/tome/data/general/objects/egos/weapon.lua
index 50c91e56fcd271a4f0e0378dff6b95360c8f208d..45cc5c7141ddd348aaf1e6cdfd14474d6ef2d7f6 100644
--- a/game/modules/tome/data/general/objects/egos/weapon.lua
+++ b/game/modules/tome/data/general/objects/egos/weapon.lua
@@ -433,7 +433,7 @@ newEntity{
 -------------------------------------------------------
 newEntity{
 	power_source = {nature=true},
-	name = "huntsmen's ", prefix=true, instant_resolve=true,
+	name = "huntsman's ", prefix=true, instant_resolve=true,
 	keywords = {hunt=true},
 	level_range = {1, 50},
 	rarity = 10,
diff --git a/game/modules/tome/data/general/objects/egos/wizard-hat.lua b/game/modules/tome/data/general/objects/egos/wizard-hat.lua
index c7139836d344edafd10c7f3f5bd4e909fb874d6d..1ac20fd739f2316669673e7aa7733905c0131250 100644
--- a/game/modules/tome/data/general/objects/egos/wizard-hat.lua
+++ b/game/modules/tome/data/general/objects/egos/wizard-hat.lua
@@ -354,7 +354,7 @@ newEntity{
 		max_mana = resolvers.mbonus_material(40, 20),
 		talents_types_mastery = {
 			["spell/arcane"] = resolvers.mbonus_material(3, 1, function(e, v) v=v/10 return 0, v end),
-			["spell/arcane-shield"] = resolvers.mbonus_material(3, 1, function(e, v) v=v/10 return 0, v end),
+	--		["spell/arcane-shield"] = resolvers.mbonus_material(3, 1, function(e, v) v=v/10 return 0, v end),
 		},
 	},
 }
diff --git a/game/modules/tome/data/general/objects/world-artifacts.lua b/game/modules/tome/data/general/objects/world-artifacts.lua
index 06cc3f2bcb08bbed54d55d4255b2e3bc252e003c..af8eeb8f207012372b806288ca203a47939c08f0 100644
--- a/game/modules/tome/data/general/objects/world-artifacts.lua
+++ b/game/modules/tome/data/general/objects/world-artifacts.lua
@@ -1878,6 +1878,7 @@ newEntity{ base = "BASE_LEATHER_BELT",
 			[DamageType.LIGHT] = 15,
 			[DamageType.DARKNESS] = 15,
 			[DamageType.BLIGHT] = 15,
+			[DamageType.TEMPORAL] = 15,
 			[DamageType.NATURE] = 15,
 			[DamageType.PHYSICAL] = 10,
 			[DamageType.ARCANE] = 10,
@@ -3503,7 +3504,7 @@ newEntity{ base = "BASE_CLOTH_ARMOR",
 	unique = true,
 	name = "Robe of Force", color = colors.YELLOW, image = "object/artifact/robe_spider_silk_robe_spydre.png",
 	unided_name = "rippling cloth robe",
-	desc = [[This thin cloth robe is surrounded by a think shroud of telekinetic forces.]],
+	desc = [[This thin cloth robe is surrounded by a thick shroud of telekinetic forces.]],
 	level_range = {20, 28},
 	rarity = 190,
 	cost = 250,
diff --git a/game/modules/tome/data/gfx/effects/insomnia.png b/game/modules/tome/data/gfx/effects/insomnia.png
new file mode 100644
index 0000000000000000000000000000000000000000..8732e21f364c64b2fc27276250a8cd09761bb68b
Binary files /dev/null and b/game/modules/tome/data/gfx/effects/insomnia.png differ
diff --git a/game/modules/tome/data/gfx/talents/psychic_lobotomy.png b/game/modules/tome/data/gfx/talents/psychic_lobotomy.png
index 359c622019f194750b07866e90171123843779b7..b975afbe214fcf225468b8346aca3f1c2e26ca61 100644
Binary files a/game/modules/tome/data/gfx/talents/psychic_lobotomy.png and b/game/modules/tome/data/gfx/talents/psychic_lobotomy.png differ
diff --git a/game/modules/tome/data/talents/corruptions/shadowflame.lua b/game/modules/tome/data/talents/corruptions/shadowflame.lua
index d08f96550a0c7310e1d44e5f139dfae1862cafe3..e81b70c4c7abbfbcf87f3bd75a4c74476345814d 100644
--- a/game/modules/tome/data/talents/corruptions/shadowflame.lua
+++ b/game/modules/tome/data/talents/corruptions/shadowflame.lua
@@ -137,6 +137,10 @@ newTalent{
 			game.logPlayer(self, "This spell can not be used from within the Fearscape.")
 			return
 		end
+		if game.zone.no_planechange then
+			game.logPlayer(self, "This spell can not be cast here.")
+			return
+		end
 		if not self:canBe("planechange") then
 			game.logPlayer(self, "The spell fizzles...")
 			return
diff --git a/game/modules/tome/data/talents/misc/objects.lua b/game/modules/tome/data/talents/misc/objects.lua
index 8cb93d991aee367d63d48d5df56b906b68a3d1a3..90824b7d07dbcd750826615074a16d9dac1d203a 100644
--- a/game/modules/tome/data/talents/misc/objects.lua
+++ b/game/modules/tome/data/talents/misc/objects.lua
@@ -192,11 +192,11 @@ newTalent{
 	getBlockValue = function(self, t)
 		local val = 0
 		local shield1 = self:hasShield()
-		if shield1 then val = val + (shield1.special_combat and shield1.special_combat.block) or 0 end
+		if shield1 then val = val + (shield1.special_combat and shield1.special_combat.block or 0) end
 		
 		if not self:getInven("MAINHAND") then return val end
 		local shield2 = self:getInven("MAINHAND")[1]
-		if shield2 then val = val + (shield2.special_combat and shield2.special_combat.block) or 0 end
+		if shield2 then val = val + (shield2.special_combat and shield2.special_combat.block or 0) end
 		return val
 	end,
 	getBlockedTypes = function(self, t)
diff --git a/game/modules/tome/data/talents/psionic/discharge.lua b/game/modules/tome/data/talents/psionic/discharge.lua
index 9fb8efafe24601f14e88ad80d0a1747c3d120060..bff8da2592b6619476e142b6f067494ca3cb43dc 100644
--- a/game/modules/tome/data/talents/psionic/discharge.lua
+++ b/game/modules/tome/data/talents/psionic/discharge.lua
@@ -23,7 +23,7 @@ newTalent{
 	name = "Backlash",
 	type = {"psionic/discharge", 1},
 	points = 5, 
-	require = psi_wil_req1,
+	require = psi_wil_high1,
 	mode = "passive",
 	range = function(self, t) return 5 + math.min(5, (self:isTalentActive(self.T_MIND_STORM) and self:getTalentLevelRaw(self.T_MIND_STORM)) or 0) end,
 	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 75) end,
@@ -53,16 +53,15 @@ newTalent{
 	name = "Feedback Loop",
 	type = {"psionic/discharge", 2},
 	points = 5, 
-	require = psi_wil_req2,
+	require = psi_wil_high2,
 	cooldown = 24,
 	tactical = { FEEDBACK = 2 },
 	no_break_channel = true,
-	getDuration = function(self, t) return math.ceil(self:getTalentLevel(t) * 1.5) end,
+	getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t) * 1.5) end,
 	on_pre_use = function(self, t, silent) if self:getFeedback() <= 0 then if not silent then game.logPlayer(self, "You have no feedback to start a feedback loop!") end return false end return true end,
 	action = function(self, t)
 		local wrath = self:hasEffect(self.EFF_FOCUSED_WRATH)
 		self:setEffect(self.EFF_FEEDBACK_LOOP, self:mindCrit(t.getDuration(self, t), nil, wrath and wrath.power or 0), {})
-		
 		return true
 	end,
 	info = function(self, t)
@@ -77,7 +76,7 @@ newTalent{
 	name = "Mind Storm",
 	type = {"psionic/discharge", 3},
 	points = 5, 
-	require = psi_wil_req3,
+	require = psi_wil_high3,
 	sustain_feedback = 50,
 	mode = "sustained",
 	cooldown = 12,
@@ -164,7 +163,7 @@ newTalent{
 	name = "Focused Wrath",   
 	type = {"psionic/discharge", 4},
 	points = 5, 
-	require = psi_wil_req4,
+	require = psi_wil_high4,
 	feedback = 25,
 	cooldown = 12,
 	tactical = { ATTACK = {MIND = 2}},
diff --git a/game/modules/tome/data/talents/psionic/distortion.lua b/game/modules/tome/data/talents/psionic/distortion.lua
index 51b9cc102ec2461dc20465ab66260d995c80e587..28fe96cd830684c4f4ed1a6421adf11b1ac6c73c 100644
--- a/game/modules/tome/data/talents/psionic/distortion.lua
+++ b/game/modules/tome/data/talents/psionic/distortion.lua
@@ -17,214 +17,209 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
--- Edge TODO: Sounds, Particles, Talent Icons; All Talents
--- Fade from Reality?  (better name would be good, sounds to much like fade from time..  but yeah, same principal, only targeted so it reduces the enemies damage and what not)
+-- Edge TODO: Sounds, Particles
+
+local Object = require "mod.class.Object"
 
 newTalent{
-	name = "Distortion",
+	name = "Distortion Bolt",
 	type = {"psionic/distortion", 1},
 	points = 5, 
 	require = psi_wil_req1,
-	cooldown = 5,
-	tactical = { DISABLE = 2},
-	range = 0,
-	direct_hit = true,
+	cooldown = 2,
+	psi = 5,
+	tactical = { ATTACK = { PHYSICAL = 2} },
+	range = 10,
+	radius = function(self, t) return 1 + math.floor(self:getTalentLevel(t)/2) end,
 	requires_target = true,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 150) end,
-	radius = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
+	proj_speed = 20,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 100) end,
+	getDetonateDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end,
 	target = function(self, t)
-		return {type="cone", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false}
-	end,
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return true end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 100
-		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 100
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
+		return {type="bolt", range=self:getTalentRange(t), talent=t, display={particle="bolt_void", trail="dust_trail"}}
 	end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
-		
-		local damage = math.min(self.psionic_feedback, t.getDamage(self, t))
-		self:project(tg, x, y, DamageType.MIND, {dam=self:mindCrit(damage), crossTierChance=math.max(100, damage)})
-		
-		self.psionic_feedback = self.psionic_feedback - damage
-							
+		if not x or not y then return nil end
+		self:projectile(tg, x, y, DamageType.DISTORTION, {dam=self:mindCrit(t.getDamage(self, t)), explosion=t.getDetonateDamage(self, t), penetrate=true, radius=self:getTalentRadius(t)})
 		return true
 	end,
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
+		local detonate_damage = t.getDetonateDamage(self, t)
 		local radius = self:getTalentRadius(t)
-		return ([[You now store damage you take from outside sources as psionic feedback.  Activate to distortion up to %0.2f feedback in a %d radius cone.  Targets in the area will suffer mind damage and may be brain locked by this attack.
-		Learning this talent will increase the amount of feedback you can store by 100 (first talent point only).
-		The damage will scale with your mindpower.]]):format(damage, radius)
+		return ([[Fire a bolt of distortion that ignores resistance and inflicts %0.2f physical damage.  This damage will distort affected targets, rendering them vulnerable to distortion effects.
+		If the bolt comes in contact with a target that's already distorted a detonation will occur, inflicting %0.2f physical damage and knocking back all targets in a %d radius.
+		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), damDesc(self, DamageType.PHYSICAL, detonate_damage), radius)
 	end,
 }
 
 newTalent{
-	name = "Distortion 2",
+	name = "Distortion Wave",
 	type = {"psionic/distortion", 2},
 	points = 5, 
 	require = psi_wil_req2,
-	mode = "sustained",
-	sustain_psi = 20,
-	cooldown = 18,
-	tactical = { BUFF = 2 },
-	getMaxOverflow = function(self, t) return self.psionic_feedback_max * (self:combatTalentMindDamage(t, 20, 100)/100) end,
-	radius = function(self, t) return math.ceil(self:getTalentLevel(t)/2) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 50
-		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 50
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
-	end,
-	doOverflowdistortion = function(self, t)
-		local tg = {type="ball", range=0, radius=self:getTalentRadius(t), selffire=false, friendlyfire=false}
-		local damage = self.psionic_overflow
-		self:project(tg, self.x, self.y, DamageType.MIND, self:mindCrit(damage))
-		-- Lose remaining overflow
-		self.psionic_overflow = nil
-	end,
-	activate = function(self, t)
-		game:playSoundNear(self, "talents/flame")
-		return {
-			ov = self:addTemporaryValue("psionic_overflow_max", t.getMaxOverflow(self, t)),
-		}
+	cooldown = 6,
+	psi = 10,
+	tactical = { ATTACK = { PHYSICAL = 2}, DISABLE = 2},
+	range = 0,
+	radius = function(self, t) return 3 + math.ceil(self:getTalentLevel(t)/2) end,
+	requires_target = true,
+	direct_hit = true,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 150) end,
+	getPower = function(self, t) return math.ceil(self:getTalentRadius(t)/2) end,
+	target = function(self, t)
+		return { type="cone", range=self:getTalentRange(t), radius=self:getTalentRadius(t), talent=t }
 	end,
-	deactivate = function(self, t, p)
-		self:removeTemporaryValue("psionic_overflow_max", p.ov)
+	action = function(self, t)
+		local tg = self:getTalentTarget(t)
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		self:project(tg, x, y, DamageType.DISTORTION, {dam=self:mindCrit(t.getDamage(self, t)), knockback=t.getPower(self, t), stun=t.getPower(self, t)}, {type="mind"})
 		return true
 	end,
 	info = function(self, t)
-		local overflow = t.getMaxOverflow(self, t)
+		local damage = t.getDamage(self, t)
 		local radius = self:getTalentRadius(t)
-		return ([[While active you store up to %d excess feedback as overflow.  At the start of your turn the overflow will be unleased as mind damage in a radius of %d.
-		Learning this talent will increase the amount of feedback you can store by 50 (first talent point only).
-		The max excess you can store will improve with your mindpower and max feedback.]]):format(overflow, radius)
+		local power = t.getPower(self, t)
+		return ([[Creates a distortion wave in a radius %d cone that deals %0.2f physical damage and knocks back targets in the blast radius.
+		This damage will distort affected targets, rendering them vulnerable to distortion effects.
+		If the target is already distorted they'll be stunned for %d turns as well.
+		The damage will scale with your mindpower.]]):format(radius, damDesc(self, DamageType.PHYSICAL, damage), power)
 	end,
 }
 
 newTalent{
-	name = "Distortion 3",
+	name = "Ravage",
 	type = {"psionic/distortion", 3},
-	points = 5,
+	points = 5, 
 	require = psi_wil_req3,
-	cooldown = 10,
-	tactical = { ATTACKAREA = {PHYSICAL = 2}, DISABLE = { knockback = 2 }, },
-	range = 0,
-	radius = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
-	direct_hit = true,
+	cooldown = 12,
+	psi = 20,
+	tactical = { ATTACK = { PHYSICAL = 2}, DISABLE = 2},
+	range = 10,
 	requires_target = true,
+	direct_hit = true,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
+	getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)) end,
 	target = function(self, t)
-		return {type="ball", range=self:getTalentRange(t), talent=t}
-	end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 230) end,
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return not self:hasEffect(self.EFF_REGENERATION) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 50
-		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 50
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
+		return {type="hit", range=self:getTalentRange(t), talent=t}
 	end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
+		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 target = game.level.map(x, y, Map.ACTOR)
+		if not target then return end
 		
-		local damage = math.min(self.psionic_feedback, t.getDamage(self, t))
-		self:project(tg, x, y, DamageType.MINDKNOCKBACK, self:mindCrit(damage))
-		self.psionic_feedback = self.psionic_feedback - damage
+		local ravage = false
+		if target:hasEffect(target.EFF_DISTORTION) then
+			ravage = true
+		end
 		
+		target:setEffect(target.EFF_RAVAGE, t.getDuration(self, t), {dam=self:mindCrit(t.getDamage(self, t)), ravage=ravage, apply_power=self:combatMindpower()})
+							
 		return true
 	end,
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
-		local radius = self:getTalentRadius(t)
-		return ([[Activate to convert up to %0.2f of stored feedback into a blast of kinetic energy.  Targets out to a radius of %d will suffer physical damage and may be knocked back.
-		Learning this talent will increase the amount of feedback you can store by 50 (first talent point only).
-		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), radius)
+		local duration = t.getDuration(self, t)
+		return ([[Ravages the target with distortion, inflicting %0.2f physical damage each turn for %d turns.
+		This damage will distort affected targets, rendering them vulnerable to distortion effects.
+		If the target is already distorted when ravage is applied the target will also lose one beneficial physical effect or sustain each turn.
+		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), duration)
 	end,
 }
 
 newTalent{
-	name = "Distortion 4",
+	name = "Maelstrom",
 	type = {"psionic/distortion", 4},
 	points = 5, 
 	require = psi_wil_req4,
-	cooldown = 15,
-	tactical = { DEFEND = 2, ATTACK = {MIND = 2}},
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return true end,
-	getShieldPower = function(self, t) return self:combatTalentMindDamage(t, 20, 300) end,
+	cooldown = 24,
+	psi = 30,
+	tactical = { ATTACK = { PHYSICAL = 2}, DISABLE = 2},
+	range = 10,
+	radius = function(self, t) return 3 end,
+	requires_target = true,
 	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 100
-		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 100
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
+	getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t)) end,
+	target = function(self, t)
+		return {type="hit", range=self:getTalentRange(t), nolock=true, talent=t}
 	end,
+	tactical = { ATTACKAREA = { PHYSICAL = 2 }, DISABLE = 1 },
 	action = function(self, t)
-		local power = math.min(self.psionic_feedback, t.getShieldPower(self, t))
-		self:setEffect(self.EFF_RESONANCE_SHIELD, 10, {power = self:mindCrit(power), dam = t.getDamage(self, t)})
-		self.psionic_feedback = self.psionic_feedback - power
+		local tg = self:getTalentTarget(t)
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local _ _, x, y = self:canProject(tg, x, y)
+		if game.level.map:checkEntity(x, y, Map.TERRAIN, "block_move") then return nil end
+
+		local oe = game.level.map(x, y, Map.TERRAIN)
+		if not oe or oe.is_maelstrom then return end
+		
+		local e = Object.new{
+			old_feat = oe,
+			type = oe.type, subtype = oe.subtype,
+			name = "maelstrom", image = oe.image, add_mos = {{image = "terrain/wormhole.png"}},
+			display = '&', color_r=255, color_g=255, color_b=255, back_color=colors.STEEL_BLUE,
+			always_remember = true,
+			temporary = t.getDuration(self, t),
+			is_maelstrom = true,
+			x = x, y = y,
+			canAct = false,
+			dam = self:mindCrit(t.getDamage(self, t)),
+			radius = self:getTalentRadius(t),
+			act = function(self)
+				local tgts = {}
+				local Map = require "engine.Map"
+				local DamageType = require "engine.DamageType"
+				local grids = core.fov.circle_grids(self.x, self.y, self.radius, true)
+				for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
+					local Map = require "engine.Map"
+					local target = game.level.map(x, y, Map.ACTOR)
+					if target then 
+						tgts[#tgts+1] = {actor=target, sqdist=core.fov.distance(self.x, self.y, x, y)}
+					end
+				end end
+				table.sort(tgts, "sqdist")
+				for i, target in ipairs(tgts) do
+					if target.actor:canBe("knocback") then
+						target.actor:pull(self.x, self.y, 1)
+						game.logSeen(target.actor, "%s is pulled in by the %s!", target.actor.name:capitalize(), self.name)
+					end
+					DamageType:get(DamageType.PHYSICAL).projector(self.summoner, target.actor.x, target.actor.y, DamageType.PHYSICAL, self.dam)
+					target.actor:setEffect(target.actor.EFF_DISTORTION, 1, {})
+				end
+
+				self:useEnergy()
+				self.temporary = self.temporary - 1
+				if self.temporary <= 0 then
+					game.level.map:removeParticleEmitter(self.particles)	
+					game.level.map(self.x, self.y, engine.Map.TERRAIN, self.old_feat)
+					game.level:removeEntity(self)
+					game.level.map:updateMap(self.x, self.y)
+				end
+			end,
+			summoner_gain_exp = true,
+			summoner = self,
+		}
+		
+		e.particles = game.level.map:particleEmitter(x, y, 3, "leavestide", {only_one=true}) -- Edge TODO: Make particles for this
+		game.level:addEntity(e)
+		game.level.map(x, y, Map.TERRAIN, e)
+		game.nicer_tiles:updateAround(game.level, x, y)
+		game.level.map:updateMap(x, y)
+		game:playSoundNear(self, "talents/fire")
 		return true
 	end,
 	info = function(self, t)
-		local shield_power = t.getShieldPower(self, t)
+		local duration = t.getDuration(self, t)
 		local damage = t.getDamage(self, t)
-		return ([[Activate to conver up to %0.2f feedback into a resonance shield that will absorb 50%% of all damage you take and inflict %0.2f mind damage to melee attackers.
-		Learning this talent will increase the amount of feedback you can store by 100 (first talent point only).
-		The conversion ratio will scale with your mindpower and the effect lasts up to ten turns.]]):format(shield_power, damDesc(self, DamageType.MIND, damage))
+		return ([[Create a powerful maelstorm for %d turns.  Each turn the maelstrom will pull in actors within a radius of 3 and inflict %0.2f physical damage.
+		This damage will distort affected targets, rendering them vulnerable to distortion effects.
+		The damage will scale with your mindpower.]]):format(duration, damDesc(self, DamageType.PHYSICAL, damage))
 	end,
 }
\ No newline at end of file
diff --git a/game/modules/tome/data/talents/psionic/feedback.lua b/game/modules/tome/data/talents/psionic/feedback.lua
index af03654e57d0139dc5bab517cfd712be2cc89cfa..8eb4d14c9b5ebc452b04ff2febbf04ac215a1273 100644
--- a/game/modules/tome/data/talents/psionic/feedback.lua
+++ b/game/modules/tome/data/talents/psionic/feedback.lua
@@ -65,11 +65,9 @@ newTalent{
 	getMaxFeedback = function(self, t) return self:getTalentLevelRaw(t) * 10 end,
 	on_learn = function(self, t)
 		self:incMaxFeedback(10)
-		return true
 	end,
 	on_unlearn = function(self, t)
 		self:incMaxFeedback(-10)
-		return true
 	end,
 	info = function(self, t)
 		local max_feedback = t.getMaxFeedback(self, t)
diff --git a/game/modules/tome/data/talents/psionic/mentalism.lua b/game/modules/tome/data/talents/psionic/mentalism.lua
index 0c58d7cf88cc33f26e0cb88a916f8d4cea64c5ae..31f5b7e17f55417f99c88088f7895af13e953417 100644
--- a/game/modules/tome/data/talents/psionic/mentalism.lua
+++ b/game/modules/tome/data/talents/psionic/mentalism.lua
@@ -27,40 +27,81 @@ newTalent{
 	points = 5, 
 	require = psi_wil_req1,
 	mode = "passive",
-	getMultiplier = function(self, t) return 0.05 + (self:getTalentLevel(t) / 33) end,
+	getPsychometryCap = function(self, t) return self:getTalentLevelRaw(t) end,
+	updatePsychometryCount = function(self, t)
+		-- Update psychometry power
+		local psychometry_count = 0
+		for inven_id, inven in pairs(self.inven) do
+			if inven.worn then
+				for item, o in ipairs(inven) do
+					if o and item and o.power_source and (o.power_source.psionic or o.power_source.nature or o.power_source.antimagic) then
+						psychometry_count = psychometry_count + math.min(o.material_level or 1, t.getPsychometryCap(self, t))
+					end
+				end
+			end
+		end
+		self:attr("psychometry_power", psychometry_count, true)
+	end,
+	on_learn = function(self, t)
+		t.updatePsychometryCount(self, t)
+	end,	
+	on_unlearn = function(self, t)
+		if not self:knowTalent(t) then
+			self.psychometry_power = nil
+		else
+			t.updatePsychometryCount(self, t)
+		end
+	end,
 	info = function(self, t)
-		local multiplier = t.getMultiplier(self, t)
-		return ([[When you wield or wear an item infused by psionic, nature, or arcane-disrupting forces you improve all values under its 'when wielded/worn' field by %d%%.
-		Note this doesn't change the item itself, but rather the effects it has on your person (the item description will not reflect the improved values).]]):format(multiplier * 100)
+		local max = t.getPsychometryCap(self, t)
+		return ([[Resonate with psionic, nature, and anti-magic powered objects, increasing your physical and mind power by %d or the objects material level (which ever is lower).
+		This effect stacks and applies for each qualifying object worn.]]):format(max)
 	end,
 }
 
 newTalent{
-	name = "Schism",
+	name = "Mental Shielding",
 	type = {"psionic/mentalism", 2},
 	points = 5,
 	require = psi_wil_req2,
-	mode = "sustained",
-	sustain_psi = 10,
+	psi = 15,
 	cooldown = 24,
-	remove_on_zero = true,
-	tactical = { BUFF=2, DEFEND=2},
-	getPower = function(self, t) return 20 + (self:getTalentLevel(t) * 10) end,
-	activate = function(self, t)
-		game:playSoundNear(self, "talents/heal")
-		local ret = {
-			schism = self:addTemporaryValue("psionic_schism", t.getPower(self, t)),
-		}
-		return ret
-	end,
-	deactivate = function(self, t, p)
-		self:removeTemporaryValue("psionic_schism", p.schism)
+	tactical = { CURE=2},
+	no_energy = true,
+	getRemoveCount = function(self, t) return math.ceil(self:getTalentLevel(t)) end,
+	action = function(self, t)
+		local effs = {}
+		local count = t.getRemoveCount(self, t)
+
+		-- Go through all mental effects
+		for eff_id, p in pairs(self.tmp) do
+			local e = self.tempeffect_def[eff_id]
+			if e.type == "mental" and e.status == "detrimental" then
+				effs[#effs+1] = {"effect", eff_id}
+			end
+		end
+
+		for i = 1, t.getRemoveCount(self, t) do
+			if #effs == 0 then break end
+			local eff = rng.tableRemove(effs)
+
+			if eff[1] == "effect" then
+				self:removeEffect(eff[2])
+				count = count - 1
+			end
+		end
+		
+		if count >= 1 then
+			self:setEffect(self.EFF_CLEAR_MIND, 6, {power=count})
+		end
+		
+		game.logSeen(self, "%s's mind is clear!", self.name:capitalize())
 		return true
 	end,
 	info = function(self, t)
-		local power = t.getPower(self, t)
-		return ([[Divide your mental faculties, increasing your mindpower for mind damage hit calculations by %d%% and giving you a %d%% chance to roll any mental saves against status effects twice, taking the better of the two results.
-		]]):format(power, power)
+		local count = t.getRemoveCount(self, t)
+		return ([[Clears your mind of current mental effects and block additional ones over 6 turns.  At most %d mental effects will be affected.
+		This talent takes not time to use.]]):format(count)
 	end,
 }
 
@@ -69,7 +110,7 @@ newTalent{
 	type = {"psionic/mentalism", 3},
 	points = 5, 
 	require = psi_wil_req3,
-	psi = 10,
+	psi = 20,
 	cooldown = 24,
 	no_npc_use = true, -- this can be changed if the AI is improved.  I don't trust it to be smart enough to leverage this effect.
 	getPower = function(self, t) return math.ceil(self:combatTalentMindDamage(t, 5, 40)) end,
@@ -81,7 +122,7 @@ newTalent{
 			game.logPlayer(self, "Not enough space to invoke your spirit!")
 			return
 		end
-
+		
 		local m = self:clone{
 			shader = "shadow_simulacrum",
 			no_drops = true,
@@ -155,7 +196,10 @@ newTalent{
 				end,
 			})
 		end
-		game:onTickEnd(function() game.party:setPlayer(m)  self:resetCanSeeCache() end)
+		game:onTickEnd(function() 
+			game.party:setPlayer(m)
+			self:resetCanSeeCache()
+		end)
 		
 		return true
 	end,
@@ -173,12 +217,12 @@ newTalent{
 	type = {"psionic/mentalism", 4},
 	points = 5, 
 	require = psi_wil_req4,
-	sustain_psi = 20,
+	sustain_psi = 50,
 	mode = "sustained",
 	no_sustain_autoreset = true,
 	cooldown = 24,
 	tactical = { BUFF = 2, ATTACK = {MIND = 2}},
-	range = 10,
+	range = function(self, t) return 5 + math.min(5, self:getTalentLevelRaw(t)) end,
 	direct_hit = true,
 	requires_target = true,
 	target = function(self, t)
@@ -189,17 +233,13 @@ newTalent{
 		local tg = self:getTalentTarget(t)
 		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 target = game.level.map(x, y, Map.ACTOR)
 		if not target or target == self then return end
 		
-		-- I would just check hit here but I hate bypassing the on_set_temporary_effect function, it kinda cheats the player
-		target:setEffect(target.EFF_MIND_LINK_TARGET, 10, {apply_power = self:combatMindpower(), no_ct_effect=true, src=self})
-		
-		-- So we do it like this...  Did we hit?
-		if not target:hasEffect(target.EFF_MIND_LINK_TARGET) then return false end
+		target:setEffect(target.EFF_MIND_LINK_TARGET, 10, {power=t.getBonusDamage(self, t), src=self, range=self:getTalentRange(t)})
 		
 		local ret = {
-			bonus_damage = t.getBonusDamage(self, t),
 			target = target,
 			esp = self:addTemporaryValue("esp", {[target.type] = 1}),
 		}
@@ -218,6 +258,7 @@ newTalent{
 	info = function(self, t)
 		local damage = t.getBonusDamage(self, t)
 		return ([[Link minds with the target.  While your minds are linked you'll inflict %d%% more mind damage to the target and gain telepathy to it's creature type.
-		Only one mindlink can be maintained at a time and the mind damage bonus will scale with your mindpower.]]):format(damage)
+		Only one mindlink can be maintained at a time and the effect will break if the target dies or goes beyond the talent range.
+		The mind damage bonus will scale with your mindpower.]]):format(damage)
 	end,
-}
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/talents/psionic/nightmare.lua b/game/modules/tome/data/talents/psionic/nightmare.lua
index 9c6838f87c77d7f0c83794f9fcddd6c19b6d043a..e188b1d2c962cb00ca166dc77738c57cb3f5b860 100644
--- a/game/modules/tome/data/talents/psionic/nightmare.lua
+++ b/game/modules/tome/data/talents/psionic/nightmare.lua
@@ -17,48 +17,70 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
--- Edge TODO: Sounds, Particles, Talent Icons; All Talents
--- Idea: Nightmare effects gain a bonus to mindpower applications on slept targets, increasing chances of landing as well as brain-locks
--- Idea Night Terror: Sustain, increases mind damage by x% and increases darkness damage by X% of your +mind damage (up to 100).  Increases power of all nightmare effects on sleeping targets by X%
+-- Edge TODO: Sounds, Particles,
 
 newTalent{
-	name = "Nightmare/Waking Nightmare",
-	short_name = "WAKING_NIGHTMARE",
+	name = "Nightmare",
 	type = {"psionic/nightmare", 1},
-	points = 5,
-	require = psi_wil_req1,
-	cooldown = 10,
-	psi = 20,
-	range = 10,
+	points = 5, 
+	require = psi_wil_high1,
+	cooldown = 8,
+	psi = 10,
+	tactical = { DISABLE = {sleep = 1}, ATTACK = { DARKNESS = 2 }, },
 	direct_hit = true,
 	requires_target = true,
-	tactical = { ATTACK = { DARKNESS = 2 }, DISABLE = { confusion = 1, stun = 1, blind = 1 } },
-	getChance = function(self, t) return self:combatTalentMindDamage(t, 15, 50) end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end,
-	getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t)) end,
+	range = function(self, t) return 2 + math.floor(self:getTalentLevel(t)/2) end,
+	target = function(self, t) return {type="cone", radius=self:getTalentRange(t), range=0, talent=t, selffire=false} end,
+	getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)/2) end,
+	getInsomniaDuration = function(self, t)
+		local t = self:getTalentFromId(self.T_SANDMAN)
+		local reduction = t.getInsomniaReduction(self, t)
+		return 10 - reduction
+	end,
+	getSleepPower = function(self, t) 
+		local power = self:combatTalentMindDamage(t, 5, 25)
+		if self:knowTalent(self.T_SANDMAN) then
+			local t = self:getTalentFromId(self.T_SANDMAN)
+			power = power + t.getSleepPowerBonus(self, t)
+		end
+		return power
+	end,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 100) end,
 	action = function(self, t)
-		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		local _ _, x, y = self:canProject(tg, x, y)
-		if not x or not y then return nil end
-		local target = game.level.map(x, y, Map.ACTOR)
-		if not target then return nil end
 
-		if target:canBe("fear") then
-			target:setEffect(target.EFF_WAKING_NIGHTMARE, t.getDuration(self, t), {src = self, chance=t.getChance(self, t), dam=self:mindCrit(t.getDamage(self, t)), apply_power=self:combatMindpower()})
-		else
-			game.logSeen(target, "%s resists the nightmare!", target.name:capitalize())
+		--Restless?
+		local is_waking =0
+		if self:knowTalent(self.T_RESTLESS_NIGHT) then
+			local t = self:getTalentFromId(self.T_RESTLESS_NIGHT)
+			is_waking = t.getDamage(self, t)
 		end
-
+		
+		local damage = self:mindCrit(t.getDamage(self, t))
+		self:project(tg, x, y, function(tx, ty)
+			local target = game.level.map(tx, ty, Map.ACTOR)
+			if target then
+				if target:canBe("sleep") then
+					target:setEffect(target.EFF_NIGHTMARE, t.getDuration(self, t), {src=self, power=power, waking=is_waking, dam=damage, insomnia=t.getInsomniaDuration(self, t), no_ct_effect=true, apply_power=self:combatMindpower()})
+				else
+					game.logSeen(self, "%s resists the nightmare!", target.name:capitalize())
+				end
+			end
+		end)
 		return true
 	end,
 	info = function(self, t)
-		local damage = t.getDamage(self, t)
+		local radius = self:getTalentRange(t)
 		local duration = t.getDuration(self, t)
-		local chance = t.getChance(self, t)
-		return ([[Inflicts %0.2f darkness damage each turn for %d turns and has a %d%% chance to randomly cause blindness, stun, or confusion (lasting 3 turns).]]):
-		format(damDesc(self, DamageType.DARKNESS, (damage)), duration, chance)
+		local power = t.getSleepPower(self, t)
+		local damage = t.getDamage(self, t)
+		local insomnia = t.getInsomniaDuration(self, t)
+		return([[Puts targets in a radius %d cone into a nightmarish sleep for %d turns, rendering them unable to act.  Every %d points of damage the target suffers will reduce the effect duration by one turn.
+		Each turn they'll suffer %0.2f darkness damage.  This damage will not reduce the duration of the effect.
+		When Nightmare ends the target will suffer from Insomnia for %d turns, rendering them resistant to sleep effects.
+		The damage threshold and mind damage will scale with your mindpower.]]):format(radius, duration, power, damDesc(self, DamageType.DARKNESS, (damage)), insomnia)
 	end,
 }
 
@@ -66,7 +88,7 @@ newTalent{
 	name = "Inner Demons",
 	type = {"psionic/nightmare", 2},
 	points = 5,
-	require = psi_wil_req2,
+	require = psi_wil_high2,
 	cooldown = 18,
 	psi = 20,
 	range = 10,
@@ -126,10 +148,7 @@ newTalent{
 			if t.mode == "sustained" and m:isTalentActive(t.id) then m:forceUseTalent(t.id, {ignore_energy=true}) end
 			m.talents[t.id] = nil
 		end
-
-		-- nil the Inner Demons effect to squelch combat log spam
-		m.tmp[m.EFF_INNER_DEMONS] = nil
-
+		
 		-- remove detrimental timed effects
 		local effs = {}
 		for eff_id, p in pairs(m.tmp) do
@@ -146,7 +165,6 @@ newTalent{
 			end
 		end
 
-
 		game.zone:addEntity(game.level, m, "actor", x, y)
 		game.level.map:particleEmitter(x, y, 1, "shadow")
 
@@ -161,9 +179,14 @@ newTalent{
 		if not x or not y then return nil end
 		local target = game.level.map(x, y, Map.ACTOR)
 		if not target then return nil end
-
+		if self:reactionToward(target) < 0 then
+			game.logPlayer(self, "You can't cast this on friendly targets.")
+		end
+		
+		local chance = self:mindCrit(t.getChance(self, t))
+		if target:attr("sleep") then chance = chance * 2 end
 		if target:canBe("fear") then
-			target:setEffect(target.EFF_INNER_DEMONS, t.getDuration(self, t), {src = self, chance=self:mindCrit(t.getChance(self, t)), apply_power=self:combatMindpower()})
+			target:setEffect(target.EFF_INNER_DEMONS, t.getDuration(self, t), {src = self, chance=chance, apply_power=self:combatMindpower()})
 		else
 			game.logSeen(target, "%s resists the demons!", target.name:capitalize())
 		end
@@ -173,7 +196,144 @@ newTalent{
 	info = function(self, t)
 		local duration = t.getDuration(self, t)
 		local chance = t.getChance(self, t)
-		return ([[Brings the target's inner demons to the surface.  Each turn for %d turns there's a %d%% chance that one will be summoned.
-		If the summoning is resisted the effect will end early.]]):format(duration, chance)
+		return ([[Brings the target's inner demons to the surface.  Each turn for %d turns there's a %d%% chance that the a demon will surface, requiring the target to make a mental save to keep it form manifesting.
+		If the target is sleeping the chance will be doubled and no saving throw will be allowed.  Otherwise if the summoning is resisted the effect will end early.
+		The summon chance will scale with your mindpower.]]):format(duration, chance)
+	end,
+}
+
+newTalent{
+	name = "Waking Nightmare",
+	type = {"psionic/nightmare", 3},
+	points = 5,
+	require = psi_wil_high3,
+	cooldown = 10,
+	psi = 20,
+	range = 10,
+	direct_hit = true,
+	requires_target = true,
+	tactical = { ATTACK = { DARKNESS = 2 }, DISABLE = { confusion = 1, stun = 1, blind = 1 } },
+	getChance = function(self, t) return self:combatTalentMindDamage(t, 15, 50) end,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end,
+	getDuration = function(self, t) return 4 + math.ceil(self:getTalentLevel(t)) end,
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local _ _, x, y = self:canProject(tg, x, y)
+		if not x or not y then return nil end
+		local target = game.level.map(x, y, Map.ACTOR)
+		if not target then return nil end
+
+		local chance = self:mindCrit(t.getChance(self, t))
+		if target:attr("sleep") then chance = chance * 2 end
+		if target:canBe("fear") then
+			target:setEffect(target.EFF_WAKING_NIGHTMARE, t.getDuration(self, t), {src = self, chance=t.getChance(self, t), dam=self:mindCrit(t.getDamage(self, t)), apply_power=self:combatMindpower()})
+		else
+			game.logSeen(target, "%s resists the nightmare!", target.name:capitalize())
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		local duration = t.getDuration(self, t)
+		local chance = t.getChance(self, t)
+		return ([[Inflicts %0.2f darkness damage each turn for %d turns and has a %d%% chance to randomly cause blindness, stun, or confusion (lasting 3 turns).
+		If the target is sleeping the chance of suffering a negative effect will be doubled.
+		The damage will scale with your mindpower.]]):
+		format(damDesc(self, DamageType.DARKNESS, (damage)), duration, chance)
+	end,
+}
+
+newTalent{
+	name = "Night Terror",
+	type = {"psionic/nightmare", 4},
+	points = 5,
+	require = psi_wil_high4,
+	mode = "sustained",
+	sustain_psi = 50,
+	cooldown = 24,
+	tactical = { BUFF=2 },
+	getDamageBonus = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
+	getSummonTime = function(self, t) return math.floor(self:getTalentLevel(t)*2) end,
+	summonNightTerror = function(self, target, t)
+		-- Find space
+		local x, y = util.findFreeGrid(target.x, target.y, 1, true, {[Map.ACTOR]=true})
+		if not x then
+			return
+		end
+		
+		local stats = 10 + t.getDamageBonus(self, t)
+		local NPC = require "mod.class.NPC"
+		local m = NPC.new{
+			name = "terror",
+			display = "h", color=colors.DARK_GREY, image="npc/horror_eldritch_nightmare_horror.png",
+			blood_color = colors.BLUE,
+			desc = "A formless terror that seems to cut through the air, and its victims, like a knife.",
+			type = "horror", subtype = "eldritch",
+			rank = 2,
+			size_category = 2,
+			body = { INVEN = 10 },
+			no_drops = true,
+			autolevel = "warriorwill",
+			level_range = {1, nil}, exp_worth = 0,
+			ai = "summoned", ai_real = "dumb_talented_simple", ai_state = { talent_in=2 },
+			stats = { str=15, dex=15, wil=15, con=15, cun=15},
+			infravision = 10,
+			can_pass = {pass_wall=20},
+			resists = {[DamageType.LIGHT] = -50, [DamageType.DARKNESS] = 100},
+			silent_levelup = true,
+			no_breath = 1,
+			negative_status_effect_immune = 1,
+			infravision = 10,
+			see_invisible = 80,
+			sleep = 1,
+			lucid_dreamer = 1,
+			max_life = resolvers.rngavg(50, 80),
+			combat_armor = 1, combat_def = 10,
+			combat = { dam=resolvers.levelup(resolvers.rngavg(15,20), 1, 1.1), atk=resolvers.rngavg(5,15), apr=5, dammod={str=1}, damtype=DamageType.DARKNESS },
+			resolvers.talents{
+			--	[Talents.T_SLEEP]=self:getTalentLevelRaw(t),
+			},
+		}
+
+		m.faction = self.faction
+		m.summoner = self
+		m.summoner_gain_exp = true
+		m.summon_time = t.getSummonTime(self, t)
+		m.remove_from_party_on_death = true
+		m:resolve() m:resolve(nil, true)
+		m:forceLevelup(self.level)
+		
+		game.zone:addEntity(game.level, m, "actor", x, y)
+		game.level.map:particleEmitter(x, y, 1, "shadow")
+		
+		if game.party:hasMember(self) then
+			game.party:addMember(m, {
+				control="no",
+				type="terror",
+				title="Night Terror",
+				orders = {target=true},
+			})
+		end
+
+	end,
+	activate = function(self, t)
+		game:playSoundNear(self, "talents/heal")
+		local ret = {
+			damage = self:addTemporaryValue("night_terror", t.getDamageBonus(self, t)),
+		}
+		return ret
+	end,
+	deactivate = function(self, t, p)
+		self:removeTemporaryValue("night_terror", p.damage)
+		return true
+	end,
+	info = function(self, t)
+		local damage = t.getDamageBonus(self, t)
+		local summon = t.getSummonTime(self, t)
+		return ([[Increases your damage and resistance penetration on sleeping targets by %d%%.  Additionally every time you slay a sleeping target a Night Terror will be summoned for %d turns.
+		The Night Terror's stats will scale with your mindpower as will the damage bonus to sleeping targets.]]):format(damage, summon)
 	end,
 }
\ No newline at end of file
diff --git a/game/modules/tome/data/talents/psionic/psionic.lua b/game/modules/tome/data/talents/psionic/psionic.lua
index 1a276bc52b45b1106331a750e1f7438fbdbb100b..0a03f15400522f23396559e2b194beeb14e704db 100644
--- a/game/modules/tome/data/talents/psionic/psionic.lua
+++ b/game/modules/tome/data/talents/psionic/psionic.lua
@@ -36,7 +36,7 @@ newTalentType{ allow_random=true, type="psionic/brainstorm", name = "brainstorm"
 
 -- Secret Project...
 -- Solipsist Talent Trees
-newTalentType{ allow_random=true, type="psionic/discharge", name = "discharge", description = "Store and discharge psychic feedback." }
+newTalentType{ allow_random=true, type="psionic/discharge", name = "discharge", description = "Project feedback on the world around you." }
 newTalentType{ allow_random=true, type="psionic/distortion", name = "distortion", description = "Distort reality with your mental energy." }
 newTalentType{ allow_random=true, type="psionic/nightmare", name = "nightmare", description = "Manifest your enemies nightmares." }
 newTalentType{ allow_random=true, type="psionic/psychic-assault", name = "Psychic Assault", description = "Directly attack your opponents minds." }
@@ -45,8 +45,9 @@ newTalentType{ allow_random=true, type="psionic/solipsism", name = "solipsism",
 newTalentType{ allow_random=true, type="psionic/thought-forms", name = "Thought-Forms", description = "Manifest your thoughts as psionic summons." }
 
 -- Generic Solipsist Trees
-newTalentType{ allow_random=true, type="psionic/mentalism", generic = true, name = "mentalism", description = "ESP and other various mental powers." }
-newTalentType{ allow_random=true, type="psionic/feedback", generic = true, name = "feedback", description = "Store and manipulate psychic feedback." }
+newTalentType{ allow_random=true, type="psionic/dreaming", generic = true, name = "dreaming", description = "Manipulate the sleep cycles of yourself and your enemies." }
+newTalentType{ allow_random=true, type="psionic/mentalism", generic = true, name = "mentalism", description = "Various mind based effects." }
+newTalentType{ allow_random=true, type="psionic/feedback", generic = true, name = "feedback", description = "Store feedback as you get damaged and use it to protect and heal your body." }
 newTalentType{ allow_random=true, type="psionic/trance", generic = true, name = "trance", description = "Put your mind into a deep trance." }
 
 newTalentType{ allow_random=true, type="psionic/possession", name = "possession", description = "You have learnt to shed away your body, allowing you to possess any other." }
@@ -165,6 +166,83 @@ function getGemLevel(self)
 	return gem_level
 end
 
+-- Thought Forms really only differ in the equipment they carry, the talents they have, and stat weights
+-- So these function will handle everything else
+function cancelThoughtForms(self)
+	local forms = {self.T_TF_DEFENDER, self.T_TF_WARRIOR, self.T_TF_BOWMAN}
+	for i, t in ipairs(forms) do
+		if self:isTalentActive(t) then
+			self:forceUseTalent(t, {ignore_energy=true})
+		end
+	end
+end
+
+function setupThoughtForm(self, m, x, y)
+	-- Set up some basic stuff
+	m.display = "p" 
+	m.color=colors.YELLOW
+	m.blood_color = colors.YELLOW
+	m.type = "thought-form"
+	m.subtype = "thought-form"
+	m.summoner_gain_exp=true
+	m.faction = self.faction
+	m.no_inventory_access = true -- Uncomment later; just for testing
+	m.rank = 2
+	m.size_category = 3
+	m.infravision = 10
+	m.lite = 1
+	m.no_breath = 1
+	
+	-- Less tedium
+	m.life_regen = 1
+	m.stamina_regen = 1
+	
+	-- Make sure we don't gain anything from leveling
+	m.autolevel = "none"
+	m.unused_stats = 0
+	m.unused_talents = 0
+	m.unused_generics = 0
+	m.unused_talents_types = 0
+	m.exp_worth = 0
+	m.no_points_on_levelup = true
+	m.silent_levelup = true
+	m.level_range = {self.level, self.level}
+
+	-- Try to use stored AI talents to preserve tweaking over multiple summons
+	m.ai_talents = self.stored_ai_talents and self.stored_ai_talents[m.name] or {}
+	m.save_hotkeys = true
+	
+	-- Inheret some attributes
+	if self:getTalentLevel(self.T_TF_UNITY) >=5 then
+		local damage_bonus = self:attr("inc_damage") and self:attr("inc_damage")[engine.DamageType.MIND] or 0
+		m.inc_damage.all = m.inc_damage.all or 0 + damage_bonus
+	end
+	if self:getTalentLevel(self.T_TF_UNITY) >=3 then
+		local save_bonus = self:combatMentalResist(fake)
+		m:attr("combat_physresist", save_bonus)
+		m:attr("combat_mentalresist", save_bonus)
+		m:attr("combat_spellresist", save_bonus)
+	end
+
+	if game.party:hasMember(self) then
+		m.remove_from_party_on_death = true
+		game.party:addMember(m, {
+			control="no",
+			type="thought-form",
+			title="thought-form",
+			orders = {target=true, leash=true, anchor=true, talents=true},
+		})
+	end
+	m:resolve() m:resolve(nil, true)
+	m:forceLevelup(self.level)
+	game.zone:addEntity(game.level, m, "actor", x, y)
+	game.level.map:particleEmitter(x, y, 1, "summon")
+
+	-- Summons never flee
+	m.ai_tactic = m.ai_tactic or {}
+	m.ai_tactic.escape = 0
+end
+
 load("/data/talents/psionic/absorption.lua")
 load("/data/talents/psionic/finer-energy-manipulations.lua")
 load("/data/talents/psionic/mental-discipline.lua")
@@ -181,6 +259,7 @@ load("/data/talents/psionic/grip.lua")
 -- Solipsist
 load("/data/talents/psionic/discharge.lua")
 load("/data/talents/psionic/distortion.lua")
+load("/data/talents/psionic/dreaming.lua")
 load("/data/talents/psionic/mentalism.lua")
 load("/data/talents/psionic/feedback.lua")
 load("/data/talents/psionic/nightmare.lua")
diff --git a/game/modules/tome/data/talents/psionic/psychic-assault.lua b/game/modules/tome/data/talents/psionic/psychic-assault.lua
index eeef0eafcc22a0d2af70749f7b971431f2e93c5a..2908995e5e06e7454210706a45c46c25da9810f9 100644
--- a/game/modules/tome/data/talents/psionic/psychic-assault.lua
+++ b/game/modules/tome/data/talents/psionic/psychic-assault.lua
@@ -17,9 +17,7 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
--- Edge TODO: Sounds, Particles, Talent Icons; All Talents
--- Idea (5:06:11 PM) Neuq: Sunder mind - Hit the enemy for X mind damage + Y mind damage for every stack of Sunder mind he has on him? :)\
--- Idea 2; Cognitive Disonance, sustain - Improves mindpower for applying brain lock and gives your mind damage a chance to apply brain lock equal to X% of the damage dealt
+-- Edge TODO: Sounds, Particles
 
 newTalent{
 	name = "Sunder Mind",
@@ -28,33 +26,70 @@ newTalent{
 	points = 5,
 	cooldown = 2,
 	psi = 5,
+	tactical = { ATTACK = { MIND = 2}, DISABLE = 1},
+	range = 10,
+	requires_target = true,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 150) end,
+	target = function(self, t)
+		return {type="hit", range=self:getTalentRange(t), talent=t}
+	end,
+	action = function(self, t)
+		local tg = self:getTalentTarget(t)
+		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 target = game.level.map(x, y, Map.ACTOR)
+		if not target then return end
+		
+		local dam =self:mindCrit(t.getDamage(self, t))
+		self:project(tg, x, y, DamageType.MIND, {dam=dam, alwaysHit=true})
+		target:setEffect(target.EFF_SUNDER_MIND, 4, {power=dam/10})
+			
+		return true
+	end,
+	info = function(self, t)
+		local damage = t.getDamage(self, t)
+		local power = t.getDamage(self, t) / 10
+		return ([[Cripples the target's mind, inflicting %0.2f mind damage and reducing it's mental save by %d.  This attack always hits and the mental save reduction stacks.
+		The damage and save reduction will scale with your mindpower.]]):
+		format(damDesc(self, DamageType.MIND, (damage)), power)
+	end,
+}
+
+newTalent{
+	name = "Mind Sear",
+	type = {"psionic/psychic-assault", 2},
+	require = psi_wil_req2,
+	points = 5,
+	cooldown = 2,
+	psi = 5,
 	range = 7,
 	direct_hit = true,
 	requires_target = true,
 	target = function(self, t)
 		return {type="beam", range=self:getTalentRange(t), talent=t}
 	end,
-	tactical = { ATTACK = { MIND = 3 } },
+	tactical = { ATTACKAREA = { MIND = 3 } },
 	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 340) end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
-		self:project(tg, x, y, DamageType.MIND, self:mindCrit(self:combatTalentMindDamage(t, 10, 340)), {type="mind"})
+		self:project(tg, x, y, DamageType.MIND, self:mindCrit(t.getDamage(self, t)), {type="mind"})
 		game:playSoundNear(self, "talents/spell_generic")
 		return true
 	end,
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
 		return ([[Sends a telepathic attack, trying to destroy the brains of any target in the beam, doing %0.2f mind damage.
-		The damage will increase with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage))
+		The damage will increase with your mindpower.]]):format(damDesc(self, DamageType.MIND, damage))
 	end,
 }
 
 newTalent{
 	name = "Psychic Lobotomy",
-	type = {"psionic/psychic-assault", 2},
-	require = psi_wil_req2,
+	type = {"psionic/psychic-assault", 3},
+	require = psi_wil_req3,
 	points = 5,
 	cooldown = 6,
 	range = 10,
@@ -62,8 +97,8 @@ newTalent{
 	direct_hit = true,
 	requires_target = true,
 	tactical = { ATTACK = { MIND = 2 }, DISABLE = { confusion = 2 } },
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 250) end,
-	getCunningDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 30) end,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end,
+	getPower = function(self, t) return self:combatTalentMindDamage(t, 20, 60) end,
 	getDuration = function(self, t) return math.floor(self:getTalentLevel(t)) end,
 	no_npc = true,
 	action = function(self, t)
@@ -76,9 +111,8 @@ newTalent{
 		if not target then return nil end
 		local ai = target.ai or nil		
 		
-		self:project(tg, x, y, DamageType.MIND, {dam=self:mindCrit(t.getDamage(self, t))})
 		if target:canBe("confused") then
-			target:setEffect(target.EFF_LOBOTOMIZED, t.getDuration(self, t), {src = self, ai=target.ai, power=t.getCunningDamage(self, t), apply_power=self:combatMindpower()})
+			target:setEffect(target.EFF_LOBOTOMIZED, t.getDuration(self, t), {src=self, dam=t.getDamage(self, t), power=t.getPower(self, t), apply_power=self:combatMindpower()})
 		else
 			game.logSeen(target, "%s resists the lobotomy!", target.name:capitalize())
 		end
@@ -87,72 +121,39 @@ newTalent{
 	end,
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
-		local cunning_damage = t.getCunningDamage(self, t)
+		local cunning_damage = t.getPower(self, t)/2
+		local power = t.getPower(self, t)
 		local duration = t.getDuration(self, t)
-		return ([[Inflicts %0.2f mind damage and cripples the target's higher mental functions, reducing cunning by %d and preventing the target from making tactical decisions for %d turns.
-		The damage and cunning penalty will scale with your Mindpower.]]):
-		format(damDesc(self, DamageType.MIND, (damage)), cunning_damage, duration)
-	end,
-}
-
-newTalent{
-	name = "Mind Sear",
-	type = {"psionic/psychic-assault", 1},
-	require = psi_wil_req1,
-	points = 5,
-	cooldown = 2,
-	psi = 5,
-	range = 7,
-	direct_hit = true,
-	requires_target = true,
-	target = function(self, t)
-		return {type="beam", range=self:getTalentRange(t), talent=t}
-	end,
-	tactical = { ATTACK = { MIND = 3 } },
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 340) end,
-	action = function(self, t)
-		local tg = self:getTalentTarget(t)
-		local x, y = self:getTarget(tg)
-		if not x or not y then return nil end
-		self:project(tg, x, y, DamageType.MIND, self:mindCrit(self:combatTalentMindDamage(t, 10, 340)), {type="mind"})
-		game:playSoundNear(self, "talents/spell_generic")
-		return true
-	end,
-	info = function(self, t)
-		local damage = t.getDamage(self, t)
-		return ([[Sends a telepathic attack, trying to destroy the brains of any target in the beam, doing %0.2f mind damage.
-		The damage will increase with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage))
+		return ([[Inflicts %0.2f mind damage and cripples the target's higher mental functions, reducing cunning by %d and confusing (%d%% power) the target for %d turns.
+		The damage, cunning penalty, and confusion power will scale with your mindpower.]]):
+		format(damDesc(self, DamageType.MIND, (damage)), cunning_damage, power, duration)
 	end,
 }
 
 newTalent{
-	name = "Brain Lock",  -- sustain, gives chance to brain lock enemies when mental damage is applied
-	type = {"psionic/psychic-assault", 1},
-	require = psi_wil_req1,
+	name = "Synaptic Static",
+	type = {"psionic/psychic-assault", 4},
+	require = psi_wil_req4,
 	points = 5,
-	cooldown = 2,
-	psi = 5,
-	range = 7,
+	cooldown = 10,
+	psi = 25,
+	range = 0,
 	direct_hit = true,
 	requires_target = true,
-	target = function(self, t)
-		return {type="beam", range=self:getTalentRange(t), talent=t}
-	end,
-	tactical = { ATTACK = { MIND = 3 } },
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 340) end,
+	radius = function(self, t) return math.min(10, 3 + math.ceil(self:getTalentLevel(t))) end,
+	target = function(self, t) return {type="ball", radius=self:getTalentRadius(t), range=self:getTalentRange(t), talent=t, selffire=false} end,
+	tactical = { ATTACKAREA = { MIND = 3 }, DISABLE=1 },
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
-		local x, y = self:getTarget(tg)
-		if not x or not y then return nil end
-		self:project(tg, x, y, DamageType.MIND, self:mindCrit(self:combatTalentMindDamage(t, 10, 340)), {type="mind"})
+		self:project(tg, self.x, self.y, DamageType.MIND, {dam=self:mindCrit(self:combatTalentMindDamage(t, 20, 200)), crossTierChance=100}, {type="mind"})
 		game:playSoundNear(self, "talents/spell_generic")
 		return true
 	end,
 	info = function(self, t)
 		local damage = t.getDamage(self, t)
-		return ([[Sends a telepathic attack, trying to destroy the brains of any target in the beam, doing %0.2f mind damage.
-		The damage will increase with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage))
+		local radius = self:getTalentRadius(t)
+		return ([[Sends out a blast of telepathic static in a %d radius, inflicting %0.2f mind damage.  This attack can brain-lock affected targets.
+		The damage will increase with your mindpower.]]):format(radius, damDesc(self, DamageType.MIND, damage))
 	end,
-}
-
--- Idea, Brain Rupture
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/talents/psionic/slumber.lua b/game/modules/tome/data/talents/psionic/slumber.lua
index 8c7a2406d542973aee9a028556f25884548b19ab..8de572ec893535d54dc2498c934620f7798ea651 100644
--- a/game/modules/tome/data/talents/psionic/slumber.lua
+++ b/game/modules/tome/data/talents/psionic/slumber.lua
@@ -17,21 +17,20 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
--- Edge TODO: Sounds, Particles, Talent Icons; All Talents
+-- Edge TODO: Sounds, Particles,
 
 newTalent{
-	name = "Sleep",
+	name = "Slumber",
 	type = {"psionic/slumber", 1},
 	points = 5, 
 	require = psi_wil_req1,
 	cooldown = 8,
-	psi = 5,
-	tactical = { DISABLE = 2},
+	psi = 10,
+	tactical = { DISABLE = {sleep = 2} },
 	direct_hit = true,
 	requires_target = true,
 	range = function(self, t) return 5 + math.min(5, self:getTalentLevelRaw(t)) end,
-	radius = function(self, t) return 1 + math.floor(self:getTalentLevel(t)/4) end,
-	target = function(self, t) return {type="ball", radius=self:getTalentRadius(t), range=self:getTalentRange(t), talent=t} end,
+	target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end,
 	getDuration = function(self, t) return 2 + math.ceil(self:getTalentLevel(t)/2) end,
 	getInsomniaDuration = function(self, t)
 		local t = self:getTalentFromId(self.T_SANDMAN)
@@ -39,7 +38,7 @@ newTalent{
 		return 10 - reduction
 	end,
 	getSleepPower = function(self, t) 
-		local power = self:combatTalentMindDamage(t, 10, 50)
+		local power = self:combatTalentMindDamage(t, 10, 100)
 		if self:knowTalent(self.T_SANDMAN) then
 			local t = self:getTalentFromId(self.T_SANDMAN)
 			power = power + t.getSleepPowerBonus(self, t)
@@ -47,162 +46,199 @@ newTalent{
 		return power
 	end,
 	doContagiousSlumber = function(self, target, p, t)
-		local tg = {type="ball", radius=self:getTalentRadius(t), talent=t}
+		local tg = {type="ball", radius=1, talent=t}
 		self:project(tg, target.x, target.y, function(tx, ty)
-			local target = game.level.map(tx, ty, Map.ACTOR)
-			if target and self:reactionToward(target) < 0 and rng.percent(p.contagious) and target:canBe("sleep") and not target:attr("sleep") then
-				target:setEffect(target.EFF_SLEEP, math.floor(p.dur/2), {src=self, power=p.power, contagious=p.contagious/2, insomnia=math.ceil(p.insomnia/2), no_ct_effect=true, apply_power=self:combatMindpower()})
+			local t2 = game.level.map(tx, ty, Map.ACTOR)
+			if t2 and target_two ~= target and rng.percent(p.contagious) and t2:canBe("sleep") then
+				t2:setEffect(t2.EFF_SLEEP, math.floor(p.dur/2), {src=self, power=p.power/10, waking=p.waking, insomnia=math.ceil(p.insomnia/2), no_ct_effect=true, apply_power=self:combatMindpower()})
 			end
 		end)
 	end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
-		local x, y = self:getTarget(tg)
+		local x, y, target = self:getTarget(tg)
 		if not x or not y then return nil end
+		local _ _, x, y = self:canProject(tg, x, y)
+		target = game.level.map(x, y, Map.ACTOR)
+		if not target then return nil end
 
 		--Contagious?
 		local is_contagious = 0
-		if self:getTalentLevel(self.T_SANDMAN) > 5 then
+		if self:getTalentLevel(t) >= 5 then
 			is_contagious = 25
 		end
-		--Sandman?
+		--Restless?
+		local is_waking =0
+		if self:knowTalent(self.T_RESTLESS_NIGHT) then
+			local t = self:getTalentFromId(self.T_RESTLESS_NIGHT)
+			is_waking = t.getDamage(self, t)
+		end
+		
 		local power = self:mindCrit(t.getSleepPower(self, t))
-		self:project(tg, x, y, function(tx, ty)
-			local target = game.level.map(tx, ty, Map.ACTOR)
-			if target and not target:attr("sleep") then
-				if target:canBe("sleep") then
-					target:setEffect(target.EFF_SLEEP, t.getDuration(self, t), {src=self, power=power, contagious=is_contagious, insomnia=t.getInsomniaDuration(self, t), no_ct_effect=true, apply_power=self:combatMindpower()})
-				else
-					game.logSeen(self, "%s resists the sleep!", target.name:capitalize())
-				end
-			end
-		end)
+		if target:canBe("sleep") then
+			target:setEffect(target.EFF_SLUMBER, t.getDuration(self, t), {src=self, power=power, waking=is_waking, contagious=is_contagious, insomnia=t.getInsomniaDuration(self, t), no_ct_effect=true, apply_power=self:combatMindpower()})
+		else
+			game.logSeen(self, "%s resists the sleep!", target.name:capitalize())
+		end
 		return true
 	end,
 	info = function(self, t)
-		local radius = self:getTalentRadius(t)
 		local duration = t.getDuration(self, t)
 		local power = t.getSleepPower(self, t)
 		local insomnia = t.getInsomniaDuration(self, t)
-		return([[Puts targets in a radius of %d to sleep for %d turns, rendering them unable to act.  Every %d points of damage the target suffers will reduce the effect duration by one turn.
-		When Sleep ends the target will suffer from Insomnia for %d turns, rendering them resistant to Sleep effects.
-		The damage threshold will scale with your mindpower.]]):format(radius, duration, power, insomnia)
+		return([[Puts the target into a deep sleep for %d turns, rendering it unable to act.  Every %d points of damage the target suffers will reduce the effect duration by one turn.
+		When Slumber ends the target will suffer from Insomnia for %d turns, rendering them resistant to sleep effects.
+		At talent level 5 your Slumber will become contagious and has a 25%% chance to spread Sleep to nearby targets each turn.
+		The damage threshold will scale with your mindpower.]]):format(duration, power, insomnia)
 	end,
 }
 
 newTalent{
-	name = "Sandman",
+	name = "Restless Night",
 	type = {"psionic/slumber", 2},
 	points = 5, 
 	require = psi_wil_req2,
 	mode = "passive",
-	getSleepPowerBonus = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
-	getInsomniaReduction = function(self, t) return math.min(8, math.floor(self:getTalentLevel(self.T_SANDMAN))) end,
+	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 200) end,
 	info = function(self, t)
-		local power_bonus = t.getSleepPowerBonus(self, t)
-		local reduction = t.getInsomniaReduction(self, t)
-		return([[Increases the amount of damage you can deal to sleeping targets before rousing them by %d and reduces the duration of the Insomnia effect by %d turns.
-		At talent level 5 the Sleep will become contagious and has a 25%% chance to spread to nearby targets each turn.
-		These effects will be directly reflected in the Sleep talent description.
-		The damage threshold bonus will scale with your mindpower.]]):format(power_bonus, reduction)
+		local damage = t.getDamage(self, t)
+		return([[Targets you have slept now take %0.2f mind damage upon waking.
+		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.MIND, (damage)))
 	end,
 }
 
-
 newTalent{
-	name = "Contagious Slumber",
+	name = "Sandman",
 	type = {"psionic/slumber", 3},
-	points = 5,
+	points = 5, 
 	require = psi_wil_req3,
-	cooldown = 10,
-	tactical = { ATTACKAREA = {PHYSICAL = 2}, DISABLE = { knockback = 2 }, },
-	range = 0,
-	radius = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
-	direct_hit = true,
-	requires_target = true,
-	target = function(self, t)
-		return {type="ball", range=self:getTalentRange(t), talent=t}
-	end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 230) end,
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return not self:hasEffect(self.EFF_REGENERATION) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 50
-		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 50
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
-	end,
-	action = function(self, t)
-		local tg = self:getTalentTarget(t)
-		if not x or not y then return nil end
-		
-		local damage = math.min(self.psionic_feedback, t.getDamage(self, t))
-		self:project(tg, x, y, DamageType.MINDKNOCKBACK, self:mindCrit(damage))
-		self.psionic_feedback = self.psionic_feedback - damage
-		
-		return true
-	end,
+	mode = "passive",
+	getSleepPowerBonus = function(self, t) return self:combatTalentMindDamage(t, 5, 25) end,
+	getInsomniaReduction = function(self, t) return math.min(8, math.floor(self:getTalentLevel(self.T_SANDMAN))) end,
 	info = function(self, t)
-		local damage = t.getDamage(self, t)
-		local radius = self:getTalentRadius(t)
-		return ([[Activate to convert up to %0.2f of stored feedback into a blast of kinetic energy.  Targets out to a radius of %d will suffer physical damage and may be knocked back.
-		Learning this talent will increase the amount of feedback you can store by 50 (first talent point only).
-		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), radius)
+		local power_bonus = t.getSleepPowerBonus(self, t)
+		local reduction = t.getInsomniaReduction(self, t)
+		return([[Increases the amount of damage you can deal to sleeping targets before reducing the effect duration by %d and reduces the duration of all Insomnia effects by %d turns.
+		These effects will be directly reflected in the appropriate talent descriptions.
+		The damage threshold bonus will scale with your mindpower.]]):format(power_bonus, reduction)
 	end,
 }
 
 newTalent{
-	name = "Sleep4",
+	name = "Dreamscape",
 	type = {"psionic/slumber", 4},
 	points = 5, 
 	require = psi_wil_req4,
-	cooldown = 15,
-	tactical = { DEFEND = 2, ATTACK = {MIND = 2}},
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return true end,
-	getShieldPower = function(self, t) return self:combatTalentMindDamage(t, 20, 300) end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 100
+	cooldown = 24,
+	psi = 40,
+	tactical = { DISABLE = {sleep = 2} },
+	direct_hit = true,
+	requires_target = true,
+	range = function(self, t) return 5 + math.min(5, self:getTalentLevelRaw(t)) end,
+	target = function(self, t) return {type="hit", range=self:getTalentRange(t), talent=t} end,
+	getDuration = function(self, t) return 10 + math.ceil(self:getTalentLevel(t) * 4) end,
+	getPower = function(self, t) return self:combatTalentMindDamage(t, 10, 100) end,
+	on_pre_use = function(self, t, silent) if self:attr("is_psychic_projection") then if not silent then game.logPlayer(self, "You feel it unwise to travel to the dreamscape in such a fragile form.") end return false end return true end,
+	action = function(self, t)
+		if game.zone.is_dream_scape then
+			game.logPlayer(self, "This talent can not be used from within the Dreamscape.")
+			return
 		end
-		return true
-	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 100
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
+		if game.zone.no_planechange then
+			game.logPlayer(self, "This talent can not be used here.")
+			return
 		end
-		return true
-	end,
-	action = function(self, t)
-		local power = math.min(self.psionic_feedback, t.getShieldPower(self, t))
-		self:setEffect(self.EFF_RESONANCE_SHIELD, 10, {power = self:mindCrit(power), dam = t.getDamage(self, t)})
-		self.psionic_feedback = self.psionic_feedback - power
+		if not self:canBe("planechange") then
+			game.logPlayer(self, "The effect fizzles...")
+			return
+		end
+	
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local tx, ty, target = self:getTarget(tg)
+		if not tx or not ty or not target then return nil end
+		local _ _, tx, ty = self:canProject(tg, tx, ty)
+		if not tx or not ty or not target then return nil end
+		target = game.level.map(tx, ty, Map.ACTOR)
+		if not tx or not ty or not target then return nil end
+		if not (target.player and target.game_ender) and not (self.player and self.game_ender) then return nil end
+		if target == self then return end
+		if not (target and target:attr("sleep")) then 
+			game.logPlayer(self, "Your target must be sleeping in order to enter it's dreamscape.")
+			return nil
+		end
+		
+		game:onTickEnd(function()
+			if self:attr("dead") then return end
+			local oldzone = game.zone
+			local oldlevel = game.level
+			
+			-- Clean up thought-forms
+			cancelThoughtForms(self)
+			
+			-- Remove them before making the new elvel, this way party memebrs are not removed from the old
+			if oldlevel:hasEntity(self) then oldlevel:removeEntity(self) end
+			if oldlevel:hasEntity(target) then oldlevel:removeEntity(target) end
+						
+			oldlevel.no_remove_entities = true
+			local zone = mod.class.Zone.new("dreamscape-talent")
+			local level = zone:getLevel(game, 1, 0)
+			oldlevel.no_remove_entities = nil
+			
+			level:addEntity(self)
+			level:addEntity(target)
+
+			level.source_zone = oldzone
+			level.source_level = oldlevel
+			game.zone = zone
+			game.level = level
+			game.zone_name_s = nil
+			
+			local x1, y1 = util.findFreeGrid(4, 6, 20, true, {[Map.ACTOR]=true})
+			if x1 then
+				self:move(x1, y1, true)
+				game.level.map:particleEmitter(x1, y1, 1, "teleport")
+			end
+			local x2, y2 = util.findFreeGrid(8, 6, 20, true, {[Map.ACTOR]=true})
+			if x2 then
+				target:move(x2, y2, true)
+			end
+		
+			target:setTarget(self)
+			target.dream_plane_trapper = self
+			target.dream_plane_on_die = target.on_die
+			target.on_die = function(self, ...)
+				self.dream_plane_trapper:removeEffect(self.EFF_DREAMSCAPE)
+				local args = {...}
+				game:onTickEnd(function()
+					if self.dream_plane_on_die then self:dream_plane_on_die(unpack(args)) end
+					self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil
+				end)
+			end
+
+			self.dream_plane_on_die = self.on_die
+			self.on_die = function(self, ...)
+				self:removeEffect(self.EFF_DREAMSCAPE)
+				local args = {...}
+				game:onTickEnd(function()
+					if self.dream_plane_on_die then self:dream_plane_on_die(unpack(args)) end
+					self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil
+				--	if not game.party:hasMember(self) then world:gainAchievement("FEARSCAPE", game:getPlayer(true)) end
+				end)
+			end
+
+			game.logPlayer(game.player, "#LIGHT_BLUE#You are taken to the Dreamscape!")
+		end)
+		
+		local power = self:mindCrit(t.getPower(self, t))
+		self:setEffect(self.EFF_DREAMSCAPE, t.getDuration(self, t), {target=target, power=power, projections_killed=0, x=self.x, y=self.y, tx=target.x, ty=target.y})
 		return true
 	end,
 	info = function(self, t)
-		local shield_power = t.getShieldPower(self, t)
-		local damage = t.getDamage(self, t)
-		return ([[Activate to conver up to %0.2f feedback into a resonance shield that will absorb 50%% of all damage you take and inflict %0.2f mind damage to melee attackers.
-		Learning this talent will increase the amount of feedback you can store by 100 (first talent point only).
-		The conversion ratio will scale with your mindpower and the effect lasts up to ten turns.]]):format(shield_power, damDesc(self, DamageType.MIND, damage))
+		local duration = t.getDuration(self, t)
+		local power = t.getPower(self, t)
+		return([[Enter a sleeping target's dreams for %d turns.  While in the dreamscape you'll encounter the target's invulnerable sleeping form as well as dream projections that it will spawn every four turns to defend it's mind.  When the dreamscape ends the target's life will be reduced by 20%% and it will to be brainlocked for one turn for each projection destroyed.
+		Lucid dreamer's will spawn projections every two turns instead of every four and their projections will deal more damage (generally projections have a 50%% penalty to all damage).
+		In the dreamscape your damage will be improved by %d%%.
+		The damage bonus will improve with your mindpower.]]):format(duration, power)
 	end,
-}
\ No newline at end of file
+}
diff --git a/game/modules/tome/data/talents/psionic/solipsism.lua b/game/modules/tome/data/talents/psionic/solipsism.lua
index 20b62e8f39fbc577d6dd1e9070bf1c25e1501086..f15d98f521cb71e6609dd6c8d5296070bd568982 100644
--- a/game/modules/tome/data/talents/psionic/solipsism.lua
+++ b/game/modules/tome/data/talents/psionic/solipsism.lua
@@ -35,14 +35,12 @@ newTalent{
 			self.life_rating = math.ceil(self.life_rating/2)
 			self.psi_rating =  self.psi_rating + 10
 		end
-		return true
 	end,
 	on_unlearn = function(self, t)
 		if not self:knowTalent(t) then
 			self:incMaxPsi(-50)
 			self.solipsism_threshold = self.solipsism_threshold - 0.2
 		end
-		return true
 	end,
 	info = function(self, t)
 		local conversion_ratio = t.getConversionRatio(self, t)
@@ -64,14 +62,12 @@ newTalent{
 			self:incMaxPsi(50)
 			self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1
 		end
-		return true
 	end,
 	on_unlearn = function(self, t)
 		if not self:knowTalent(t) then
 			self:incMaxPsi(-50)
 			self.solipsism_threshold = self.solipsism_threshold - 0.1
 		end
-		return true
 	end,
 	info = function(self, t)
 		local ratio = t.getBalanceRatio(self, t) * 100
@@ -86,14 +82,13 @@ newTalent{
 	points = 5, 
 	require = psi_wil_req3,
 	mode = "passive",
-	getClarityThreshold = function(self, t) return math.max(0.5, 1 - self:getTalentLevelRaw(t) / 10) end,
+	getClarityThreshold = function(self, t) return math.max(0.5, 1 - self:getTalentLevel(t) / 15) end,
 	on_learn = function(self, t)
 		self.clarity_threshold = t.getClarityThreshold(self, t)
 		if self:getTalentLevelRaw(t) == 1 then
 			self:incMaxPsi(50)
 			self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1
 		end
-		return true
 	end,
 	on_unlearn = function(self, t)
 		if not self:knowTalent(t) then
@@ -103,7 +98,6 @@ newTalent{
 		else
 			self.clarity_threshold = t.getClarityThreshold(self, t)
 		end
-		return true
 	end,
 	info = function(self, t)
 		local threshold = t.getClarityThreshold(self, t)
@@ -124,14 +118,12 @@ newTalent{
 			self:incMaxPsi(50)
 			self.solipsism_threshold = (self.solipsism_threshold or 0) + 0.1
 		end
-		return true
 	end,
 	on_unlearn = function(self, t)
 		if not self:knowTalent(t) then
 			self:incMaxPsi(-50)
 			self.solipsism_threshold = self.solipsism_threshold - 0.1
 		end
-		return true
 	end,
 	doDismissalOnHit = function(self, value, src, t)
 		local saving_throw = self:mindCrit(t.getSavePercentage(self, t))
diff --git a/game/modules/tome/data/talents/psionic/thought-forms.lua b/game/modules/tome/data/talents/psionic/thought-forms.lua
index 5ca2ce7c5cfdf090b8c1c6b8fb286a2775bc71b2..700511fef6f478c4261082b1ec3cc33589156508 100644
--- a/game/modules/tome/data/talents/psionic/thought-forms.lua
+++ b/game/modules/tome/data/talents/psionic/thought-forms.lua
@@ -17,213 +17,556 @@
 -- Nicolas Casalini "DarkGod"
 -- darkgod@te4.org
 
--- Edge TODO: Sounds, Particles, Talent Icons; All Talents
+-- Edge TODO: Sounds, Particles,
 
+-- Thought Forms
 newTalent{
-	name = "Thought Form1",
-	type = {"psionic/thought-forms", 1},
+	name = "Thought-Form: Warrior",
+	short_name = "TF_WARRIOR",
+	type = {"psionic/other", 1},
 	points = 5, 
 	require = psi_wil_req1,
-	cooldown = 5,
-	tactical = { DISABLE = 2},
-	range = 0,
-	direct_hit = true,
-	requires_target = true,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 150) end,
-	radius = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
-	target = function(self, t)
-		return {type="cone", range=self:getTalentRange(t), radius=self:getTalentRadius(t), selffire=false}
-	end,
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return true end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 100
-		end
-		return true
+	sustain_psi = 20,
+	mode = "sustained",
+	no_sustain_autoreset = true,
+	cooldown = 24,
+	range = function(self, t)
+		local t = self:getTalentFromId(self.T_OVER_MIND)
+		return 10 + t.getRangeBonus(self, t)
 	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 100
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
-		end
-		return true
+	getStatBonus = function(self, t) 
+		local t = self:getTalentFromId(self.T_THOUGHT_FORMS)
+		return t.getStatBonus(self, t)
 	end,
-	action = function(self, t)
-		local tg = self:getTalentTarget(t)
-		local x, y = self:getTarget(tg)
+	activate = function(self, t)
+		cancelThoughtForms(self)
 		
-		local damage = math.min(self.psionic_feedback, t.getDamage(self, t))
-		self:project(tg, x, y, DamageType.MIND, {dam=self:mindCrit(damage), crossTierChance=math.max(100, damage)})
+		-- Find space
+		local x, y = util.findFreeGrid(self.x, self.y, 5, true, {[Map.ACTOR]=true})
+		if not x then
+			game.logPlayer(self, "Not enough space to summon!")
+			return
+		end
+		
+		-- Do our stat bonuses here so we only roll for crit once		
+		local stat_bonus = math.floor(self:mindCrit(t.getStatBonus(self, t)))
+	
+		local NPC = require "mod.class.NPC"
+		local m = NPC.new{
+			name = "thought-forged warrior", summoner = self, 
+			desc = [[A thought-forged warrior wielding a massive hammer and clad in heavy armor.  It appears ready for battle.]],
+			body = { INVEN = 10, MAINHAND = 1, BODY = 1, HANDS = 1, FEET = 1},
+			-- Make a moddable tile
+			resolvers.generic(function(e)
+				if e.summoner.female then
+					e.female = true
+				end
+				e.image = e.summoner.image
+				e.moddable_tile = e.summoner.moddable_tile and e.summoner.moddable_tile or nil
+				e.moddable_tile_base = e.summoner.moddable_tile_base and e.summoner.moddable_tile_base or nil
+				e.moddable_tile_ornament = e.summoner.moddable_tile_ornament and e.summoner.moddable_tile_ornament or nil
+			end),
+			-- Disable our sustain when we die
+			on_die = function(self)
+				game:onTickEnd(function() 
+					if self.summoner:isTalentActive(self.summoner.T_TF_WARRIOR) then
+						self.summoner:forceUseTalent(self.summoner.T_TF_WARRIOR, {ignore_energy=true})
+					end
+					if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then
+						self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true})
+					end
+				end)
+			end,
+			-- Keep them on a leash
+			on_act = function(self)
+				local t = self.summoner:getTalentFromId(self.summoner.T_TF_WARRIOR)
+				if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then
+					local Map = require "engine.Map"
+					local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true})
+					if not x then
+						return
+					end
+					-- Clear it's targeting on teleport
+					self.ai_target.actor = nil
+					self:move(x, y, true)
+					game.level.map:particleEmitter(x, y, 1, "summon")
+				end
+			end,
+			
+			ai = "summoned", ai_real = "tactical",
+			ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 },
+			ai_tactic = resolvers.tactic("melee"),
+			
+			max_life = resolvers.rngavg(100,110),
+			life_rating = 15,
+			combat_armor = 0, combat_def = 0,
+			inc_stats = {
+				str = stat_bonus,
+				dex = stat_bonus / 2,
+				con = stat_bonus / 2,
+			},
+			
+			resolvers.talents{ 
+				[Talents.T_ARMOUR_TRAINING]= 3,
+				[Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10),
+				[Talents.T_WEAPONS_MASTERY]= math.ceil(self.level/10),
+				
+				[Talents.T_RUSH]= math.ceil(self.level/10),
+				[Talents.T_DEATH_DANCE]= math.ceil(self.level/10),
+				[Talents.T_BERSERKER]= math.ceil(self.level/10),
+
+				[Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+			},
+			resolvers.equip{
+				{type="weapon", subtype="greatmaul", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="heavy", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+			},
+			resolvers.sustains_at_birth(),
+		}
+
+		setupThoughtForm(self, m, x, y)
+
+		game:playSoundNear(self, "talents/spell_generic")
 		
-		self.psionic_feedback = self.psionic_feedback - damage
-							
+		local ret = {
+			summon = m
+		}
+		if self:knowTalent(self.T_TF_UNITY) then
+			local t = self:getTalentFromId(self.T_TF_UNITY)
+			ret.power = self:addTemporaryValue("combat_mindpower", t.getOffensePower(self, t))
+		end
+		return ret
+	end,
+	deactivate = function(self, t, p)
+		p.summon:die(p.summon)
+		if p.power then self:removeTemporaryValue("combat_mindpower", p.power) end
 		return true
 	end,
 	info = function(self, t)
-		local damage = t.getDamage(self, t)
-		local radius = self:getTalentRadius(t)
-		return ([[You now store damage you take from outside sources as psionic feedback.  Activate to discharge up to %0.2f feedback in a %d radius cone.  Targets in the area will suffer mind damage and may be brain locked by this attack.
-		Learning this talent will increase the amount of feedback you can store by 100 (first talent point only).
-		The damage will scale with your mindpower.]]):format(damage, radius)
+		local stat = t.getStatBonus(self, t)
+		return ([[Forge a warrior wielding a greatmaul from your thoughts.  The warrior learns weapon mastery, combat accuracy, berserker, death dance, and rush as it levels up and has %d improved strength, %d dexterity, and %d constitution.
+		The stat bonuses will improve with your mindpower.]]):format(stat, stat/2, stat/2)
 	end,
 }
 
 newTalent{
-	name = "Thought Form2",
-	type = {"psionic/thought-forms", 2},
+	name = "Thought-Form: Defender",
+	short_name = "TF_DEFENDER",
+	type = {"psionic/other", 1},
 	points = 5, 
-	require = psi_wil_req2,
-	mode = "sustained",
+	require = psi_wil_req1,
 	sustain_psi = 20,
-	cooldown = 18,
-	tactical = { BUFF = 2 },
-	getMaxOverflow = function(self, t) return self.psionic_feedback_max * (self:combatTalentMindDamage(t, 20, 100)/100) end,
-	radius = function(self, t) return math.ceil(self:getTalentLevel(t)/2) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 50
-		end
-		return true
+	mode = "sustained",
+	no_sustain_autoreset = true,
+	cooldown = 24,
+	range = function(self, t)
+		local t = self:getTalentFromId(self.T_OVER_MIND)
+		return 10 + t.getRangeBonus(self, t)
 	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 50
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
+	getStatBonus = function(self, t) 
+		local t = self:getTalentFromId(self.T_THOUGHT_FORMS)
+		return t.getStatBonus(self, t)
+	end,
+	activate = function(self, t)
+		cancelThoughtForms(self)
+		
+		-- Find space
+		local x, y = util.findFreeGrid(self.x, self.y, 5, true, {[Map.ACTOR]=true})
+		if not x then
+			game.logPlayer(self, "Not enough space to summon!")
+			return
+		end
+		
+		-- Do our stat bonuses here so we only roll for crit once	
+		local stat_bonus = math.floor(self:mindCrit(t.getStatBonus(self, t)))
+	
+		local NPC = require "mod.class.NPC"
+		local m = NPC.new{
+			name = "thought-forged defender", summoner = self,
+			desc = [[A thought-forged defender clad in massive armor.  It wields a sword and shield and appears ready for battle.]],
+			body = { INVEN = 10, MAINHAND = 1, OFFHAND = 1, BODY = 1, HANDS = 1, FEET = 1},
+			-- Make a moddable tile
+			resolvers.generic(function(e)
+				if e.summoner.female then
+					e.female = true
+				end
+				e.image = e.summoner.image
+				e.moddable_tile = e.summoner.moddable_tile and e.summoner.moddable_tile or nil
+				e.moddable_tile_base = e.summoner.moddable_tile_base and e.summoner.moddable_tile_base or nil
+				e.moddable_tile_ornament = e.summoner.moddable_tile_ornament and e.summoner.moddable_tile_ornament or nil
+			end),
+			-- Disable our sustain when we die
+			on_die = function(self)
+				game:onTickEnd(function() 
+					if self.summoner:isTalentActive(self.summoner.T_TF_DEFENDER) then
+						self.summoner:forceUseTalent(self.summoner.T_TF_DEFENDER, {ignore_energy=true})
+					end
+					if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then
+						self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true})
+					end
+				end)
+			end,
+			-- Keep them on a leash
+			on_act = function(self)
+				local t = self.summoner:getTalentFromId(self.summoner.T_TF_DEFENDER)
+				if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then
+					local Map = require "engine.Map"
+					local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true})
+					if not x then
+						return
+					end
+					-- Clear it's targeting on teleport
+					self.ai_target.actor = nil
+					self:move(x, y, true)
+					game.level.map:particleEmitter(x, y, 1, "summon")
+				end
+			end,		
+			
+			ai = "summoned", ai_real = "tactical",
+			ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 },
+			ai_tactic = resolvers.tactic("tank"),
+			
+			max_life = resolvers.rngavg(100,110),
+			life_rating = 15,
+			combat_armor = 0, combat_def = 0,
+			inc_stats = {
+				str = stat_bonus / 2,
+				dex = stat_bonus / 2,
+				con = stat_bonus,
+			},
+			
+			resolvers.talents{ 
+				[Talents.T_ARMOUR_TRAINING]= 3 + math.ceil(self.level/10),
+				[Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10),
+				[Talents.T_WEAPONS_MASTERY]= math.ceil(self.level/10),
+				
+				[Talents.T_SHIELD_PUMMEL]= math.ceil(self.level/10),
+				[Talents.T_SHIELD_WALL]= math.ceil(self.level/10),
+				
+
+				[Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+
+			},
+			resolvers.equip{
+				{type="weapon", subtype="longsword", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="shield", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="massive", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+			},
+			resolvers.sustains_at_birth(),
+		}
+
+		setupThoughtForm(self, m, x, y)
+
+		game:playSoundNear(self, "talents/spell_generic")
+		
+		local ret = {
+			summon = m
+		}
+		if self:knowTalent(self.T_TF_UNITY) then
+			local t = self:getTalentFromId(self.T_TF_UNITY)
+			ret.resist = self:addTemporaryValue("resists", {all= t.getDefensePower(self, t)})
 		end
+		return ret
+	end,
+	deactivate = function(self, t, p)
+		p.summon:die(p.summon)
+		if p.resist then self:removeTemporaryValue("resists", p.resist) end
 		return true
 	end,
-	doOverflowDischarge = function(self, t)
-		local tg = {type="ball", range=0, radius=self:getTalentRadius(t), selffire=false, friendlyfire=false}
-		local damage = self.psionic_overflow
-		self:project(tg, self.x, self.y, DamageType.MIND, self:mindCrit(damage))
-		-- Lose remaining overflow
-		self.psionic_overflow = nil
+	info = function(self, t)
+		local stat = t.getStatBonus(self, t)
+		return ([[Forge a defender wielding a sword and shield from your thoughts.  The solider learns armor training, weapon mastery, combat accuracy, shield pummel, and shield wall as it levels up and has %d improved strength, %d dexterity, and %d constitution.
+		The stat bonuses will improve with your mindpower.]]):format(stat/2, stat/2, stat)
+	end,
+}
+
+newTalent{
+	name = "Thought-Form: Bowman",
+	short_name = "TF_BOWMAN",
+	type = {"psionic/other", 1},
+	points = 5, 
+	require = psi_wil_req1,
+	sustain_psi = 20,
+	mode = "sustained",
+	no_sustain_autoreset = true,
+	cooldown = 24,
+	range = function(self, t)
+		local t = self:getTalentFromId(self.T_OVER_MIND)
+		return 10 + t.getRangeBonus(self, t)
+	end,
+	getStatBonus = function(self, t) 
+		local t = self:getTalentFromId(self.T_THOUGHT_FORMS)
+		return t.getStatBonus(self, t)
 	end,
 	activate = function(self, t)
-		game:playSoundNear(self, "talents/flame")
-		return {
-			ov = self:addTemporaryValue("psionic_overflow_max", t.getMaxOverflow(self, t)),
+		cancelThoughtForms(self)
+		
+		-- Find space
+		local x, y = util.findFreeGrid(self.x, self.y, 5, true, {[Map.ACTOR]=true})
+		if not x then
+			game.logPlayer(self, "Not enough space to summon!")
+			return
+		end
+		
+		-- Do our stat bonuses here so we only roll for crit once	
+		local stat_bonus = math.floor(self:mindCrit(t.getStatBonus(self, t)))
+	
+		local NPC = require "mod.class.NPC"
+		local m = NPC.new{
+			name = "thought-forged bowman", summoner = self,
+			desc = [[A thought-forged bowman.  It appears ready for battle.]],
+			body = { INVEN = 10, MAINHAND = 1, BODY = 1, QUIVER=1, HANDS = 1, FEET = 1},
+			-- Make a moddable tile
+			resolvers.generic(function(e)
+				if e.summoner.female then
+					e.female = true
+				end
+				e.image = e.summoner.image
+				e.moddable_tile = e.summoner.moddable_tile and e.summoner.moddable_tile or nil
+				e.moddable_tile_base = e.summoner.moddable_tile_base and e.summoner.moddable_tile_base or nil
+				e.moddable_tile_ornament = e.summoner.moddable_tile_ornament and e.summoner.moddable_tile_ornament or nil
+			end),
+			-- Disable our sustain when we die
+			on_die = function(self)
+				game:onTickEnd(function() 
+					if self.summoner:isTalentActive(self.summoner.T_TF_BOWMAN) then
+						self.summoner:forceUseTalent(self.summoner.T_TF_BOWMAN, {ignore_energy=true})
+					end
+					if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then
+						self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true})
+					end
+				end)
+			end,
+			-- Keep them on a leash
+			on_act = function(self)
+				local t = self.summoner:getTalentFromId(self.summoner.T_TF_BOWMAN)
+				if not game.level:hasEntity(self.summoner) or core.fov.distance(self.x, self.y, self.summoner.x, self.summoner.y) > self.summoner:getTalentRange(t) then
+					local Map = require "engine.Map"
+					local x, y = util.findFreeGrid(self.summoner.x, self.summoner.y, 5, true, {[Map.ACTOR]=true})
+					if not x then
+						return
+					end
+					-- Clear it's targeting on teleport
+					self.ai_target.actor = nil
+					self:move(x, y, true)
+					game.level.map:particleEmitter(x, y, 1, "summon")
+				end
+			end,
+
+			ai = "summoned", ai_real = "tactical",
+			ai_state = { ai_move="move_dmap", talent_in=3, ally_compassion=10 },
+			ai_tactic = resolvers.tactic("ranged"),
+			
+			max_life = resolvers.rngavg(100,110),
+			life_rating = 12,
+			combat_armor = 0, combat_def = 0,
+			inc_stats = {
+				str = stat_bonus / 2,
+				dex = stat_bonus,
+				con = stat_bonus / 2,
+			},
+			
+			resolvers.talents{ 
+				[Talents.T_HEAVE]= math.ceil(self.level/10),
+				[Talents.T_WEAPON_COMBAT]= math.ceil(self.level/10),
+				[Talents.T_BOW_MASTERY]= math.ceil(self.level/10),
+				
+				[Talents.T_STEADY_SHOT]= math.ceil(self.level/10),
+				[Talents.T_RAPID_SHOT]= math.ceil(self.level/10),
+				
+
+				[Talents.T_PSYCHOMETRY]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_BIOFEEDBACK]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+				[Talents.T_LUCID_DREAMER]= math.floor(self:getTalentLevel(self.T_TRANSCENDENT_THOUGHT_FORMS)),
+			},
+			resolvers.equip{
+				{type="weapon", subtype="longbow", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="ammo", subtype="arrow", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="light", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="hands", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+				{type="armor", subtype="feet", autoreq=true, forbid_power_source={arcane=true, technique=true} },
+			},
+			resolvers.sustains_at_birth(),
+		}
+
+		setupThoughtForm(self, m, x, y)
+
+		game:playSoundNear(self, "talents/spell_generic")
+		
+		local ret = {
+			summon = m
 		}
+		if self:knowTalent(self.T_TF_UNITY) then
+			local t = self:getTalentFromId(self.T_TF_UNITY)
+			ret.speed = self:addTemporaryValue("combat_mindspeed", t.getSpeedPower(self, t)/100)
+		end
+		return ret
 	end,
 	deactivate = function(self, t, p)
-		self:removeTemporaryValue("psionic_overflow_max", p.ov)
+		p.summon:die(p.summon)
+		if p.speed then self:removeTemporaryValue("combat_mindspeed", p.speed) end
 		return true
 	end,
 	info = function(self, t)
-		local overflow = t.getMaxOverflow(self, t)
-		local radius = self:getTalentRadius(t)
-		return ([[While active you store up to %d excess feedback as overflow.  At the start of your turn the overflow will be unleased as mind damage in a radius of %d.
-		Learning this talent will increase the amount of feedback you can store by 50 (first talent point only).
-		The max excess you can store will improve with your mindpower and max feedback.]]):format(overflow, radius)
+		local stat = t.getStatBonus(self, t)
+		return ([[Forge a bowman clad in leather armor from your thoughts.  The bowman learns disengage, bow mastery, combat accuracy, steady shot, and rapid shot as it levels up and has %d improved strength, %d dexterity, and %d constitution.
+		The stat bonuses will improve with your mindpower.]]):format(stat/2, stat, stat/2)
 	end,
 }
 
 newTalent{
-	name = "Thought Form3",
-	type = {"psionic/thought-forms", 3},
-	points = 5,
-	require = psi_wil_req3,
-	cooldown = 10,
-	tactical = { ATTACKAREA = {PHYSICAL = 2}, DISABLE = { knockback = 2 }, },
-	range = 0,
-	radius = function(self, t) return 1 + math.ceil(self:getTalentLevel(t)) end,
-	direct_hit = true,
-	requires_target = true,
-	target = function(self, t)
-		return {type="ball", range=self:getTalentRange(t), talent=t}
-	end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 20, 230) end,
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return not self:hasEffect(self.EFF_REGENERATION) end,
+	name = "Thought-Forms",
+	short_name = "THOUGHT_FORMS",
+	type = {"psionic/thought-forms", 1},
+	points = 5, 
+	require = psi_wil_req1,
+	mode = "passive",
+	range = function(self, t)
+		local t = self:getTalentFromId(self.T_OVER_MIND)
+		return 10 + t.getRangeBonus(self, t)
+	end,
+	getStatBonus = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end,
 	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
-			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 50
+		if self:getTalentLevel(t) >= 1 and not self:knowTalent(self.T_TF_WARRIOR) then
+			self:learnTalent(self.T_TF_WARRIOR, true)
 		end
-		return true
-	end,
+		if self:getTalentLevel(t) >= 3 and not self:knowTalent(self.T_TF_DEFENDER) then
+			self:learnTalent(self.T_TF_DEFENDER, true)
+		end
+		if self:getTalentLevel(t) >= 5 and not self:knowTalent(self.T_TF_BOWMAN) then
+			self:learnTalent(self.T_TF_BOWMAN, true)
+		end
+	end,	
 	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 50
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
-			end
+		if self:getTalentLevel(t) < 1 and self:knowTalent(self.T_TF_WARRIOR) then
+			self:unlearnTalent(self.T_TF_WARRIOR)
+		end
+		if self:getTalentLevel(t) < 3 and self:knowTalent(self.T_TF_DEFENDER) then
+			self:unlearnTalent(self.T_TF_DEFENDER)
+		end
+		if self:getTalentLevel(t) < 5 and self:knowTalent(self.T_TF_BOWMAN) then
+			self:unlearnTalent(self.T_TF_BOWMAN)
 		end
-		return true
 	end,
-	action = function(self, t)
-		local tg = self:getTalentTarget(t)
-		if not x or not y then return nil end
-		
-		local damage = math.min(self.psionic_feedback, t.getDamage(self, t))
-		self:project(tg, x, y, DamageType.MINDKNOCKBACK, self:mindCrit(damage))
-		self.psionic_feedback = self.psionic_feedback - damage
-		
-		return true
+	info = function(self, t)
+		local bonus = t.getStatBonus(self, t)
+		local range = self:getTalentRange(t)
+		return([[Forge a guardian from your thoughts alone.  Your guardian's primary stat will be improved by %d and it's two secondary stats by %d.
+		At talent level one you may forge a powerful warrior wielding a two-handed weapon, at talent level 3 you may forge a strong defender using a sword and shield, and at talent level 5 a mighty bowman clad in leather armor.
+		Thought forms can only be maintained up to a range of %d and will rematerialize next to you if this range is exceeded.
+		Only one thought-form may be active at a time and the stat bonuses will improve with your mindpower.]]):format(bonus, bonus/2, range)
 	end,
+}
+
+newTalent{
+	name = "Transcendent Thought-Forms",
+	short_name = "TRANSCENDENT_THOUGHT_FORMS",
+	type = {"psionic/thought-forms", 2},
+	points = 5, 
+	require = psi_wil_req2,
+	mode = "passive",
 	info = function(self, t)
-		local damage = t.getDamage(self, t)
-		local radius = self:getTalentRadius(t)
-		return ([[Activate to convert up to %0.2f of stored feedback into a blast of kinetic energy.  Targets out to a radius of %d will suffer physical damage and may be knocked back.
-		Learning this talent will increase the amount of feedback you can store by 50 (first talent point only).
-		The damage will scale with your mindpower.]]):format(damDesc(self, DamageType.PHYSICAL, damage), radius)
+		local level = self:getTalentLevel(t)
+		return([[Your thought-forms now know Lucid Dreamer, Biofeedback, and Psychometry at talent level %d.]]):format(level)
 	end,
 }
 
 newTalent{
-	name = "Thought Form4",
-	type = {"psionic/thought-forms", 4},
+	name = "Over Mind",
+	type = {"psionic/thought-forms", 3},
 	points = 5, 
-	require = psi_wil_req4,
-	cooldown = 15,
-	tactical = { DEFEND = 2, ATTACK = {MIND = 2}},
-	on_pre_use = function(self, t, silent) if self.psionic_feedback <= 0 then if not silent then game.logPlayer(self, "You have no feedback to power this talent.") end return false end return true end,
-	getShieldPower = function(self, t) return self:combatTalentMindDamage(t, 20, 300) end,
-	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 50) end,
-	on_learn = function(self, t)
-		if self:getTalentLevelRaw(t) == 1 then
-			if not self.psionic_feedback then
-				self.psionic_feedback = 0
+	require = psi_wil_req3,
+	sustain_psi = 50,
+	mode = "sustained",
+	no_sustain_autoreset = true,
+	cooldown = 24,
+	no_npc_use = true,
+	getControlBonus = function(self, t) return self:combatTalentMindDamage(t, 5, 50) end,
+	getRangeBonus = function(self, t) return self:getTalentLevelRaw(t) end,
+	on_pre_use = function(self, t, silent) if not game.party:findMember{type="thought-form"} then if not silent then game.logPlayer(self, "You must have an active Thought-Form to use this talent!") end return false end return true end,
+	activate = function(self, t)
+		-- Find our thought-form
+		local target = game.party:findMember{type="thought-form"}
+		
+		-- Modify the control permission
+		local old_control = game.party:hasMember(target).control
+		game.party:hasMember(target).control = "full"
+				
+		-- Store life bonus and heal value
+		local life_bonus = target.max_life * (t.getControlBonus(self, t)/100)
+		
+		-- Switch on TickEnd so every thing applies correctly
+		game:onTickEnd(function() 
+			game.party:hasMember(target).on_control = function(self)
+				self.summoner.over_mind_ai = self.summoner.ai
+				self.summoner.ai = "none"
+				target:hotkeyAutoTalents()
 			end
-			self.psionic_feedback_max = (self.psionic_feedback_max or 0) + 100
-		end
-		return true
+			game.party:hasMember(target).on_uncontrol = function(self)
+				self.summoner.ai = self.summoner.over_mind_ai
+				if self.summoner:isTalentActive(self.summoner.T_OVER_MIND) then
+					self.summoner:forceUseTalent(self.summoner.T_OVER_MIND, {ignore_energy=true})
+				end
+			end
+			game.party:setPlayer(target)
+			self:resetCanSeeCache()
+		end)
+			
+		local ret = {
+			target = target, old_control = old_control,
+			life = target:addTemporaryValue("max_life", life_bonus),
+			speed = target:addTemporaryValue("combat_physspeed", t.getControlBonus(self, t)/100),
+			damage = target:addTemporaryValue("inc_damage", {all=t.getControlBonus(self, t)}),
+			target:heal(life_bonus),
+		}
+		
+		return ret
 	end,
-	on_unlearn = function(self, t)
-		if not self:knowTalent(t) then
-			self.psionic_feedback_max = self.psionic_feedback_max - 100
-			if self.psionic_feedback_max <= 0 then
-				self.psionic_feedback_max = nil
-				self.psionic_feedback = nil
+	deactivate = function(self, t, p)
+		if p.target then
+			p.target:removeTemporaryValue("max_life", p.life)
+			p.target:removeTemporaryValue("inc_damage", p.damage)
+			p.target:removeTemporaryValue("combat_physspeed", p.speed)
+		
+			if game.party:hasMember(p.target) then
+				game.party:hasMember(p.target).control = old_control
 			end
 		end
 		return true
 	end,
-	action = function(self, t)
-		local power = math.min(self.psionic_feedback, t.getShieldPower(self, t))
-		self:setEffect(self.EFF_RESONANCE_SHIELD, 10, {power = self:mindCrit(power), dam = t.getDamage(self, t)})
-		self.psionic_feedback = self.psionic_feedback - power
-		return true
+	info = function(self, t)
+		local bonus = t.getControlBonus(self, t)
+		local range = t.getRangeBonus(self, t)
+		return ([[Take direct control of your active thought-form, improving it's damage, attack speed, and maximum life by %d%% but leaving your body a defenseless shell.
+		Also increases the range at which you can maintain your thought forms (rather this talent is active or not) by %d.
+		The life, damage, and speed bonus will improve with your mindpower.]]):format(bonus, range)
 	end,
+}
+
+newTalent{
+	name = "Thought-Form Unity",
+	short_name = "TF_UNITY",
+	type = {"psionic/thought-forms", 4},
+	points = 5, 
+	require = psi_wil_req4,
+	mode = "passive",
+	getOffensePower = function(self, t) return self:combatTalentMindDamage(t, 10, 30) end,
+	getDefensePower = function(self, t) return self:combatTalentMindDamage(t, 5, 15) end,
+	getSpeedPower = function(self, t) return self:combatTalentMindDamage(t, 5, 15) end,
 	info = function(self, t)
-		local shield_power = t.getShieldPower(self, t)
-		local damage = t.getDamage(self, t)
-		return ([[Activate to conver up to %0.2f feedback into a resonance shield that will absorb 50%% of all damage you take and inflict %0.2f mind damage to melee attackers.
-		Learning this talent will increase the amount of feedback you can store by 100 (first talent point only).
-		The conversion ratio will scale with your mindpower and the effect lasts up to ten turns.]]):format(shield_power, damDesc(self, DamageType.MIND, damage))
+		local offense = t.getOffensePower(self, t)
+		local defense = t.getDefensePower(self, t)
+		local speed = t.getSpeedPower(self, t)
+		return([[You now gain a %d bonus to mind power while Thought-Form: Warrior is active, a %d%% bonus to resist all while Thought-Form: Defender is active, and a %d%% bonus to mind speed while Thought-Form: Bowman is active.
+		At talent level one any Feedback your Thought-Forms gain will be given to you as well, at talent level three your Thought-Forms gain a bonus to all saves equal to your mental save, and at talent level five they gain a bonus to all damage equal to your bonus mind damage.
+		These bonuses scale with your mindpower.]]):format(offense, defense, speed)
 	end,
 }
\ No newline at end of file
diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua
index fd2fe2ebe9824b0185373d0c11bbaae956400f11..92906db110795dc48d940cbbbbff5d8751c7d0bc 100644
--- a/game/modules/tome/data/timed_effects/mental.lua
+++ b/game/modules/tome/data/timed_effects/mental.lua
@@ -97,7 +97,7 @@ newEffect{
 	on_gain = function(self, err) return "#Target# wanders around!.", "+Confused" end,
 	on_lose = function(self, err) return "#Target# seems more focused.", "-Confused" end,
 	activate = function(self, eff)
-		eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0), 10)
+		eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0) * 100, 10)
 		eff.tmpid = self:addTemporaryValue("confused", eff.power)
 		if eff.power <= 0 then eff.dur = 0 end
 	end,
@@ -283,12 +283,14 @@ newEffect{
 	type = "mental",
 	subtype = { gloom=true, confusion=true },
 	status = "detrimental",
-	parameters = {},
+	parameters = { power = 10 },
 	on_gain = function(self, err) return "#F53CBE##Target# is lost in despair!", "+Confused" end,
 	on_lose = function(self, err) return "#Target# overcomes the gloom", "-Confused" end,
 	activate = function(self, eff)
 		eff.particle = self:addParticles(Particles.new("gloom_confused", 1))
+		eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0) * 100, 10)
 		eff.tmpid = self:addTemporaryValue("confused", eff.power)
+		if eff.power <= 0 then eff.dur = 0 end
 	end,
 	deactivate = function(self, eff)
 		self:removeParticles(eff.particle)
@@ -906,18 +908,20 @@ newEffect{
 	type = "mental",
 	subtype = { madness=true, confusion=true },
 	status = "detrimental",
-	parameters = {},
+	parameters = { power=10 },
 	on_gain = function(self, err) return "#F53CBE##Target# is lost in madness!", "+Confused" end,
 	on_lose = function(self, err) return "#Target# overcomes the madness", "-Confused" end,
 	activate = function(self, eff)
 		eff.particle = self:addParticles(Particles.new("gloom_confused", 1))
 		eff.mindResistChangeId = self:addTemporaryValue("resists", { [DamageType.MIND]=eff.mindResistChange })
+		eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0) * 100, 10)
 		eff.tmpid = self:addTemporaryValue("confused", eff.power)
 	end,
 	deactivate = function(self, eff)
 		self:removeTemporaryValue("resists", eff.mindResistChangeId)
 		self:removeParticles(eff.particle)
 		self:removeTemporaryValue("confused", eff.tmpid)
+		if self == game.player and self.updateMainShader then self:updateMainShader() end
 	end,
 }
 
@@ -1468,8 +1472,8 @@ newEffect{
 
 newEffect{
 	name = "WAKING_NIGHTMARE", image = "talents/waking_nightmare.png",
-	desc = "Waking Nightmare",
-	long_desc = function(self, eff) return ("The target is lost in a nightmare that deals %0.2f darkness damage each turn and has a %d%% chance to cause a random detrimental effect."):format(eff.dam, eff.chance) end,
+	desc = "Waking NIGHTMARE",
+	long_desc = function(self, eff) return ("The target is lost in a nightmare that deals %0.2f mind damage each turn and has a %d%% chance to cause a random detrimental effect."):format(eff.dam, eff.chance) end,
 	type = "mental",
 	subtype = { nightmare=true, darkness=true },
 	status = "detrimental",
@@ -1478,7 +1482,7 @@ newEffect{
 	on_lose = function(self, err) return "#Target# is free from the nightmare.", "-Night Terrors" end,
 	on_timeout = function(self, eff)
 		DamageType:get(DamageType.DARKNESS).projector(eff.src or self, self.x, self.y, DamageType.DARKNESS, eff.dam)
-		if rng.percent(eff.chance or 0) then
+		if rng.percent(eff.chance) then
 			-- Pull random effect
 			local chance = rng.range(1, 3)
 			if chance == 1 then
@@ -1505,15 +1509,15 @@ newEffect{
 	long_desc = function(self, eff) return ("The target is plagued by inner demons and each turn there's a %d%% chance that one will appear.  If the caster is killed or the target resists setting his demons loose the effect will end early."):format(eff.chance) end,
 	type = "mental",
 	subtype = { nightmare=true },
-	status = "detrimental",
-	parameters = {},
+	status = "detrimental", remove_on_clone = true,
+	parameters = {chance=0},
 	on_gain = function(self, err) return "#F53CBE##Target# is plagued by inner demons!", "+Inner Demons" end,
 	on_lose = function(self, err) return "#Target# is freed from the demons.", "-Inner Demons" end,
 	on_timeout = function(self, eff)
 		if eff.src.dead or not game.level:hasEntity(eff.src) then eff.dur = 0 return true end
-		if rng.percent(eff.chance or 0) then
-			if self:checkHit(eff.src:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
-				local t = eff.src:getTalentFromId(eff.src.T_INNER_DEMONS)
+		local t = eff.src:getTalentFromId(eff.src.T_INNER_DEMONS)
+		if rng.percent(eff.chance) then 
+			if self:attr("sleep") or self:checkHit(eff.src:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
 				t.summon_inner_demons(eff.src, self, t)
 			else
 				eff.dur = 0
@@ -2260,23 +2264,29 @@ newEffect{
 newEffect{
 	name = "LOBOTOMIZED", image = "talents/psychic_lobotomy.png",
 	desc = "Lobotomized",
-	long_desc = function(self, eff) return ("The target's mental faculties have been impaired, reducing it's cunning by %d and preventing it from making tactical decisions."):format(eff.power) end,
+	long_desc = function(self, eff) return ("The target's mental faculties have been impaired, confusing the target, making it act randomly (%d%% chance) and reducing it's cunning by %d."):format(eff.power, eff.power/2) end,
 	type = "mental",
 	subtype = { confusion=true },
 	status = "detrimental",
 	on_gain = function(self, err) return "#Target# higher mental functions have been imparied.", "+Lobotomized" end,
 	on_lose = function(self, err) return "#Target#'s regains it's senses.", "-Lobotomized" end,
-	parameters = { },
+	parameters = { power=1, dam=1 },
 	activate = function(self, eff)
-		eff.cid = self:addTemporaryValue("inc_stats", {[Stats.STAT_CUN]=-eff.power})
-		if self.ai then self.ai="dumb_talented_simple" end
+
+		DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.dam))
+		eff.power = math.max(eff.power - (self:attr("confusion_immune") or 0) * 100, 10)
+		eff.tmpid = self:addTemporaryValue("confused", eff.power)
+		eff.cid = self:addTemporaryValue("inc_stats", {[Stats.STAT_CUN]=-eff.power/2})
+		if eff.power <= 0 then eff.dur = 0 end
 	end,
 	deactivate = function(self, eff)
+		self:removeTemporaryValue("confused", eff.tmpid)
 		self:removeTemporaryValue("inc_stats", eff.cid)
-		if self.ai then self.ai=eff.ai end
+		if self == game.player and self.updateMainShader then self:updateMainShader() end
 	end,
 }
 
+
 newEffect{
 	name = "PSIONIC_SHIELD", image = "talents/kinetic_shield.png",
 	desc = "Psionic Shield",
@@ -2306,7 +2316,7 @@ newEffect{
 }
 
 newEffect{
-	name = "CLEAR_MIND", image = "talents/aura_discipline.png",
+	name = "CLEAR_MIND", image = "talents/mental_shielding.png",
 	desc = "Clear Mind",
 	long_desc = function(self, eff) return ("Nullifies the next %d detrimental mental effects."):format(self.mental_negative_status_effect_immune) end,
 	type = "mental",
@@ -2350,14 +2360,14 @@ newEffect{
 	type = "mental",
 	subtype = { psionic=true },
 	status = "detrimental",
-	parameters = {power = 1},
+	parameters = {power = 1, range = 5},
 	remove_on_clone = true, decrease = 0,
 	on_gain = function(self, err) return "#Target#'s mind has been invaded!", "+Mind Link" end,
 	on_lose = function(self, err) return "#Target# is free from the mental invasion.", "-Mind Link" end,
 	on_timeout = function(self, eff)
 		-- Remove the mind link when appropriate
 		local p = eff.src:isTalentActive(eff.src.T_MIND_LINK)
-		if not p or p.target ~= self or eff.src.dead or not game.level:hasEntity(eff.src) then
+		if not p or p.target ~= self or eff.src.dead or not game.level:hasEntity(eff.src) or core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) > eff.range then
 			self:removeEffect(self.EFF_MIND_LINK_TARGET)
 		end
 	end,
@@ -2395,16 +2405,61 @@ newEffect{
 newEffect{
 	name = "SLEEP", image = "talents/sleep.png",
 	desc = "Sleep",
-	long_desc = function(self, eff) return ("The target is in a deep sleep and unable to act.  Every %d damage it takes will reduce the duration of the effect by one turn."):format(eff.power) end,
+	long_desc = function(self, eff) return ("The target is asleep and unable to act.  Every %d damage it takes will reduce the duration of the effect by one turn."):format(eff.power) end,
 	type = "mental",
 	subtype = { sleep=true },
 	status = "detrimental",
-	parameters = { power=1, contagious=0, insomnia=1 },
+	parameters = { power=1, insomnia=1, waking=0 },
 	on_gain = function(self, err) return "#Target# has been put to sleep.", "+Sleep" end,
 	on_lose = function(self, err) return "#Target# is no longer sleeping.", "-Sleep" end,
 	on_timeout = function(self, eff)
-		if eff.contagious > 0 and eff.dur > 1 then
-			local t = eff.src:getTalentFromId(eff.src.T_SLEEP)
+		local dream_prison = false
+		if eff.src and eff.src.isTalentActive and eff.src:isTalentActive(eff.src.T_DREAM_PRISON) then
+			local t = eff.src:getTalentFromId(eff.src.T_DREAM_PRISON)
+			if core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) <= eff.src:getTalentRange(t) then
+				dream_prison = true
+			end
+		end
+		if dream_prison then
+			eff.dur = eff.dur + 1
+		end
+	end,
+	activate = function(self, eff)
+		eff.sid = self:addTemporaryValue("sleep", eff.power)
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("sleep", eff.sid)
+		if not self:attr("lucid_dreamer") then
+			self:setEffect(self.EFF_INSOMNIA, eff.insomnia, {power=eff.insomnia/10})
+		end
+		if not self:attr("sleep") and eff.waking > 0 then
+			DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking))
+		end
+	end,
+}
+
+newEffect{
+	name = "SLUMBER", image = "talents/slumber.png",
+	desc = "Slumber",
+	long_desc = function(self, eff) return ("The target is in a deep sleep and unable to act.  Every %d damage it takes will reduce the duration of the effect by one turn."):format(eff.power) end,
+	type = "mental",
+	subtype = { sleep=true },
+	status = "detrimental",
+	parameters = { power=1, contagious=0, insomnia=1, waking=0 },
+	on_gain = function(self, err) return "#Target# is in a deep sleep.", "+Slumber" end,
+	on_lose = function(self, err) return "#Target# is no longer sleeping.", "-Slumber" end,
+	on_timeout = function(self, eff)
+		local dream_prison = false
+		if eff.src and eff.src.isTalentActive and eff.src:isTalentActive(eff.src.T_DREAM_PRISON) then
+			local t = eff.src:getTalentFromId(eff.src.T_DREAM_PRISON)
+			if core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) <= eff.src:getTalentRange(t) then
+				dream_prison = true
+			end
+		end
+		if dream_prison then
+			eff.dur = eff.dur + 1
+		elseif eff.contagious > 0 and eff.dur > 1 then
+			local t = eff.src:getTalentFromId(eff.src.T_SLUMBER)
 			t.doContagiousSlumber(eff.src, self, eff, t)
 		end
 	end,
@@ -2413,33 +2468,89 @@ newEffect{
 	end,
 	deactivate = function(self, eff)
 		self:removeTemporaryValue("sleep", eff.sid)
-		self:setEffect(self.EFF_INSOMNIA, eff.insomnia, {power=eff.insomnia/10})
+		if not self:attr("lucid_dreamer") then
+			self:setEffect(self.EFF_INSOMNIA, eff.insomnia, {power=eff.insomnia/10})
+		end
+		if not self:attr("sleep") and eff.waking > 0 then
+			DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking))
+		end
+	end,
+}
+
+newEffect{
+	name = "NIGHTMARE", image = "talents/nightmare.png",
+	desc = "Nightmare",
+	long_desc = function(self, eff) return ("The target is in a nightmarish sleep, suffering %0.2f mind damage each turn and unable to act.  Every %d damage it takes will reduce the duration of the effect by one turn."):format(eff.dam, eff.power) end,
+	type = "mental",
+	subtype = { nightmare=true, sleep=true },
+	status = "detrimental",
+	parameters = { power=1, dam=0, insomnia=1, waking=0},
+	on_gain = function(self, err) return "#F53CBE##Target# is lost in a nightmare.", "+Nightmare" end,
+	on_lose = function(self, err) return "#Target# is free from the nightmare.", "-Nightmare" end,
+	on_timeout = function(self, eff)
+		local dream_prison = false
+		if eff.src and eff.src.isTalentActive and eff.src:isTalentActive(eff.src.T_DREAM_PRISON) then
+			local t = eff.src:getTalentFromId(eff.src.T_DREAM_PRISON)
+			if core.fov.distance(self.x, self.y, eff.src.x, eff.src.y) <= eff.src:getTalentRange(t) then
+				dream_prison = true
+			end
+		end
+		if dream_prison then
+			eff.dur = eff.dur + 1
+		else
+			-- Store the power for later
+			local real_power = eff.power
+			-- Temporarily spike the power so the nightmare doesn't break it
+			eff.power = 10000
+			DamageType:get(DamageType.DARKNESS).projector(eff.src or self, self.x, self.y, DamageType.DARKNESS, eff.dam)
+			-- Set the power back to its baseline
+			eff.power = real_power
+		end
+	end,
+	activate = function(self, eff)
+		eff.sid = self:addTemporaryValue("sleep", eff.power)
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("sleep", eff.sid)
+		if not self:attr("lucid_dreamer") then
+			self:setEffect(self.EFF_INSOMNIA, eff.insomnia, {power=eff.insomnia/10})
+		end
+		if not self:attr("sleep") and eff.waking > 0 then
+			DamageType:get(DamageType.MIND).projector(eff.src or self, self.x, self.y, DamageType.MIND, eff.src:mindCrit(eff.waking))
+		end
 	end,
 }
 
 newEffect{
 	name = "INSOMNIA", image = "talents/sleep.png",
 	desc = "Insomnia",
-	long_desc = function(self, eff) return ("The target is wide awake and has %d%% resistance to sleep effects."):format(eff.power) end,
+	long_desc = function(self, eff) return ("The target is wide awake and has %d%% resistance to sleep effects."):format(eff.power*100) end,
 	type = "mental",
-	subtype = { sleep=true },
+	subtype = { psionic=true },
 	status = "beneficial",
 	parameters = { power=0 },
+	on_gain = function(self, err) return "#Target# is suffering from insomnia.", "+Insomnia" end,
+	on_lose = function(self, err) return "#Target# is no longer suffering from insomnia.", "-Insomnia" end,
 	on_merge = function(self, old_eff, new_eff)
 		-- Merge the effect
-		local dur = math.ceil((old_eff.dur + new_eff.dur) / 2)
+		local dur = math.min(10, math.ceil(old_eff.dur + new_eff.dur))
 		old_eff.dur = dur
 		old_eff.power = dur/10
 		-- Need to remove and re-add the effect
 		self:removeTemporaryValue("sleep_immune", old_eff.sid)
-		old_eff.effsid = self:addTemporaryValue("sleep_immune", old_eff.power)
+		old_eff.sid = self:addTemporaryValue("sleep_immune", old_eff.power)
 		return old_eff
 	end,
 	on_timeout = function(self, eff)
-		-- Deincrement the power
-		eff.power = eff.dur/10
-		self:removeTemporaryValue("sleep_immune", eff.sid)
-		eff.sid = self:addTemporaryValue("sleep_immune", eff.power)
+		-- Insomnia only ticks when we're awake
+		if self:attr("sleep") then
+			eff.dur = eff.dur + 1
+		else
+			-- Deincrement the power
+			eff.power = eff.dur/10
+			self:removeTemporaryValue("sleep_immune", eff.sid)
+			eff.sid = self:addTemporaryValue("sleep_immune", eff.power)
+		end
 	end,
 	activate = function(self, eff)
 		eff.sid = self:addTemporaryValue("sleep_immune", eff.power)
@@ -2449,3 +2560,29 @@ newEffect{
 	end,
 }
 
+newEffect{
+	name = "SUNDER_MIND", image = "talents/sunder_mind.png",
+	desc = "Sundered Mind",
+	long_desc = function(self, eff) return ("The target's mental faculties have been impaired, reducing it's mental save by %d."):format(eff.cur_power or eff.power) end,
+	type = "mental",
+	subtype = { psionic=true },
+	status = "detrimental",
+	on_gain = function(self, err) return "#Target# mental functions have been imparied.", "+Sundered Mind" end,
+	on_lose = function(self, err) return "#Target#'s regains it's senses.", "-Sundered Mind" end,
+	parameters = { power=10 },
+	on_merge = function(self, old_eff, new_eff)
+		self:removeTemporaryValue("combat_mentalresist", old_eff.sunder)
+		old_eff.cur_power = old_eff.cur_power + new_eff.power
+		old_eff.sunder = self:addTemporaryValue("combat_mentalresist", -old_eff.cur_power)
+
+		old_eff.dur = new_eff.dur
+		return old_eff
+	end,
+	activate = function(self, eff)
+		eff.cur_power = eff.power
+		eff.sunder = self:addTemporaryValue("combat_mentalresist", -eff.power)
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("combat_mentalresist", eff.sunder)
+	end,
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua
index 33acaf83d00e1de23961adc9ffdeb731991e09e6..8b6f73702dc070c2c57b6f85efa39c1abc0a1985 100644
--- a/game/modules/tome/data/timed_effects/other.lua
+++ b/game/modules/tome/data/timed_effects/other.lua
@@ -1577,3 +1577,201 @@ newEffect{
 		self:removeTemporaryValue("global_speed_add", eff.tmpid)
 	end,
 }
+
+newEffect{
+	name = "DREAMSCAPE", image = "talents/dreamscape.png",
+	desc = "Dreamscape",
+	long_desc = function(self, eff) return ("This target has invaded %s's dreams and has gained a %d%% bonus to all damage."):format(eff.target.name, eff.power) end,
+	type = "other",
+	subtype = { psionic=true },
+	status = "beneficial",
+	parameters = { power=1, projections_killed=0 },
+	on_timeout = function(self, eff)
+		-- Dreamscape doesn't cooldown in the dreamscape
+		self.talents_cd[self.T_DREAMSCAPE] = self.talents_cd[self.T_DREAMSCAPE] + 1
+		-- Spawn every four turns, or every two for lucid dreamers
+		local spawn_time = 4
+		if eff.target:attr("lucid_dreamer") then
+			spawn_time = 2
+		end
+		if eff.dur%spawn_time == 0 then 
+			local x, y = util.findFreeGrid(eff.target.x, eff.target.y, 1, true, {[Map.ACTOR]=true})
+			if not x then
+				game.logPlayer(self, "Not enough space to summon!")
+				return
+			end
+			
+			-- Create a clone for later spawning
+			local m = require("mod.class.NPC").new(eff.target:clone{
+				shader = "shadow_simulacrum",
+				no_drops = true,
+				faction = eff.target.faction,
+				summoner = eff.target, summoner_gain_exp=true,
+				ai_target = {actor=nil},
+				ai = "summoned", ai_real = "tactical",
+				name = eff.target.name.."'s dream projection",
+			})
+			m:removeAllMOs()
+			m.make_escort = nil
+			m.on_added_to_level = nil
+
+			m.energy.value = 0
+			m.player = nil
+			m.max_life = m.max_life
+			m.life = util.bound(m.life, 0, m.max_life)
+			if not eff.target:attr("lucid_dreamer") then
+				m.inc_damage.all = (m.inc_damage.all or 0) - 50
+			end
+			m.forceLevelup = function() end
+			m.die = nil
+			m.on_die = nil
+			m.on_acquire_target = nil
+			m.seen_by = nil
+			m.can_talk = nil
+			m.puuid = nil
+			m.on_takehit = nil
+			m.exp_worth = 0
+			m.no_inventory_access = true
+			m.clone_on_hit = nil
+			m.remove_from_party_on_death = true
+			m.is_psychic_projection = true
+			-- remove imprisonment
+			m.invulnerable = m.invulnerable - 1
+			m.time_prison = m.time_prison - 1
+			m.no_timeflow = m.no_timeflow - 1
+			m.status_effect_immune = m.status_effect_immune - 1
+			m:removeParticles(eff.particle)
+			
+			-- track number killed
+			m.on_die = function(self, who)
+				if who then
+					local p = who:hasEffect(who.EFF_DREAMSCAPE) or who.summoner:hasEffect(who.summoner.EFF_DREAMSCAPE)
+					p.projections_killed = p.projections_killed + 1
+				end
+			end
+			
+			game.zone:addEntity(game.level, m, "actor", x, y)
+			game.level.map:particleEmitter(x, y, 1, "shadow")
+
+			if game.party:hasMember(eff.target) then
+				game.party:addMember(m, {
+					control="full",
+					type="projection",
+					title="Dream Self",
+					orders = {target=true},
+				})
+				if eff.target == game.player then
+					game.party:setPlayer(m)
+					m:resetCanSeeCache()
+				end
+			end
+		end
+	end,
+	activate = function(self, eff)
+		-- Make the target invulnerable
+		eff.iid = eff.target:addTemporaryValue("invulnerable", 1)
+		eff.sid = eff.target:addTemporaryValue("time_prison", 1)
+		eff.tid = eff.target:addTemporaryValue("no_timeflow", 1)
+		eff.imid = eff.target:addTemporaryValue("status_effect_immune", 1)
+		eff.particle = eff.target:addParticles(Particles.new("time_prison", 1))
+		eff.target.energy.value = 0
+		-- Make the invader deadly
+		eff.pid = self:addTemporaryValue("inc_damage", {all=eff.power})
+		eff.did = self:addTemporaryValue("lucid_dreamer", 1)
+	end,
+	deactivate = function(self, eff)
+		-- Remove the target's invulnerability
+		eff.target:removeTemporaryValue("invulnerable", eff.iid)
+		eff.target:removeTemporaryValue("time_prison", eff.sid)
+		eff.target:removeTemporaryValue("no_timeflow", eff.tid)
+		eff.target:removeTemporaryValue("status_effect_immune", eff.imid)
+		eff.target:removeParticles(eff.particle)
+		-- Remove the invaders damage bonus
+		self:removeTemporaryValue("inc_damage", eff.pid)
+		self:removeTemporaryValue("lucid_dreamer", eff.did)
+		-- Return from the dreamscape
+		game:onTickEnd(function()
+			-- Collect objects
+			local objs = {}
+			for i = 0, game.level.map.w - 1 do for j = 0, game.level.map.h - 1 do
+				for z = game.level.map:getObjectTotal(i, j), 1, -1 do
+					objs[#objs+1] = game.level.map:getObject(i, j, z)
+					game.level.map:removeObject(i, j, z)
+				end
+			end end
+
+			local oldzone = game.zone
+			local oldlevel = game.level
+			local zone = game.level.source_zone
+			local level = game.level.source_level
+
+			if not self.dead then
+				oldlevel:removeEntity(self)
+				level:addEntity(self)
+			end
+
+			game.zone = zone
+			game.level = level
+			game.zone_name_s = nil
+
+			local x1, y1 = util.findFreeGrid(eff.x, eff.y, 20, true, {[Map.ACTOR]=true})
+			if x1 then
+				if not self.dead then
+					self:move(x1, y1, true)
+					self.on_die, self.dream_plane_on_die = self.dream_plane_on_die, nil
+					game.level.map:particleEmitter(x1, y1, 1, "teleport")
+				else
+					self.x, self.y = x1, y1
+				end
+			end
+			local x2, y2 = util.findFreeGrid(eff.tx, eff.ty, 20, true, {[Map.ACTOR]=true})
+			if not eff.target.dead then
+				if x2 then
+					eff.target:move(x2, y2, true)
+					eff.target.on_die, eff.target.dream_plane_on_die = eff.target.dream_plane_on_die, nil
+				end
+				if oldlevel:hasEntity(eff.target) then oldlevel:removeEntity(eff.target) end
+				level:addEntity(eff.target)
+			else
+				eff.target.x, eff.target.y = x2, y2
+			end
+
+			-- Add objects back
+			for i, o in ipairs(objs) do
+				if self.dead then
+					game.level.map:addObject(eff.target.x, eff.target.y, o)
+				else
+					game.level.map:addObject(self.x, self.y, o)
+				end
+			end
+
+			-- Remove all npcs in the dreamscape
+			for uid, e in pairs(oldlevel.entities) do
+				if e ~= self and e ~= eff.target and e.die then e:die() end
+			end
+
+			-- Reload MOs
+			game.level.map:redisplay()
+			game.level.map:recreate()
+
+			game.logPlayer(game.player, "#LIGHT_BLUE#You are brought back from the Dreamscape!")
+			
+			-- Apply Dreamscape hit
+			if eff.projections_killed > 0 then
+				eff.target:takeHit(eff.target.max_life/5 * eff.projections_killed, self)
+				eff.target:setEffect(eff.target.EFF_BRAINLOCKED, eff.projections_killed, {})
+			end
+		end)
+	end,
+}
+
+newEffect{
+	name = "DISTORTION", image = "talents/distortion.png",
+	desc = "Distortion",
+	long_desc = function(self, eff) return "The target has recently taken distortion damage and is vulnerable to distortion effects." end,
+	type = "other",
+	subtype = { distortion=true },
+	status = "detrimental",
+	parameters = { },
+	no_stop_enter_worlmap = true, no_stop_resting = true,
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua
index f90957f9a48ec4dd6b32a4de17cdaa117cf45386..3a4d188eaf9d8f47ab834d161e1dd8129265c7cd 100644
--- a/game/modules/tome/data/timed_effects/physical.lua
+++ b/game/modules/tome/data/timed_effects/physical.lua
@@ -1449,7 +1449,7 @@ newEffect{
 newEffect{
 	name = "OFFBALANCE",
 	desc = "Off-balance",
-	long_desc = function(self, eff) return ("Badly off balance. Global speed is reduced by 15%%.") end,
+	long_desc = function(self, eff) return ("Badly off balance. Global speed is reduced by 15%.") end,
 	type = "physical",
 	subtype = { ["cross tier"]=true },
 	status = "detrimental",
@@ -1783,3 +1783,56 @@ newEffect{
 		self:removeTemporaryValue("combat_crit_vulnerable", eff.crit)
 	end,
 }
+
+newEffect{
+	name = "RAVAGE", image = "talents/ravage.png",
+	desc = "Ravage",
+	long_desc = function(self, eff)
+		local ravaged = "each turn."
+		if eff.ravage then ravaged = "and is losing one physical effect turn." end
+		return ("The target is being ravaged by distortion, taking %0.2f physical damage %s"):format(eff.dam, ravaged) 
+	end,
+	type = "physical",
+	subtype = { distortion=true },
+	status = "detrimental",
+	parameters = {dam=1},
+	on_gain = function(self, err) return  nil, "+Ravage" end,
+	on_lose = function(self, err) return "#Target# is no longer being ravaged." or nil, "-Ravage" end,
+	on_timeout = function(self, eff)
+		if eff.ravage then
+			-- Go through all physical effects
+			local effs = {}
+			for eff_id, p in pairs(self.tmp) do
+				local e = self.tempeffect_def[eff_id]
+				if e.type == "physical" and e.status == "beneficial" then
+					effs[#effs+1] = {"effect", eff_id}
+				end
+			end
+
+			-- Go through all sustained techniques
+			for tid, act in pairs(self.sustain_talents) do
+				if act then
+					local talent = self:getTalentFromId(tid)
+					if talent.type[1]:find("^technique/") then effs[#effs+1] = {"talent", tid} end
+				end
+			end
+
+			if #effs > 0 then
+				local eff = rng.tableRemove(effs)
+				if eff[1] == "effect" then
+					self:removeEffect(eff[2])
+				else
+					self:forceUseTalent(eff[2], {ignore_energy=true})
+				end
+			end
+		end
+		self:setEffect(self.EFF_DISTORTION, 1, {})
+		DamageType:get(DamageType.PHYSICAL).projector(eff.src or self, self.x, self.y, DamageType.PHYSICAL, eff.dam)
+	end,
+	activate = function(self, eff)
+		self:setEffect(self.EFF_DISTORTION, 1, {})
+		if eff.ravage then
+			game.logSeen(self, "#LIGHT_RED#%s is being ravaged by distortion!", self.name:capitalize())
+		end
+	end,
+}
diff --git a/game/modules/tome/data/zones/demon-plane-spell/zone.lua b/game/modules/tome/data/zones/demon-plane-spell/zone.lua
index cd5cd5e82f584d923a663a43322f5b447488978e..184c72720cfb47df2b386bb188efefe95496b1e6 100644
--- a/game/modules/tome/data/zones/demon-plane-spell/zone.lua
+++ b/game/modules/tome/data/zones/demon-plane-spell/zone.lua
@@ -28,6 +28,7 @@ return {
 	all_lited = true,
 	no_worldport = true,
 	is_demon_plane = true,
+	no_planechange = true,
 	ambient_music = "Straight Into Ambush.ogg",
 	generator =  {
 		map = {
diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua
index 805b38ad9136effd99155ab951defc48e7224ef3..814412ba9d9e2ae56f636f5ca403cdb007f332c7 100644
--- a/game/modules/tome/dialogs/CharacterSheet.lua
+++ b/game/modules/tome/dialogs/CharacterSheet.lua
@@ -387,7 +387,7 @@ function _M:drawDialog(kind, actor_to_compare)
 		self:mouseTooltip(self.TOOLTIP_SPEED_SPELL,    s:drawColorStringBlended(self.font, ("Spell speed   : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
 		text = compare_fields(player, actor_to_compare, function(actor) return actor.combat_physspeed - 1 end, "%.2f%%", "%+.2f%%", 100)
 		self:mouseTooltip(self.TOOLTIP_SPEED_ATTACK,   s:drawColorStringBlended(self.font, ("Attack speed  : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
-		text = compare_fields(player, actor_to_compare, function(actor) return actor.combat_mentalspeed - 1 end, "%.2f%%", "%+.2f%%", 100)
+		text = compare_fields(player, actor_to_compare, function(actor) return actor.combat_mindspeed - 1 end, "%.2f%%", "%+.2f%%", 100)
 		self:mouseTooltip(self.TOOLTIP_SPEED_MENTAL,   s:drawColorStringBlended(self.font, ("Mental speed  : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
 		h = h + self.font_h
 		if player.died_times then
@@ -654,6 +654,8 @@ function _M:drawDialog(kind, actor_to_compare)
 		self:mouseTooltip(self.TOOLTIP_MINDPOWER, s:drawColorStringBlended(self.font, ("Mindpower: #00ff00#%s"):format(text, dur_text), w, h, 255, 255, 255, true)) h = h + self.font_h
 		text = compare_fields(player, actor_to_compare, function(actor, ...) return actor:combatMindCrit() end, "%d%%", "%+.0f%%")
 		self:mouseTooltip(self.TOOLTIP_MIND_CRIT, s:drawColorStringBlended(self.font,  ("Crit. chance: #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
+		text = compare_fields(player, actor_to_compare, function(actor, ...) return actor:combatMindSpeed() end, "%.2f%%", "%+.2f%%", 100)
+		self:mouseTooltip(self.TOOLTIP_SPELL_SPEED, s:drawColorStringBlended(self.font, ("Mind speed : #00ff00#%s"):format(text), w, h, 255, 255, 255, true)) h = h + self.font_h
 
 		h = 0
 		w = self.w * 0.5