diff --git a/game/engine/interface/ActorTalents.lua b/game/engine/interface/ActorTalents.lua
index 3757eb5c35ec39dc5a99e7eae9783573c18b539d..10ecbf5ee5fd49a2fb3a945e9221e3cffa094691 100644
--- a/game/engine/interface/ActorTalents.lua
+++ b/game/engine/interface/ActorTalents.lua
@@ -44,6 +44,10 @@ function _M:newTalent(t)
 	assert(t.mode == "activated" or t.mode == "sustained", "wrong talent mode, requires either 'activated' or 'sustained'")
 	assert(t.info, "no talent info")
 
+	-- Remove line stat with tabs to be cleaner ..
+	local info = t.info
+	t.info = function(self) return info(self):gsub("\n\t+", "\n") end
+
 	table.insert(self.talents_def, t)
 	t.id = #self.talents_def
 	self["T_"..t.short_name] = #self.talents_def
@@ -155,6 +159,32 @@ function _M:canLearnTalent(t)
 	return true
 end
 
+--- Formats the requirements as a (multiline) string
+-- @param t_id the id of the talent to desc
+function _M:getTalentReqDesc(t_id)
+	local t = _M.talents_def[t_id]
+	local req = t.require
+	if not req then return "" end
+
+	local str = ""
+
+	if t.type[2] and t.type[2] > 1 then
+		str = str .. ("- Talents of the same category: %d\n"):format(t.type[2] - 1)
+	end
+
+	-- Obviously this requires the ActorStats interface
+	if req.stat then
+		for s, v in pairs(req.stat) do
+			str = str .. ("- %s %d\n"):format(self.stats_def[s].name, v)
+		end
+	end
+	if req.level then
+		str = str .. ("- Level %d\n"):format(req.level)
+	end
+
+	return str
+end
+
 --- Do we know this talent type
 function _M:knowTalentType(name)
 	return self.talents_types[name]
@@ -174,3 +204,19 @@ end
 function _M:getTalentTypeFrom(id)
 	return _M.talents_types_def[id]
 end
+
+--- Actor learns a talent type
+-- @param t_id the id of the talent to learn
+-- @return true if the talent was learnt, nil and an error message otherwise
+function _M:learnTalentType(tt)
+	self.talents_types[tt] = true
+	return true
+end
+
+--- Actor forgets a talent type
+-- @param t_id the id of the talent to learn
+-- @return true if the talent was unlearnt, nil and an error message otherwise
+function _M:unlearnTalentType(tt)
+	self.talents_types[tt] = nil
+	return true
+end
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 7c8145dd879c0c52aa1e6b2268a8dbfd8e17ac3d..d62ede71db5b3275de2d522dec42fa1da133c973 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -73,6 +73,8 @@ end
 function _M:levelup()
 	self.unused_stats = self.unused_stats + 3
 	self.unused_talents = self.unused_talents + 1
+	-- TODO: change it later, we need much less
+	self.unused_talents_types = self.unused_talents_types + 1
 end
 
 --- Notifies a change of stat value
@@ -98,7 +100,17 @@ end
 -- @param ab the talent (not the id, the table)
 -- @return true to continue, false to stop
 function _M:preUseTalent(ab)
-	return self:enoughEnergy()
+	local ret = self:enoughEnergy()
+	if ret == true then
+		if ab.message then
+			game.logSeen(self, "%s", self:useTalentMessage(ab))
+		elseif ab.type[1]:find("^spell/") then
+			game.logSeen(self, "%s casts %s.", self.name:capitalize(), ab.name)
+		else
+			game.logSeen(self, "%s uses %s.", self.name:capitalize(), ab.name)
+		end
+	end
+	return ret
 end
 
 --- Called before a talent is used
@@ -108,13 +120,6 @@ end
 -- @return true to continue, false to stop
 function _M:postUseTalent(ab, ret)
 	if ret == nil then return end
-	if ab.message then
-		game.logSeen(self, "%s", self:useTalentMessage(ab))
-	elseif ab.type[1]:find("^spell/") then
-		game.logSeen(self, "%s casts %s.", self.name:capitalize(), ab.name)
-	else
-		game.logSeen(self, "%s uses %s.", self.name:capitalize(), ab.name)
-	end
 	self:useEnergy()
 	return true
 end
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 76875d8dc3778ce3fd84a5c73f75b9c97f18799f..64547a9dcf55cef9d8948526e77593b1d1001a73 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -257,9 +257,19 @@ function _M:setupCommands()
 		end,
 
 		[{"_g","shift"}] = function()
