diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 40ae5b59513cfc50231d7a4797d2b7cafd6ed322..2047b840ab2e98e5f5471a289fe3425a87f14d66 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -1939,6 +1939,17 @@ function _M:canWearObject(o, try_slot)
 	return engine.interface.ActorInventory.canWearObject(self, o, try_slot)
 end
 
+function _M:lastLearntTalentsMax(what)
+	return what == "generic" and 3 or 4
+end
+
+function _M:capLastLearntTalents(what)
+	if self.no_last_learnt_talents_cap then return end
+	local list = self.last_learnt_talents[what]
+	local max = self:lastLearntTalentsMax(what)
+	while #list > max do table.remove(list, 1) end
+end
+
 --- Actor learns a talent
 -- @param t_id the id of the talent to learn
 -- @return true if the talent was learnt, nil and an error message otherwise
@@ -1948,6 +1959,12 @@ function _M:learnTalent(t_id, force, nb)
 	-- If we learned a spell, get mana, if you learned a technique get stamina, if we learned a wild gift, get power
 	local t = _M.talents_def[t_id]
 
+	if not t.no_unlearn_last and self.last_learnt_talents then
+		local list = t.generic and self.last_learnt_talents.generic or self.last_learnt_talents.class
+		table.insert(list, t_id)
+		self:capLastLearntTalents(t.generic and "generic" or "class")
+	end
+
 	if t.dont_provide_pool then return true end
 
 	if t.type[1]:find("^spell/") and not self:knowTalent(self.T_MANA_POOL) and t.mana or t.sustain_mana then
@@ -2000,6 +2017,16 @@ end
 -- @return true if the talent was unlearnt, nil and an error message otherwise
 function _M:unlearnTalent(t_id)
 	if not engine.interface.ActorTalents.unlearnTalent(self, t_id, force) then return false end
+
+	local t = _M.talents_def[t_id]
+
+	if not t.no_unlearn_last and self.last_learnt_talents then
+		local list = t.generic and self.last_learnt_talents.generic or self.last_learnt_talents.class
+		for i = #list, 1, -1 do
+			if list[i] == t_id then table.remove(list, i) break end
+		end
+	end
+
 	-- Check the various pools
 	for key, num_refs in pairs(self.resource_pool_refs) do
 		if num_refs == 0 then
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 628515ba4f17e4264c803c150c98fe06c4b99f1e..d095cd11cab09ca6882fbe7e8cfd3e82c6fe5c59 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -1076,12 +1076,10 @@ function _M:setupCommands()
 			end end
 		end end,
 		[{"_g","ctrl"}] = function() if config.settings.cheat then
-			local list = mod.class.Trap:loadList("/data/general/traps/complex.lua")
-			local b = list[2]:clone()
-			b:resolve() b:resolve(nil, true)
-			self.zone:addEntity(self.level, b, "trap", self.player.x + 1, self.player.y)
-
-
+			print("== CLASS")
+			for i, tid in ipairs(game.player.last_learnt_talents.class) do print(i, tid) end
+			print("== GENERIC")
+			for i, tid in ipairs(game.player.last_learnt_talents.generic) do print(i, tid) end
 		end end,
 		[{"_f","ctrl"}] = function() if config.settings.cheat then
 			self.player.quests["love-melinda"] = nil
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 4c80ecf688ce8659f6cbe803ab5eb5767e592f52..2d2a89ad2055ad2b72513dc491f236902f15fa5b 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -84,6 +84,7 @@ function _M:init(t, no_default)
 
 	self.descriptor = self.descriptor or {}
 	self.died_times = self.died_times or {}
+	self.last_learnt_talents = { class={}, generic={} }
 end
 
 function _M:onBirth(birther)
diff --git a/game/modules/tome/data/talents/misc/inscriptions.lua b/game/modules/tome/data/talents/misc/inscriptions.lua
index 73cf790adff860dbe44ba7e5e3f866cbc467252b..a738ef27813e580ef11bc88b2ec513285197541c 100644
--- a/game/modules/tome/data/talents/misc/inscriptions.lua
+++ b/game/modules/tome/data/talents/misc/inscriptions.lua
@@ -54,6 +54,7 @@ local newInscription = function(t)
 		if not tt.image then
 			tt.image = "talents/"..(t.short_name or t.name):lower():gsub("[^a-z0-9_]", "_")..".png"
 		end
