diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 7ae87966b1dfe3a912348ede4bbc5f4c082b8287..cff8b6c5902fcce80969fd57c3968c01a2e1b6c0 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -1351,7 +1351,7 @@ function _M:levelup()
 	if self.alchemy_golem then self.alchemy_golem:forceLevelup(self.level) end
 
 	-- Notify party levelups
-	if self.x and self.y and game.party:hasMember(self) then
+	if self.x and self.y and game.party:hasMember(self) and not self.silent_levelup then
 		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 [%s].", self.level, self.name:capitalize())
diff --git a/game/modules/tome/data/birth/races/dwarf.lua b/game/modules/tome/data/birth/races/dwarf.lua
index 40a65ee10298860968f911a8bb81dcc31dec3378..b67e609b857387ebb5b2b496c4b86ddd1bb45804 100644
--- a/game/modules/tome/data/birth/races/dwarf.lua
+++ b/game/modules/tome/data/birth/races/dwarf.lua
@@ -69,6 +69,7 @@ newBirthDescriptor
 		"#GOLD#Experience penalty:#LIGHT_BLUE# 25%",
 	},
 	inc_stats = { str=4, con=3, wil=3, mag=-2, dex=-2 },
+	talents_types = { ["race/dwarf"]={true, 0} },
 	talents = {
 		[ActorTalents.T_DWARF_RESILIENCE]=1,
 	},
diff --git a/game/modules/tome/data/birth/races/elf.lua b/game/modules/tome/data/birth/races/elf.lua
index 132ed9d553277705de8719d572d3d9737acbfb75..2a6559a3226a1aca09d9671312fd93f3b8d933b7 100644
--- a/game/modules/tome/data/birth/races/elf.lua
+++ b/game/modules/tome/data/birth/races/elf.lua
@@ -70,6 +70,7 @@ newBirthDescriptor
 	},
 	inc_stats = { str=-2, mag=2, wil=3, cun=1, dex=1, con=0 },
 	experience = 1.3,
+	talents_types = { ["race/shalore"]={true, 0} },
 	talents = { [ActorTalents.T_SHALOREN_SPEED]=1 },
 	copy = {
 		default_wilderness = {"playerpop", "shaloren"},
@@ -102,6 +103,7 @@ newBirthDescriptor
 	},
 	inc_stats = { str=2, mag=-2, wil=1, cun=0, dex=3, con=1 },
 	experience = 1.3,
+	talents_types = { ["race/thalore"]={true, 0} },
 	talents = { [ActorTalents.T_THALOREN_WRATH]=1 },
 	copy = {
 		faction = "thalore",
diff --git a/game/modules/tome/data/birth/races/halfling.lua b/game/modules/tome/data/birth/races/halfling.lua
index a5194bbcc5ea3eb78f637ee196cd8a8ed834ecf0..750190c76788a590e34c28f7015d29ce3c77bffc 100644
--- a/game/modules/tome/data/birth/races/halfling.lua
+++ b/game/modules/tome/data/birth/races/halfling.lua
@@ -74,6 +74,7 @@ newBirthDescriptor
 	},
 	inc_stats = { str=-3, dex=3, con=1, cun=3, lck=5, },
 	experience = 1.20,
+	talents_types = { ["race/halfling"]={true, 0} },
 	talents = {
 		[ActorTalents.T_HALFLING_LUCK]=1,
 	},
diff --git a/game/modules/tome/data/birth/races/yeek.lua b/game/modules/tome/data/birth/races/yeek.lua
index ef3554a1c07397617840eeeba755f5969e0dfddf..7e44ba4bfecb97297eb4b76431ee3653fe59a01f 100644
--- a/game/modules/tome/data/birth/races/yeek.lua
+++ b/game/modules/tome/data/birth/races/yeek.lua
@@ -73,6 +73,7 @@ newBirthDescriptor
 		"#GOLD#Confusion resistance:#LIGHT_BLUE# 35%",
 	},
 	inc_stats = { str=-3, con=-5, cun=4, wil=6, mag=0, dex=-2 },