---			local d = LevelupStatsDialog.new(self.player)
-			local d = LevelupTalentsDialog.new(self.player)
-			self:registerDialog(d)
+			local none = true
+			if self.player.unused_stats > 0 then
+				local ds = LevelupStatsDialog.new(self.player)
+				self:registerDialog(ds)
+				none = false
+			elseif self.player.unused_talents > 0 or self.player.unused_talents_types > 0 then
+				local dt = LevelupTalentsDialog.new(self.player)
+				self:registerDialog(dt)
+				none = false
+			end
+			if none then
+				engine.Dialog:simplePopup("Nothing to level", "You character has no stat or talent points to spend. Levelup and try again.")
+			end
 		end,
 
 		_LEFT  = function() self.player:move(self.player.x - 1, self.player.y    ) end,
diff --git a/game/modules/tome/class/Player.lua b/game/modules/tome/class/Player.lua
index 7ed1d99567437ce67a78167b5b2f994a0f81adf5..c4084ca0a2e2f39662f174e374b920045f058f54 100644
--- a/game/modules/tome/class/Player.lua
+++ b/game/modules/tome/class/Player.lua
@@ -37,7 +37,10 @@ function _M:levelup()
 
 	local x, y = game.level.map:getTileToScreen(self.x, self.y)
 	game.flyers:add(x, y, 80, 0.5, -2, "LEVEL UP!", {0,255,255})
-	game.log("#00ffff#Welcome to level %d", self.level)
+	game.log("#00ffff#Welcome to level %d.", self.level)
+	if self.unused_stats > 0 then game.log("You have %d stat point(s) to spend. Press G to use them.", self.unused_stats) end
+	if self.unused_talents > 0 then game.log("You have %d talent point(s) to spend. Press G to use them.", self.unused_talents) end
+	if self.unused_talents_types > 0 then game.log("You have %d talent category point(s) to spend. Press G to use them.", self.unused_talents_types) end
 end
 
 --- Tries to get a target from the user
diff --git a/game/modules/tome/dialogs/LevelupStatsDialog.lua b/game/modules/tome/dialogs/LevelupStatsDialog.lua
index 643b31865ea7c0415af0a8913ab0922e5f7f6d2c..b74e082aa87805b9799f46682e29b0470497ceec 100644
--- a/game/modules/tome/dialogs/LevelupStatsDialog.lua
+++ b/game/modules/tome/dialogs/LevelupStatsDialog.lua
@@ -1,5 +1,6 @@
 require "engine.class"
 require "engine.Dialog"
+local LevelupTalentsDialog = require "mod.dialogs.LevelupTalentsDialog"
 
 module(..., package.seeall, class.inherit(engine.Dialog))
 
@@ -15,7 +16,15 @@ function _M:init(actor)
 		_DOWN = function() self.statsel = util.boundWrap(self.statsel + 1, 1, 6) end,
 		_LEFT = function() self:incStat(-1) end,
 		_RIGHT = function() self:incStat(1) end,