+		tt.no_unlearn_last = true
 		newTalent(tt)
 	end
 end
diff --git a/game/modules/tome/data/talents/misc/misc.lua b/game/modules/tome/data/talents/misc/misc.lua
index e287231b004cf67bff5459eee5ceff508066962f..7d916e5c48ca63c724d51f35780b6d3245de5f9d 100644
--- a/game/modules/tome/data/talents/misc/misc.lua
+++ b/game/modules/tome/data/talents/misc/misc.lua
@@ -44,6 +44,7 @@ newTalent{
 	requires_target = true,
 	target = {type="hit", range=1},
 	tactical = { ATTACK = 1 },
+	no_unlearn_last = true,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
 		local x, y = self:getTarget(tg)
@@ -68,6 +69,7 @@ newTalent{
 	info = "Allows you to have an energy pool. Energy is used to perform psionic manipulations.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 
 newTalent{
@@ -76,6 +78,7 @@ newTalent{
 	info = "Allows you to have a mana pool. Mana is used to cast all spells.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Vim Pool",
@@ -83,6 +86,7 @@ newTalent{
 	info = "Allows you to have a vim pool. Vim is used by corruptions.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Stamina Pool",
@@ -90,6 +94,7 @@ newTalent{
 	info = "Allows you to have a stamina pool. Stamina is used to activate special combat attacks.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Equilibrium Pool",
@@ -97,6 +102,7 @@ newTalent{
 	info = "Allows you to have an equilibrium pool. Equilibrium is used to measure your balance with nature and the use of wild gifts.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Positive Pool",
@@ -104,6 +110,7 @@ newTalent{
 	info = "Allows you to have a positive energy pool.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Negative Pool",
@@ -111,6 +118,7 @@ newTalent{
 	info = "Allows you to have a negative energy pool.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 newTalent{
 	name = "Hate Pool",
@@ -118,6 +126,7 @@ newTalent{
 	info = "Allows you to have a hate pool.",
 	mode = "passive",
 	hide = true,
+	no_unlearn_last = true,
 }
 
 newTalent{
@@ -126,49 +135,7 @@ newTalent{
 	info = "Allows you to have a paradox pool.",
 	mode = "passive",
 	hide = true,
-}
-
-newTalent{
-	name = "Improved Health I",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
-}
-newTalent{
-	name = "Improved Health II",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
-}
-newTalent{
-	name = "Improved Health III",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
-}
-newTalent{
-	name = "Decreased Health I",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
-}
-newTalent{
-	name = "Decreased Health II",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
-}
-newTalent{
-	name = "Decreased Health III",
-	type = {"base/race", 1},
-	info = "Improves the number of health points per level.",
-	mode = "passive",
-	hide = true,
+	no_unlearn_last = true,
 }
 
 -- Mages class talent, teleport to angolwen
@@ -178,6 +145,7 @@ newTalent{
 	type = {"base/class", 1},
 	cooldown = 400,
 	no_npc_use = true,
+	no_unlearn_last = true,
 	no_silence=true, is_spell=true,
 	action = function(self, t)
 		if not self:canBe("worldport") or self:attr("never_move") then
diff --git a/game/modules/tome/data/talents/misc/races.lua b/game/modules/tome/data/talents/misc/races.lua
index 989c7506f7e553fc3103c6ff5213fa4ef62805ca..1c66e2d0c895ee2416dc7991e378197e468a2e1c 100644
--- a/game/modules/tome/data/talents/misc/races.lua
+++ b/game/modules/tome/data/talents/misc/races.lua
@@ -800,6 +800,7 @@ newTalent{
 	name = "Knowledge of the Way",
 	type = {"base/race", 1},
 	no_npc_use = true,
+	no_unlearn_last = true,
 	on_learn = function(self, t) self.auto_id = 2 end,
 	action = function(self, t)
 		local Chat = require("engine.Chat")
diff --git a/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua b/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua
index 65405adc83796477ba246ba8e549c99bfe2977aa..05a5ab6ed457ccebcbbaadc67e3fe6670190a039 100644
--- a/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua
+++ b/game/modules/tome/data/talents/psionic/finer-energy-manipulations.lua
@@ -46,9 +46,9 @@ newTalent{
 	psi = 0,
 	points = 5,
 	no_npc_use = true,
+	no_unlearn_last = true,
 	boost = function(self, t)
 		return math.floor(self:combatTalentIntervalDamage(t, "wil", 3, 20))
-
 	end,
 	action = function(self, t)
 		local d d = self:showInventory("Reshape which weapon?", self:getInven("INVEN"), function(o) return not o.quest and o.type == "weapon" and not o.fully_reshaped end, function(o, item)
@@ -91,6 +91,7 @@ newTalent{
 	psi = 0,
 	points = 5,
 	no_npc_use = true,
+	no_unlearn_last = true,
 	arm_boost = function(self, t)
 		--return math.floor(0.1*self:combatTalentIntervalDamage(t, "wil", 10, 30))
 		return math.floor(0.25*t.fat_red(self, t))
diff --git a/game/modules/tome/data/talents/spells/stone-alchemy.lua b/game/modules/tome/data/talents/spells/stone-alchemy.lua
index 272764c06e8198e20da636c0d73d410fb0819e96..03321f3ed0a9dd3582bd6b69fb33b62e1974e53e 100644
--- a/game/modules/tome/data/talents/spells/stone-alchemy.lua
+++ b/game/modules/tome/data/talents/spells/stone-alchemy.lua
@@ -69,6 +69,7 @@ newTalent{
 	points = 5,
 	mana = 5,
 	no_npc_use = true,
+	no_unlearn_last = true,
 	action = function(self, t)
 		local d d = self:showEquipInven("Try to extract gems from which metallic item?", function(o) return o.metallic and (o.material_level or 1) <= self:getTalentLevelRaw(t) end, function(o, inven, item)
 			if not o then return end
@@ -109,6 +110,7 @@ newTalent{
 	mana = 80,
 	cooldown = 100,
 	no_npc_use = true,
+	no_unlearn_last = true,
 	action = function(self, t)
 		local d d = self:showInventory("Use which gem?", self:getInven("INVEN"), function(gem) return gem.type == "gem" and gem.imbue_powers and gem.material_level and gem.material_level <= self:getTalentLevelRaw(t) end, function(gem, gem_item)
 			local nd = self:showInventory("Imbue which armour?", self:getInven("INVEN"), function(o) return o.type == "armor" and o.slot == "BODY" and not o.been_imbued end, function(o, item)
diff --git a/game/modules/tome/data/talents/undeads/undeads.lua b/game/modules/tome/data/talents/undeads/undeads.lua
index 8a17ca3349cf541b5f18803cfb1a267ebb266840..76cdf976084f5e92101067b1cd576618f37a9db2 100644
--- a/game/modules/tome/data/talents/undeads/undeads.lua
+++ b/game/modules/tome/data/talents/undeads/undeads.lua
@@ -51,6 +51,7 @@ newTalent{
 	name = "Knowledge of the Past",
 	type = {"undead/base", 1},
 	no_npc_use = true,
+	no_unlearn_last = true,
 	on_learn = function(self, t) self.auto_id = 2 end,
 	action = function(self, t)
 		local Chat = require("engine.Chat")
diff --git a/game/modules/tome/dialogs/LevelupDialog.lua b/game/modules/tome/dialogs/LevelupDialog.lua
index 8f7352e5408c8affd79d485acd0848f10b4653de..8af5b453d57411a936ce21e2886239631c3d1fb8 100644
--- a/game/modules/tome/dialogs/LevelupDialog.lua
+++ b/game/modules/tome/dialogs/LevelupDialog.lua
@@ -40,6 +40,7 @@ Class talent points left: #00FF00#%d#LAST#
 Generic talent points left: #00FF00#%d#LAST#]]
 
 function _M:init(actor, on_finish)
+	actor.no_last_learnt_talents_cap = true
 	self.actor = actor
 	self.unused_stats = self.actor.unused_stats
 	self.new_stats_changed = false
@@ -139,6 +140,12 @@ Mouse: #00FF00#Left click#FFFFFF# to increase a stat; #00FF00#right click#FFFFFF
 	end
 end
 
+function _M:unload()
+	self.actor.no_last_learnt_talents_cap = nil
+	self.actor:capLastLearntTalents("class")
+	self.actor:capLastLearntTalents("generic")
+end
+
 local prev_sel = nil
 function _M:onSelectStat(item, force)
 	if item == prev_sel and not force then return end
@@ -356,6 +363,7 @@ function _M:cancel()
 			self.actor:unlearnTalent(t_id)
 		end
 	end
+	self.actor.last_learnt_talents = self.actor_dup.last_learnt_talents
 end
 
 function _M:tabTabs()
@@ -596,6 +604,11 @@ function _M:treeSelect(item, sel, v)
 			local it = self.c_t_tree.items_by_key[tid]
 			if it then self.c_t_tree:drawItem(it) end
 		end
+		local t = self.actor:getTalentFromId(item.talent)
+		for _, tid in ipairs(self.actor.last_learnt_talents[t.generic and "generic" or "class"]) do
+			local it = self.c_t_tree.items_by_key[tid]
+			if it then self.c_t_tree:drawItem(it) end
+		end
 	end
 	self.c_t_desc:switchItem(item)
 	self.c_t_tree:outputList()
@@ -632,6 +645,18 @@ function _M:checkDeps()
 	end
 end
 
+function _M:isUnlearnable(t, limit)
+	if not self.actor.last_learnt_talents then return end
+	local list = self.actor.last_learnt_talents[t.generic and "generic" or "class"]
+	local max = self.actor:lastLearntTalentsMax(t.generic and "generic" or "class")
+	local min = 1
+	if limit then min = math.max(1, #list - (max - 1)) end
+	for i = #list, min, -1 do
+		if list[i] == t.id then return i end
+	end
+	return nil
+end
+
 function _M:learnTalent(t_id, v)
 	self.talents_learned[t_id] = self.talents_learned[t_id] or 0
 	local t = self.actor:getTalentFromId(t_id)
@@ -659,7 +684,7 @@ function _M:learnTalent(t_id, v)
 				self:simplePopup("Impossible", "You do not know this talent!")
 				return
 			end
-			if self.actor_dup:getTalentLevelRaw(t_id) == self.actor:getTalentLevelRaw(t_id) then
+			if not self:isUnlearnable(t, true) and self.actor_dup:getTalentLevelRaw(t_id) >= self.actor:getTalentLevelRaw(t_id) then
 				self:simplePopup("Impossible", "You cannot unlearn talents!")
 				return
 			end
@@ -700,7 +725,7 @@ function _M:learnTalent(t_id, v)
 				self:simplePopup("Impossible", "You do not know this talent!")
 				return
 			end
-			if self.actor_dup:getTalentLevelRaw(t_id) == self.actor:getTalentLevelRaw(t_id) then
+			if not self:isUnlearnable(t, true) and self.actor_dup:getTalentLevelRaw(t_id) >= self.actor:getTalentLevelRaw(t_id) then
 				self:simplePopup("Impossible", "You cannot unlearn talents!")
 				return
 			end
@@ -801,6 +826,13 @@ function _M:onDrawItem(item)
 
 	else
 		local t = self.actor:getTalentFromId(item.talent)
+
+		if self:isUnlearnable(t, true) then
+			text:add({"color","LIGHT_BLUE"}, "This talent was recently learnt, you can still unlearn it.", true, "The last ", t.generic and "3 generic" or "4 class", " talents you learnt are always unlearnable.", {"color","LAST"}, true, true)
+		elseif t.no_unlearn_last then
+			text:add({"color","YELLOW"}, "This talent can alter the world in a permanent way, as such you can never unlearn it once known.", {"color","LAST"}, true, true)
+		end
+
 		local traw = self.actor:getTalentLevelRaw(t.id)
 		local diff = function(i2, i1, res)
 			res:add({"color", "LIGHT_GREEN"}, i1, {"color", "LAST"}, " [->", {"color", "YELLOW_GREEN"}, i2, {"color", "LAST"}, "]")
@@ -887,7 +919,13 @@ function _M:generateList()
 						entity=t.display_entity,
 						talent=t.id,
 						_type=tt.type,
-						color=function(item) return ((self.actor.talents[item.talent] or 0) ~= (self.actor_dup.talents[item.talent] or 0)) and {255, 215, 0} or self.actor:knowTalentType(item._type) and {255,255,255} or {175,175,175} end,
+						color=function(item)
+							if ((self.actor.talents[item.talent] or 0) ~= (self.actor_dup.talents[item.talent] or 0)) then return {255, 215, 0}
+							elseif self:isUnlearnable(t, true) then return colors.simple(colors.LIGHT_BLUE)
+							elseif self.actor:knowTalentType(item._type) then return {255,255,255}
+							else return {175,175,175}
+							end
+						end,
 					}
 					list[#list].status = function(item)
 						local t = self.actor:getTalentFromId(item.talent)