+	talents_types = { ["race/yeek"]={true, 0} },
 	talents = {
 		[ActorTalents.T_YEEK_WILL]=1,
 		[ActorTalents.T_YEEK_ID]=1,
diff --git a/game/modules/tome/data/talents/gifts/gifts.lua b/game/modules/tome/data/talents/gifts/gifts.lua
index 599bfae517c5278b56363e7143ad60fc535d41ee..8878c61a96fef685217763e21fa7121f2abbb28d 100644
--- a/game/modules/tome/data/talents/gifts/gifts.lua
+++ b/game/modules/tome/data/talents/gifts/gifts.lua
@@ -82,7 +82,7 @@ function checkMaxSummon(self, silent)
 	end
 end
 
-function setupSummon(self, m, x, y)
+function setupSummon(self, m, x, y, no_control)
 	m.unused_stats = 0
 	m.unused_talents = 0
 	m.unused_generics = 0
@@ -99,9 +99,11 @@ function setupSummon(self, m, x, y)
 	m:attr("pin_immune", self:attr("pin_immune"))
 	m:attr("confusion_immune", self:attr("confusion_immune"))
 	if game.party:hasMember(self) then
+		local can_control = not no_controll and self:knowTalent(self.T_SUMMON_CONTROL)
+
 		m.remove_from_party_on_death = true
 		game.party:addMember(m, {
-			control=self:knowTalent(self.T_SUMMON_CONTROL) and "full" or "no",
+			control=can_control and "full" or "no",
 			type="summon",
 			title="Summon",
 			orders = {target=true, leash=true, anchor=true, talents=true},
diff --git a/game/modules/tome/data/talents/misc/races.lua b/game/modules/tome/data/talents/misc/races.lua
index 3a8d474040ed9e069578c99bd1daac784d517f88..fcf9443951ef6652b0def3199417d9632cee01e7 100644
--- a/game/modules/tome/data/talents/misc/races.lua
+++ b/game/modules/tome/data/talents/misc/races.lua
@@ -90,7 +90,7 @@ newTalent{
 	end,
 	info = function(self, t)
 		return ([[Highers have originaly been created during the Age of Allure by the human Conclave. They are imbued with magic at the very core of their being.
-		Increase spell save by +%d and Arcane resistance by %d%%.]]):format(self:getTalentLevel(t) * 3, self:getTalentLevel(t) * 5)
+		Increase spell save by +%d and Arcane resistance by %d%%.]]):format(self:getTalentLevelRaw(t) * 3, self:getTalentLevelRaw(t) * 5)
 	end,
 }
 
@@ -126,7 +126,7 @@ newTalent{
 	info = function(self, t)
 		local d = t.getData(self, t)
 		return ([[Activate some of your inner magic, manipulating the world to be in a better shape for you.
-		Restores %d stamina, %d mana, %d equilibrium, %d vim, %d positive and negative energies, -%d paradox and %d psi energy.
+		Restores %d stamina, %d mana, %d equilibrium, %d vim, %d positive and negative energies, %d paradox and %d psi energy.
 		The effect increases with your Constitution.]]):format(d.stamina, d.mana, d.equilibrium, d.vim, d.positive, d.paradox, d.psi)
 	end,
 }