-		_ESCAPE = function() game:unregisterDialog(self) end,
+		_ESCAPE = function()
+			game:unregisterDialog(self)
+
+			-- if talents to spend, do it now
+			if self.actor.unused_talents > 0 or self.actor.unused_talents_types > 0 then
+				local dt = LevelupTalentsDialog.new(self.actor)
+				game:registerDialog(dt)
+			end
+		end,
 	}
 	self:mouseZones{
 		{ x=2, y=25, w=130, h=self.font_h*6, fct=function(button, x, y, xrel, yrel, tx, ty)
diff --git a/game/modules/tome/dialogs/LevelupTalentsDialog.lua b/game/modules/tome/dialogs/LevelupTalentsDialog.lua
index f260004f136643b6feb2fbaaa130d9a3c59bb0f1..c18b95e017197c06678e0562649a61b319922ae0 100644
--- a/game/modules/tome/dialogs/LevelupTalentsDialog.lua
+++ b/game/modules/tome/dialogs/LevelupTalentsDialog.lua
@@ -34,14 +34,18 @@ function _M:generateList()
 	for i, tt in ipairs(self.actor.talents_types_def) do
 		local cat = tt.type:gsub("/.*", "")
 		list[#list+1] = { name=cat:capitalize().." / "..tt.name:capitalize() .." (category)", type=tt.type }
-		if self.actor:knowTalentType(tt.type) then known[#known+1] = "#00FF00#known" else known[#known+1] = tt.points.." point(s)" end
-
-		-- Find all talents of this school
-		for j, t in ipairs(tt.talents) do
-			local typename = "talent"
-			if t.type[1]:find("^spell/") then typename = "spell" end
-			list[#list+1] = { name="    "..t.name.." ("..typename..")", talent=t.id }
-			if self.actor:knowTalent(t.id) then known[#known+1] = "#00FF00#known" else known[#known+1] = t.points.." point(s)" end
+		if self.actor:knowTalentType(tt.type) then
+			known[#known+1] = "#00FF00#known"
+
+			-- Find all talents of this school
+			for j, t in ipairs(tt.talents) do
+				local typename = "talent"
+				if t.type[1]:find("^spell/") then typename = "spell" end
+				list[#list+1] = { name="    "..t.name.." ("..typename..")", talent=t.id }
+				if self.actor:knowTalent(t.id) then known[#known+1] = "#00FF00#known" else known[#known+1] = t.points.." point(s)" end
+			end
+		else
+			known[#known+1] = tt.points.." point(s)"
 		end
 	end
 	self.list = list
@@ -93,12 +97,14 @@ function _M:learnType(tt, v)
 			self:simplePopup("Not enough talent category points", "You have no talent category points left!")
 			return
 		end
+		self.actor:learnTalentType(tt)
 		self.actor.unused_talents_types = self.actor.unused_talents_types - 1
 	else
 		if self.actor_dup:getStat(self.talentsel) == self.actor:getStat(self.talentsel) then
 			self:simplePopup("Impossible", "You cannot take out more points!")
 			return
 		end
+		self.actor:unlearnTalentType(tt)
 		self.actor.unused_talents_types = self.actor.unused_talents_types + 1
 	end
 
@@ -113,7 +119,7 @@ function _M:drawDialog(s)
 Mouse: #00FF00#Left click#FFFFFF# to learn; #00FF00#right click#FFFFFF# to unlearn.
 ]]):splitLines(self.iw / 2 - 10, self.font)
 
-	local lines, helplines = {}
+	local lines, helplines, reqlines = {}, {}, {}
 	if self.list[self.talentsel].type then
 		local str = ""
 		str = str .. "#00FFFF#Talent Category\n"
@@ -126,17 +132,39 @@ Mouse: #00FF00#Left click#FFFFFF# to learn; #00FF00#right click#FFFFFF# to unlea
 		str = str .. "#00FFFF#A talent allows you to perform new combat moves, cast spells, improve your character. You gain a talent point every level. You may also find trainers or artifacts that allows you to learn more.\n\n"
 		helplines = str:splitLines(self.iw / 2 - 10, self.font)
 		lines = self.actor:getTalentFromId(self.list[self.talentsel].talent).info(self.actor):splitLines(self.iw / 2 - 10, self.font)
+		local req = self.actor:getTalentReqDesc(self.list[self.talentsel].talent)
+		if req ~= "" then
+			req = "Requirements:\n"..req
+			reqlines = req:splitLines(self.iw / 2 - 10, self.font)
+		end
 	end
+	local h = 2
 	for i = 1, #talentshelp do
-		s:drawColorString(self.font, talentshelp[i], self.iw / 2 + 5, 2 + (i-1) * self.font:lineSkip())
+		s:drawColorString(self.font, talentshelp[i], self.iw / 2 + 5, h)
+		h = h + self.font:lineSkip()
 	end
-	self:drawWBorder(s, self.iw / 2 + self.iw / 6, 2 + (0.5 + #talentshelp) * self.font:lineSkip(), self.iw / 6)
+
+	h = h + self.font:lineSkip()
+	self:drawWBorder(s, self.iw / 2 + self.iw / 6, h - 0.5 * self.font:lineSkip(), self.iw / 6)
 	for i = 1, #helplines do
-		s:drawColorString(self.font, helplines[i], self.iw / 2 + 5, 2 + (i + #talentshelp) * self.font:lineSkip())
+		s:drawColorString(self.font, helplines[i], self.iw / 2 + 5, h)
+		h = h + self.font:lineSkip()
 	end
-	self:drawWBorder(s, self.iw / 2 + self.iw / 6, 2 + (1.5 + #talentshelp + #helplines) * self.font:lineSkip(), self.iw / 6)
+
+	if #reqlines > 0 then
+		h = h + self.font:lineSkip()
+		self:drawWBorder(s, self.iw / 2 + self.iw / 6, h - 0.5 * self.font:lineSkip(), self.iw / 6)
+		for i = 1, #reqlines do
+			s:drawColorString(self.font, reqlines[i], self.iw / 2 + 5, h)
+			h = h + self.font:lineSkip()
+		end
+	end
+
+	h = h + self.font:lineSkip()
+	self:drawWBorder(s, self.iw / 2 + self.iw / 6, h - 0.5 * self.font:lineSkip(), self.iw / 6)
 	for i = 1, #lines do
-		s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + (i + #helplines + #talentshelp + 2) * self.font:lineSkip())
+		s:drawColorString(self.font, lines[i], self.iw / 2 + 5, 2 + h)
+		h = h + self.font:lineSkip()
 	end
 
 	-- Talents