diff --git a/game/engines/default/engine/ui/Base.lua b/game/engines/default/engine/ui/Base.lua
index b8ef5741150b8530cdbe4e15b18cd193db2e656f..14e15f301e3aee44b06b35b65351293b10f5a73b 100644
--- a/game/engines/default/engine/ui/Base.lua
+++ b/game/engines/default/engine/ui/Base.lua
@@ -160,11 +160,13 @@ function _M:makeFrame(base, w, h)
 	return f
 end
 
-function _M:drawFrame(f, x, y, r, g, b, a)
+function _M:drawFrame(f, x, y, r, g, b, a, w, h)
 	if not f.b7 then return end
 
 	x = math.floor(x)
 	y = math.floor(y)
+	f.w = w or f.w
+	f.h = h or f.h
 
 	-- Sides
 	f.b8.t:toScreenFull(x + f.b7.w, y, f.w - f.b7.w - f.b9.w + 1, f.b8.h, f.b8.tw, f.b8.th, r, g, b, a)
diff --git a/game/modules/tome/data/general/events/weird-pedestals.lua b/game/modules/tome/data/general/events/weird-pedestals.lua
index eb35e3d60fe458d6ceafaa94d08a22dbae5e5b53..7f9a8f09ca8bcfef50622f9d7731abef169ff293 100644
--- a/game/modules/tome/data/general/events/weird-pedestals.lua
+++ b/game/modules/tome/data/general/events/weird-pedestals.lua
@@ -59,7 +59,7 @@ for i = 1, 3 do
 			who:restInit(20, "refitting", "refitted", function(cnt, max)
 				if cnt > max then
 					self.pedestal_activated = true
-					require("engine.ui.Dialog"):simplePopup("Weird Pedestal", "As you inspect it a shadow materializes near you, and suddently it is no more a shadow!")
+					require("engine.ui.Dialog"):simplePopup("Weird Pedestal", "As you inspect it a shadow materializes near you, and suddenly it is no more a shadow!")
 
 					local m = game.zone:makeEntity(game.level, "actor", {
 						base_list=mod.class.NPC:loadList("/data/general/npcs/humanoid_random_boss.lua"),
diff --git a/game/modules/tome/data/gfx/stats/con.png b/game/modules/tome/data/gfx/stats/con.png
new file mode 100644
index 0000000000000000000000000000000000000000..aa1f3e9724b068078d41146703cb568a1e6d6d7f
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/con.png differ
diff --git a/game/modules/tome/data/gfx/stats/cun.png b/game/modules/tome/data/gfx/stats/cun.png
new file mode 100644
index 0000000000000000000000000000000000000000..c32dc2b4ecf1046675a78ad9505d61c0a28b28cb
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/cun.png differ
diff --git a/game/modules/tome/data/gfx/stats/dex.png b/game/modules/tome/data/gfx/stats/dex.png
new file mode 100644
index 0000000000000000000000000000000000000000..570bc0dc8edc88132a80497ef1d2b235d4525565
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/dex.png differ
diff --git a/game/modules/tome/data/gfx/stats/mag.png b/game/modules/tome/data/gfx/stats/mag.png
new file mode 100644
index 0000000000000000000000000000000000000000..b651f7090c01f98200ce2ba71b1ffb6038b41be2
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/mag.png differ
diff --git a/game/modules/tome/data/gfx/stats/str.png b/game/modules/tome/data/gfx/stats/str.png
new file mode 100644
index 0000000000000000000000000000000000000000..75d2dbcb7d53fbecc9f57f6378b9359f25c94d69
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/str.png differ
diff --git a/game/modules/tome/data/gfx/stats/wil.png b/game/modules/tome/data/gfx/stats/wil.png
new file mode 100644
index 0000000000000000000000000000000000000000..9e5d8103b7a1911d9891f0c4763f1fca3ac4e933
Binary files /dev/null and b/game/modules/tome/data/gfx/stats/wil.png differ
diff --git a/game/modules/tome/dialogs/Levelup2Dialog.lua b/game/modules/tome/dialogs/Levelup2Dialog.lua
index 9b01f7833a0a42f47fb100fe2dbc5b4673bc4317..8e7dc35061116cecdb0533918f9790a670213e45 100644
--- a/game/modules/tome/dialogs/Levelup2Dialog.lua
+++ b/game/modules/tome/dialogs/Levelup2Dialog.lua
@@ -21,7 +21,9 @@ require "engine.class"
 require "mod.class.interface.TooltipsData"
 
 local Dialog = require "engine.ui.Dialog"
+local Textzone = require "engine.ui.Textzone"
 local TalentTrees = require "mod.dialogs.elements.TalentTrees"
+local Separator = require "engine.ui.Separator"
 local DamageType = require "engine.DamageType"
 
 module(..., package.seeall, class.inherit(Dialog, mod.class.interface.TooltipsData))
@@ -154,71 +156,31 @@ function _M:finish()
 	return true
 end
 
-function _M:incStat(v)
+function _M:incStat(sid, v)
 	if v == 1 then
 		if self.actor.unused_stats <= 0 then
 			self:simplePopup("Not enough stat points", "You have no stat points left!")
 			return
 		end
-		if self.actor:getStat(self.sel, nil, nil, true) >= self.actor.level * 1.4 + 20 then
+		if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 then
 			self:simplePopup("Stat is at the maximum for your level", "You cannot increase this stat further until next level!")
 			return
 		end
-		if self.actor:isStatMax(self.sel) or self.actor:getStat(self.sel, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then
+		if self.actor:isStatMax(sid) or self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then
 			self:simplePopup("Stat is at the maximum", "You cannot increase this stat further!")
 			return
 		end
 	else
-		if self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true) then
+		if self.actor_dup:getStat(sid, nil, nil, true) == self.actor:getStat(sid, nil, nil, true) then
 			self:simplePopup("Impossible", "You cannot take out more points!")
 			return
 		end
 	end
 
-	local sel = self.sel
-	self.actor:incStat(sel, v)
+	self.actor:incStat(sid, v)
 	self.actor.unused_stats = self.actor.unused_stats - v
-	self.c_list.list[sel].base = self.actor:getStat(sel, nil, nil, true)
-	self.c_list.list[sel].val = self.actor:getStat(sel)
-	self.c_list.list[sel].color = 	{(self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true)) and {255, 255, 255} or {255, 215, 0},
-									(self.actor_dup:getStat(self.sel, nil, nil, true) == self.actor:getStat(self.sel, nil, nil, true)) and {255, 255, 255} or {255, 215, 0},
-									(self.actor:getStat(self.sel, nil, nil, true) - self.actor_dup:getStat(self.sel, nil, nil, true) + self.actor_dup:getStat(self.sel) == self.actor:getStat(self.sel)) and {255, 255, 255} or {255, 215, 0}}
-	self.c_list.sel = sel
-
-	local stats = { "str", "dex", "mag", "wil", "cun", "con" }
-	for i = 1,6 do
-		stat_sel = stats[i]
-		if self.talent_stats_req[stat_sel] then
-			to_remove = {}
-			for j=1,#self.talent_stats_req[stat_sel] do
-				local t = self.talent_stats_req[stat_sel][j][2]
-				if type(t.require) == "function" then
-					stats_req = t.require(self.actor, t).stat
-					for stat, _ in pairs(stats_req) do
-						if stat ~= stat_sel then
-							self.talent_stats_req[stat] = self.talent_stats_req[stat] or {}
-							self.talent_stats_req[stat][#self.talent_stats_req[stat] + 1] = { self.talent_stats_req[stat_sel][j][1], t }
-							to_remove[#to_remove+1] = j
-						end
-					end
-				end
-			end
-			local off = 0
-			for j=1,#to_remove do
-				table.remove(self.talent_stats_req[stat_sel], to_remove[j] - off)
-				off = off + 1
-			end
-		end
-	end
 
-	self.stats_increased[sel] = (self.stats_increased[sel] or 0) + v
-
-	self.c_list:onSelect(true)
-	self.c_list:drawItem(self.c_list.list[self.c_list.sel])
-	self.c_points.text = _points_text:format(self.actor.unused_stats)
-	self.c_points:generate()
-	self.new_stats_changed = true
-	self:onSelectStat(self.c_list.list[self.c_list.sel], true)
+	self.stats_increased[sid] = (self.stats_increased[sid] or 0) + v
 end
 
 function _M:computeDeps(t)
@@ -452,7 +414,6 @@ end
 
 function _M:generateList()
 	self.actor.__show_special_talents = self.actor.__show_special_talents or {}
-	self.talent_stats_req = {}
 
 	-- Makes up the list
 	local tree = {}
@@ -515,48 +476,100 @@ function _M:generateList()
 							end
 						end
 					end
-
-					if t.require then
-						local stats = {}
-						if type(t.require) == "table" and t.require.stat then
-							stats = t.require.stat
-						elseif type(t.require) == "function" and t.require(self.actor,t).stat then
-							stats = t.require(self.actor,t).stat
-						end
-						for stat, _ in pairs(stats) do
-							self.talent_stats_req[stat] = self.talent_stats_req[stat] or {}
-							self.talent_stats_req[stat][#self.talent_stats_req[stat] + 1] = { list[#list], t }
-						end
-					end
 				end
 			end
 		end
 	end
-	table.sort(tree, function(a, b) 
+	table.sort(tree, function(a, b)
 		if a.isgeneric == b.isgeneric then
 			return a.order_id < b.order_id
 		else
-			return a.isgeneric < b.isgeneric  
+			return a.isgeneric < b.isgeneric
 		end
 	end)
 	self.tree = tree
+
+	-- Makes up the stats list
+	local phys, mind = {}, {}
+	self.tree_stats = {{shown=true, nodes=phys, name="Physical Stats", type_stat=true}, {shown=true, nodes=mind, name="Mental Stats", type_stat=true}}
+
+	for i, sid in ipairs{self.actor.STAT_STR, self.actor.STAT_DEX, self.actor.STAT_CON, self.actor.STAT_MAG, self.actor.STAT_WIL, self.actor.STAT_CUN } do
+		local s = self.actor.stats_def[sid]
+		local e = engine.Entity.new{image="stats/"..s.short_name:lower()..".png", is_stat=true}
+		e:getMapObjects(game.uiset.hotkeys_display_icons.tiles, {}, 1)
+
+		local stats = (i <= 3) and phys or mind
+		stats[#stats+1] = {
+			name=s.name,
+			rawname=s.name,
+			entity=e,
+			stat=sid,
+			desc=s.description,
+			color=function(item)
+				if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 or
+				   self.actor:isStatMax(sid) or
+				   self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then
+					return {255, 0, 0}
+				else
+					return {175,175,175}
+				end
+			end,
+			status = function(item)
+				if self.actor:getStat(sid, nil, nil, true) >= self.actor.level * 1.4 + 20 or
+				   self.actor:isStatMax(sid) or
+				   self.actor:getStat(sid, nil, nil, true) >= 60 + math.max(0, (self.actor.level - 50)) then
+					return tstring{{"color", 0xFF, 0x00, 0x00}, tostring(self.actor:getStat(sid))}
+				else
+					return tstring{{"color", 0x00, 0xFF, 0x00}, tostring(self.actor:getStat(sid))}
+				end
+			end,
+		}
+	end
 end
 
 -----------------------------------------------------------------
 -- UI Stuff
 -----------------------------------------------------------------
 
+local _points_left = [[
+Stats points left: #00FF00#%d#LAST#
+Category points left: #00FF00#%d#LAST#
+Class talent points left: #00FF00#%d#LAST#
+Generic talent points left: #00FF00#%d#LAST#]]
+
 function _M:createDisplay()
 	self.c_tree = TalentTrees.new{
-		tiles=game.uiset.hotkeys_display_icons, 
-		tree=self.tree, 
-		width=self.iw-10, height=self.ih-10, 
-		tooltip=function(item) return self:getTalentDesc(item) end,
+		tiles=game.uiset.hotkeys_display_icons,
+		tree=self.tree,
+		width=self.iw-200-10, height=self.ih-10,
+		tooltip=function(item) return self:getTalentDesc(item), self.uis[3].x - game.tooltip.max, nil end,
+		on_use = function(item, inc) self:onUseTalent(item, inc) end,
+	}
+
+	self.c_stat = TalentTrees.new{
+		tiles=game.uiset.hotkeys_display_icons,
+		tree=self.tree_stats, no_cross = true,
+		width=200, height=210,
+		tooltip=function(item) return item.desc end,
 		on_use = function(item, inc) self:onUseTalent(item, inc) end,
+		on_expand = function(item) self.actor.__hidden_talent_types[item.type] = not item.shown end,
+	}
+
+	self.c_points = Textzone.new{
+		width=200, height=1, auto_height=true,
+		text=_points_left:format(self.actor.unused_stats, self.actor.unused_talents_types, self.actor.unused_talents, self.actor.unused_generics)
 	}
 
+	local vsep = Separator.new{dir="horizontal", size=self.ih - 20}
+	local hsep = Separator.new{dir="vertical", size=180}
+
 	return {
-		{left=0, top=0, ui=self.c_tree},
+		{left=0, top=0, ui=self.c_stat},
+		{left=self.c_stat, top=10, ui=vsep},
+		{left=vsep, top=0, ui=self.c_tree},
+
+		{left=10, top=210, ui=hsep},
+		{left=0, top=hsep, ui=self.c_points},
 	}
 end
 
@@ -625,10 +638,19 @@ end
 function _M:onUseTalent(item, inc)
 	if item.type then
 		self:learnType(item.type, inc)
+		item.shown = (self.actor.__hidden_talent_types[item.type] == nil and self.actor:knowTalentType(item.type)) or (self.actor.__hidden_talent_types[item.type] ~= nil and not self.actor.__hidden_talent_types[item.type])
+		self.c_tree:redrawAllItems()
 	elseif item.talent then
 		self:learnTalent(item.talent, inc)
+		self.c_tree:redrawAllItems()
+	elseif item.stat then
+		self:incStat(item.stat, inc and 1 or -1)
+		self.c_stat:redrawAllItems()
+		self.c_tree:redrawAllItems()
 	end
-	self.c_tree:drawItem(item)
+
+	self.c_points.text = _points_left:format(self.actor.unused_stats, self.actor.unused_talents_types, self.actor.unused_talents, self.actor.unused_generics)
+	self.c_points:generate()
 end
 
 function _M:updateTooltip()
diff --git a/game/modules/tome/dialogs/elements/TalentTrees.lua b/game/modules/tome/dialogs/elements/TalentTrees.lua
index 7c1df4648b1b46502dcaa0b6a46a804a12a9c18d..d3b10edfc25117b5df02ba0758aa66285535e739 100644
--- a/game/modules/tome/dialogs/elements/TalentTrees.lua
+++ b/game/modules/tome/dialogs/elements/TalentTrees.lua
@@ -32,6 +32,8 @@ function _M:init(t)
 	self.h = assert(t.height, "no height")
 	self.tooltip = assert(t.tooltip, "no tooltip")
 	self.on_use = assert(t.on_use, "no on_use")
+	self.on_expand = t.on_expand
+	self.no_cross = t.no_cross
 
 	self.icon_size = 48
 	self.frame_size = 50
@@ -40,6 +42,8 @@ function _M:init(t)
 
 	self.shadow = 0.7
 
+	self.frame_sel = self:makeFrame("ui/selector-sel", self.frame_size, self.frame_size)
+	self.frame_usel = self:makeFrame("ui/selector", self.frame_size, self.frame_size)
 	self.talent_frame = self:makeFrame("ui/icon-frame/frame", self.frame_size, self.frame_size)
 	self.plus = _M:getUITexture("ui/plus.png")
 	self.minus = _M:getUITexture("ui/minus.png")
@@ -51,14 +55,19 @@ function _M:onUse(item, inc)
 	self.on_use(item, inc)
 end
 
+function _M:onExpand(item, inc)
+	item.shown = not item.shown
+	if self.on_expand then self.on_expand(item) end
+end
+
 function _M:updateTooltip()
 	if not self.last_mz then
 		game.tooltip_x = nil
-		return 
+		return
 	end
 	local mz = self.last_mz
 	local str = self.tooltip(mz.item)
-	game:tooltipDisplayAtMap(self.last_display_x + mz.x2, self.last_display_y + mz.y1, str)
+	game:tooltipDisplayAtMap(mz.tx or (self.last_display_x + mz.x2), mz.ty or (self.last_display_y + mz.y1), str)
 end
 
 function _M:doScroll(v)
@@ -78,14 +87,7 @@ function _M:generate()
 
 	self.mousezones = {}
 
-	for i = 1, #self.tree do
-		local tree = self.tree[i]
-		self:drawItem(tree)
-		for j = 1, #tree.nodes do
-			local tal = tree.nodes[j]
-			self:drawItem(tal)
-		end
-	end
+	self:redrawAllItems()
 
 	-- Add UI controls
 	self.mouse:registerZone(0, 0, self.w, self.h, function(button, x, y, xrel, yrel, bx, by, event)
@@ -98,12 +100,20 @@ function _M:generate()
 			local mz = self.mousezones[i]
 			if x >= mz.x1 and x <= mz.x2 and y >= mz.y1 and y <= mz.y2 then
 				if not self.last_mz or mz.item ~= self.last_mz.item then
-					local str = self.tooltip(mz.item)
-					game:tooltipDisplayAtMap(self.last_display_x + mz.x2, self.last_display_y + mz.y1, str)
+					local str, fx, fy = self.tooltip(mz.item)
+					mz.tx, mz.ty = fx or (self.last_display_x + mz.x2), fy or (self.last_display_y + mz.y1)
+					game:tooltipDisplayAtMap(mz.tx, mz.ty, str)
+				end
+
+				if event == "button" and (button == "left" or button == "right") then
+					if mz.item.type then
+						if x - mz.x1 >= self.plus.w then self:onUse(mz.item, button == "left")
+						else self:onExpand(mz.item, button == "left") end
+					else
+						self:onUse(mz.item, button == "left")
+					end
 				end
 
-				if event == "button" and (button == "left" or button == "right") then self:onUse(mz.item, button == "left") end
-				
 				self.last_mz = mz
 				done = true
 				break
@@ -133,17 +143,41 @@ function _M:generate()
 end
 
 function _M:drawItem(item)
-	if item.talent then
+	if item.stat then
+		local str = item:status():toString()
+		local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1]
+		item.text_status = d
+	elseif item.type_stat then
+		local str = item.name:toString()
+		self.font:setStyle("bold")
+		local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1]
+		self.font:setStyle("normal")
+		item.text_status = d
+	elseif item.talent then
 		local str = item:status():toString()
 		local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1]
 		item.text_status = d
 	elseif item.type then
 		local str = item:rawname():toString()
-		local d = self.font:draw(str, self.font:size(str), 255, 255, 255, true)[1]
+		local c = item:color()
+		self.font:setStyle("bold")
+		local d = self.font:draw(str, self.font:size(str), c[1], c[2], c[3], true)[1]
+		self.font:setStyle("normal")
 		item.text_status = d
 	end
 end
 
+function _M:redrawAllItems()
+	for i = 1, #self.tree do
+		local tree = self.tree[i]
+		self:drawItem(tree)
+		for j = 1, #tree.nodes do
+			local tal = tree.nodes[j]
+			self:drawItem(tal)
+		end
+	end
+end
+
 function _M:display(x, y, nb_keyframes, screen_x, screen_y)
 	self.last_display_x = screen_x
 	self.last_display_y = screen_y
@@ -153,19 +187,32 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y)
 
 	local dx, dy = 0, 0
 
+	if self.last_mz then
+		self:drawFrame(self.focused and self.frame_sel or self.frame_usel, x+self.last_mz.x1-2, y+self.last_mz.y1-2, 1, 1, 1, 1, self.last_mz.x2-self.last_mz.x1+4, self.last_mz.y2-self.last_mz.y1+4)
+	end
+
 	self.max_display = 1
 	for i = self.scroll, #self.tree do
 		local tree = self.tree[i]
 
 		if tree.text_status then
 			local key = tree.text_status
+			local cross = not tree.shown and self.plus or self.minus
+
+			mz[#mz+1] = {item=tree, x1=dx, y1=dy, x2=dx+cross.w + 3 + key.w, y2=dy+cross.h}
+
+			if not self.no_cross then
+				cross.t:toScreenFull(dx+x, dy+y + (-cross.h + key.h) / 2, cross.w, cross.h, cross.tw, cross.th)
+				dx = dx + cross.w + 3
+			end
+
 			if self.shadow then key._tex:toScreenFull(dx+x + 2, dy+y + 2, key.w, key.h, key._tex_w, key._tex_h, 0, 0, 0, self.shadow) end
 			key._tex:toScreenFull(dx+x, dy+y, key.w, key.h, key._tex_w, key._tex_h)
 			dy = dy + key.h + 4
 		end
 
 		local addh = 0
-		for j = 1, #tree.nodes do
+		if tree.shown then for j = 1, #tree.nodes do
 			local tal = tree.nodes[j]
 
 			tal.entity:toScreen(self.tiles, dx+x + self.icon_offset, dy+y + self.icon_offset, self.icon_size, self.icon_size)
@@ -173,8 +220,6 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y)
 			local rgb = tal:color()
 			self:drawFrame(self.talent_frame, dx+x, dy+y, rgb[1]/255, rgb[2]/255, rgb[3]/255, 1)
 
-			mz[#mz+1] = {item=tal, x1=dx, y1=dy, x2=dx+self.frame_size, y2=dy+self.frame_size}
-
 			if tal.text_status then
 				local key = tal.text_status
 				if self.shadow then key._tex:toScreenFull(dx+x + (self.frame_size - key.w)/2 + 2, dy+y + self.frame_size + 4, key.w, key.h, key._tex_w, key._tex_h, 0, 0, 0, self.shadow) end
@@ -182,11 +227,14 @@ function _M:display(x, y, nb_keyframes, screen_x, screen_y)
 				addh = key.h
 			end
 
+			mz[#mz+1] = {item=tal, x1=dx, y1=dy, x2=dx+self.frame_size, y2=dy+self.frame_size+addh}
+
 			dx = dx + self.frame_size + self.frame_offset
-		end
+			addh = addh + self.frame_size
+		end end
 		self.max_display = i
 		dx = 0
-		dy = dy + self.frame_size + addh + 12
+		dy = dy + addh + 12
 		if dy + self.frame_size >= self.h then break end
 	end