@@ -139,8 +139,9 @@ newTalent{
 	short_name = "SHALOREN_SPEED",
 	name = "Grace of the Eternals",
 	type = {"race/shalore", 1},
+	require = racial_req1,
 	no_energy = true,
-	cooldown = 50,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 5 end,
 	tactical = { DEFEND = 1 },
 	action = function(self, t)
 		local power = 0.1 + self:getDex() / 210
@@ -153,6 +154,137 @@ newTalent{
 	end,
 }
 
+------------------------------------------------------------------
+-- Thaloren powers
+------------------------------------------------------------------
+newTalentType{ type="race/thalore", name = "thalore", generic = true, description = "The various racial bonuses a character can have." }
+newTalent{
+	short_name = "THALOREN_WRATH",
+	name = "Wrath of the Woods",
+	type = {"race/thalore", 1},
+	require = racial_req1,
+	points = 5,
+	no_energy = true,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 5 end,
+	tactical = { ATTACK = 1, DEFEND = 1 },
+	action = function(self, t)
+		self:setEffect(self.EFF_ETERNAL_WRATH, 5, {power=7 + self:getWil(10)})
+		return true
+	end,
+	info = function(self, t)
+		return ([[Call upon the power of the Eternals, increasing all damage by %d%% and reducing all damage taken by %d%% for 5 turns.
+		The bonus will increase with the Willpower stat]]):format(7 + self:getWil(10), 7 + self:getWil(10))
+	end,
+}
+
+newTalent{
+	name = "Unshackled",
+	type = {"race/thalore", 2},
+	require = racial_req2,
+	points = 5,
+	mode = "passive",
+	on_learn = function(self, t)
+		self.combat_physresist = self.combat_physresist + 5
+		self.combat_mentalresist = self.combat_mentalresist + 5
+	end,
+	on_unlearn = function(self, t)
+		self.combat_physresist = self.combat_physresist - 5
+		self.combat_mentalresist = self.combat_mentalresist - 5
+	end,
+	info = function(self, t)
+		return ([[Thaloren have always been a free people, living in their beloved forest, never carrying much about the world outside.
+		Increase physical and mental save by +%d.]]):format(self:getTalentLevelRaw(t) * 5)
+	end,
+}
+
+newTalent{
+	name = "Guardian of the Wood",
+	type = {"race/thalore", 3},
+	require = racial_req3,
+	points = 5,
+	mode = "passive",
+	on_learn = function(self, t)
+		self.disease_immune = self.disease_immune + 0.12
+		self.resists[DamageType.BLIGHT] = (self.resists[DamageType.BLIGHT] or 0) + 4
+	end,
+	on_unlearn = function(self, t)
+		self.disease_immune = self.disease_immune - 0.12
+		self.resists[DamageType.BLIGHT] = (self.resists[DamageType.BLIGHT] or 0) - 4
+	end,
+	info = function(self, t)
+		return ([[You are part of the wood, it shields you from corruption.
+		Increase diseases immunity by %d%% and Blight resistance by %d%%.]]):format(self:getTalentLevel(t) * 12, self:getTalentLevel(t) * 4)
+	end,
+}
+
+newTalent{
+	name = "Nature's Pride",
+	type = {"race/thalore", 4},
+	require = racial_req4,
+	points = 5,
+	no_energy = true,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 3 end,
+	tactical = { ATTACK = 2 },
+	action = function(self, t)
+		local tg = {type="bolt", nowarning=true, range=self:getTalentRange(t), nolock=true, talent=t}
+		local tx, ty, target = self:getTarget(tg)
+		if not tx or not ty then return nil end
+		local _ _, tx, ty = self:canProject(tg, tx, ty)
+		target = game.level.map(tx, ty, Map.ACTOR)
+		if target == self then target = nil end
+
+		-- Find space
+		for i = 1, 2 do
+			local x, y = util.findFreeGrid(tx, ty, 5, true, {[Map.ACTOR]=true})
+			if not x then
+				game.logPlayer(self, "Not enough space to summon!")
+				return
+			end
+
+			local NPC = require "mod.class.NPC"
+			local m = NPC.new{
+				type = "immovable", subtype = "plants",
+				display = "#",
+				name = "treant", color=colors.GREEN,
+				desc = "A very strong near-sentient tree.",
+
+				body = { INVEN = 10, MAINHAND=1, OFFHAND=1, BODY=1 },
+
+				rank = 3,
+				life_rating = 13,
+				max_life = resolvers.rngavg(50,80),
+				infravision = 20,
+
+				autolevel = "none",
+				ai = "summoned", ai_real = "tactical", ai_state = { talent_in=2, },
+				stats = {str=0, dex=0, con=0, cun=0, wil=0, mag=0},
+				combat = { dam=resolvers.levelup(resolvers.rngavg(15,25), 1, 1.3), atk=resolvers.levelup(resolvers.rngavg(15,25), 1, 1.3), dammod={str=1.1} },
+				inc_stats = { str=25 + self:getWil() * self:getTalentLevel(t) / 5, dex=18, con=10 + self:getTalentLevel(t) * 2, },
+
+				level_range = {1, nil}, exp_worth = 0,
+				silent_levelup = true,
+
+				combat_armor = 13, combat_def = 8,
+				resolvers.talents{ [Talents.T_STUN]=3, [Talents.T_KNOCKBACK]=2, },
+
+				faction = self.faction,
+				summoner = self, summoner_gain_exp=true,
+				summon_time = 6,
+				ai_target = {actor=target}
+			}
+			setupSummon(self, m, x, y)
+		end
+
+		game:playSoundNear(self, "talents/spell_generic")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Nature is with you, you can always feel the call of the woods.
+		Summons two elite Treants to your side for 6 turns.
+		Their strength increase with your Willpower stat]]):format()
+	end,
+}
+
 ------------------------------------------------------------------
 -- Dwarvess powers
 ------------------------------------------------------------------
@@ -161,8 +293,9 @@ newTalent{
 	short_name = "DWARF_RESILIENCE",
 	name = "Resilience of the Dwarves",
 	type = {"race/dwarf", 1},
+	require = racial_req1,
 	no_energy = true,
-	cooldown = 50,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 5 end,
 	tactical = { DEFEND = 2 },
 	action = function(self, t)
 		self:setEffect(self.EFF_DWARVEN_RESILIENCE, 8, {
@@ -186,8 +319,9 @@ newTalent{
 	short_name = "HALFLING_LUCK",
 	name = "Luck of the Little Folk",
 	type = {"race/halfling", 1},
+	require = racial_req1,
 	no_energy = true,
-	cooldown = 50,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 5 end,
 	tactical = { ATTACK = 2 },
 	action = function(self, t)
 		self:setEffect(self.EFF_HALFLING_LUCK, 5, {
@@ -202,27 +336,6 @@ newTalent{
 	end,
 }
 
-------------------------------------------------------------------
--- Thaloren powers
-------------------------------------------------------------------
-newTalentType{ type="race/thalore", name = "thalore", generic = true, description = "The various racial bonuses a character can have." }
-newTalent{
-	short_name = "THALOREN_WRATH",
-	name = "Wrath of the Eternals",
-	type = {"race/thalore", 1},
-	no_energy = true,
-	cooldown = 50,
-	tactical = { ATTACK = 1, DEFEND = 1 },
-	action = function(self, t)
-		self:setEffect(self.EFF_ETERNAL_WRATH, 5, {power=7 + self:getWil(10)})
-		return true
-	end,
-	info = function(self, t)
-		return ([[Call upon the power of the Eternals, increasing all damage by %d%% and reducing all damage taken by %d%% for 5 turns.
-		The bonus will increase with the Willpower stat]]):format(7 + self:getWil(10), 7 + self:getWil(10))
-	end,
-}
-
 ------------------------------------------------------------------
 -- Orcs powers
 ------------------------------------------------------------------
@@ -231,8 +344,9 @@ newTalent{
 	short_name = "ORC_FURY",
 	name = "Orcish Fury",
 	type = {"race/orc", 1},
+	require = racial_req1,
 	no_energy = true,
-	cooldown = 50,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 5 end,
 	tactical = { ATTACK = 2 },
 	action = function(self, t)
 		self:setEffect(self.EFF_ORC_FURY, 5, {power=10 + self:getWil(20)})
@@ -252,8 +366,9 @@ newTalent{
 	short_name = "YEEK_WILL",
 	name = "Dominant Will",
 	type = {"race/yeek", 1},
+	require = racial_req1,
 	no_energy = true,
-	cooldown = 50,
+	cooldown = function(self, t) return 50 - self:getTalentLevel(t) * 3 end,
 	range = 4,
 	no_npc_use = true,
 	action = function(self, t)
diff --git a/ideas/races.ods b/ideas/races.ods
index dec74eea61ca17c0e17bf87b5fcfcfffba3aadae..1b21044c6ad18fc6be08b6ec121dc89fb2d22b68 100644
Binary files a/ideas/races.ods and b/ideas/races.ods differ