diff --git a/game/engine/resolvers.lua b/game/engine/resolvers.lua
index 0123317f26e51acf07b77c437c9d95ae26e2db80..c4fef90a3e85b09d774cf5017d339388a880b151 100644
--- a/game/engine/resolvers.lua
+++ b/game/engine/resolvers.lua
@@ -36,6 +36,14 @@ function resolvers.calc.rngavg(t)
 	return rng.avg(t[1], t[2])
 end
 
+--- Random table element
+function resolvers.rngtable(t)
+	return {__resolver="rngtable", t}
+end
+function resolvers.calc.rngtable(t)
+	return rng.table(t[1])
+end
+
 --- Random bonus based on level
 resolvers.current_level = 1
 resolvers.mbonus_max_level = 50
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 4a0a7604fbf5d293d91e74d443c3b84cd8f371fd..be098e8d592daadc7688c4bc99521c5386a051b6 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -194,6 +194,9 @@ function _M:act()
 	-- Still enough energy to act ?
 	if self.energy.value < game.energy_to_act then return false end
 
+	-- Still not dead ?
+	if self.dead then return false end
+
 	return true
 end
 
diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua
index 9305598c68b2909555e3f4fe028c0dff478c7b28..6b7535642bb7eb3029ff29a30383420ad390f1df 100644
--- a/game/modules/tome/class/Object.lua
+++ b/game/modules/tome/class/Object.lua
@@ -100,6 +100,9 @@ function _M:descAttribute(attr)
 	elseif attr == "COMBAT" then
 		local c = self.combat
 		return c.dam.."-"..(c.dam*(c.damrange or 1.1)).." power, "..(c.apr or 0).." apr"
+	elseif attr == "COMBAT_DAMTYPE" then
+		local c = self.combat
+		return c.dam.."-"..(c.dam*(c.damrange or 1.1)).." power, "..(c.apr or 0).." apr, "..DamageType:get(c.damtype).name.." damage"
 	elseif attr == "ARMOR" then
 		return (self.wielder and self.wielder.combat_def or 0).." def, "..(self.wielder and self.wielder.combat_armor or 0).." armor"
 	elseif attr == "ATTACK" then
@@ -161,13 +164,13 @@ function _M:getTextualDesc()
 	-- Stop here if unided
 	if not self:isIdentified() then return table.concat(desc, "\n") end
 
-
 	if self.combat then
 		local dm = {}
 		for stat, i in pairs(self.combat.dammod or {}) do
 			dm[#dm+1] = ("+%d%% %s"):format(i * 100, Stats.stats_def[stat].name)
 		end
 		desc[#desc+1] = ("%d Power [Range %0.2f] (%s), %d Attack, %d Armor Penetration, Crit %d%%"):format(self.combat.dam or 0, self.combat.damrange or 1.1, table.concat(dm, ','), self.combat.atk or 0, self.combat.apr or 0, self.combat.physcrit or 0)
+		desc[#desc+1] = "Damage type: "..DamageType:get(self.combat.damtype or DamageType.PHYSICAL).name
 		if self.combat.range then desc[#desc+1] = "Firing range: "..self.combat.range end
 		desc[#desc+1] = ""
 	end
@@ -275,7 +278,7 @@ function _M:getTextualDesc()
 	local use_desc = self:getUseDesc()
 	if use_desc then desc[#desc+1] = use_desc end
 
-	return table.concat(desc, "\n	 ")
+	return desc
 end
 
 --- Gets the full desc of the object
@@ -293,7 +296,7 @@ function _M:getDesc()
 		desc[#desc+1] = reqs
 	end
 
-	local textdesc = self:getTextualDesc()
+	local textdesc = table.concat(self:getTextualDesc(), "\n")
 
 	return table.concat(desc, "\n").."\n"..textdesc
 end
diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index 834bb3761349615630462b85339ec8370cce6a47..4e91813761c98dc32dacbb5141795b5912abf53b 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -364,8 +364,9 @@ local weapon_talents = {
 	axe =   Talents.T_AXE_MASTERY,
 	mace =  Talents.T_MACE_MASTERY,
 	knife = Talents.T_KNIFE_MASTERY,
-	bow = Talents.T_BOW_MASTERY,
+	bow =   Talents.T_BOW_MASTERY,
 	sling = Talents.T_SLING_MASTERY,
+	staff = Talents.T_STAFF_MASTERY,
 }
 
 --- Checks weapon training
@@ -595,6 +596,16 @@ function _M:hasAlchemistWeapon()
 	return ammo
 end
 
+--- Check if the actor has a two handed weapon
+function _M:hasTwoStaffWeapon()
+	if not self:getInven("MAINHAND") then return end
+	local weapon = self:getInven("MAINHAND")[1]
+	if not weapon or weapon.subtype ~= "staff" then
+		return nil
+	end
+	return weapon
+end
+
 --- Check if the actor has a two handed weapon
 function _M:hasTwoHandedWeapon()
 	if not self:getInven("MAINHAND") then return end
diff --git a/game/modules/tome/data/general/objects/staves.lua b/game/modules/tome/data/general/objects/staves.lua
index 9cef77c0ac66e39e5e6b1b9f1114a0a0a52553bd..4c8c51ccfbc7d596f5ce990e7f23ad7ae69e6d51 100644
--- a/game/modules/tome/data/general/objects/staves.lua
+++ b/game/modules/tome/data/general/objects/staves.lua
@@ -22,10 +22,16 @@ newEntity{
 	slot = "MAINHAND",
 	slot_forbid = "OFFHAND",
 	type = "weapon", subtype="staff",
-	add_name = " (#COMBAT#)",
+	add_name = " (#COMBAT_DAMTYPE#)",
 	display = "\\", color=colors.LIGHT_RED,
 	encumber = 5,
 	rarity = 4,
+	combat = {
+		talented = "staff",
+		damrange = 1.2,
+		sound = "actions/melee", sound_miss = "actions/melee_miss",
+		damtype = resolvers.rngtable{DamageType.FIRE, DamageType.COLD, DamageType.ACID, DamageType.LIGHTNING, DamageType.LIGHT, DamageType.DARKNESS, DamageType.NATURE, DamageType.BLIGHT},
+	},
 	desc = [[Staves designed for wielders of magic, by the greats of the art.]],
 	egos = "/data/general/objects/egos/staves.lua", egos_chance = { prefix=resolvers.mbonus(40, 5), suffix=resolvers.mbonus(40, 5) },
 }
diff --git a/game/modules/tome/data/talents/spells/enhancement.lua b/game/modules/tome/data/talents/spells/enhancement.lua
index eff5d11134a8572cb889b557a1d81f6f82be7ea4..f39cd94173d1eba25df73fff9812232897036d0d 100644
--- a/game/modules/tome/data/talents/spells/enhancement.lua
+++ b/game/modules/tome/data/talents/spells/enhancement.lua
@@ -106,7 +106,7 @@ newTalent{
 	},
 	activate = function(self, t)
 		game:playSoundNear(self, "talents/spell_generic")
-		local power = math.floor(self:combatTalentSpellDamage(t, 2, 18))
+		local power = math.min(math.floor(self:combatTalentSpellDamage(t, 2, 10)), 11)
 		return {
 			stats = self:addTemporaryValue("inc_stats", {
 				[self.STAT_STR] = power,
@@ -124,6 +124,6 @@ newTalent{
 	end,
 	info = function(self, t)
 		return ([[You concentrate on your inner self, increasing your stats each by %d.]]):
-		format(self:combatTalentSpellDamage(t, 2, 18))
+		format(math.min(math.floor(self:combatTalentSpellDamage(t, 2, 10)), 11))
 	end,
 }
diff --git a/game/modules/tome/data/talents/spells/golemancy.lua b/game/modules/tome/data/talents/spells/golemancy.lua
index b6f1c4609aaa1348e8fd00c7fc17ecb53339570b..2eb67336dd00547cae0f7e55261b7a578bee47d5 100644
--- a/game/modules/tome/data/talents/spells/golemancy.lua
+++ b/game/modules/tome/data/talents/spells/golemancy.lua
@@ -39,6 +39,8 @@ local function makeGolem()
 		open_door = true,
 		blind_immune = 1,
 		fear_immune = 1,
+		poison_immune = 1,
+		disease_immune = 1,
 		see_invisible = 2,
 		no_breath = 1,
 	}
@@ -81,7 +83,7 @@ newTalent{
 			-- 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!")
+				game.logPlayer(self, "Not enough space to refit!")
 				return
 			end
 			game.zone:addEntity(game.level, self.alchemy_golem, "actor", x, y)
@@ -247,10 +249,24 @@ newTalent{
 	mana = 10,
 	cooldown = 20,
 	action = function(self, t)
+		if not game.level:hasEntity(self.alchemy_golem) then
+			game.logPlayer(self, "Your golem is currently inactive.")
+			return
+		end
+
+		-- 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 invoke!")
+			return
+		end
+
+		self.alchemy_golem:setEffect(self.alchemy_golem.EFF_MIGHTY_BLOWS, 5, {power=self:combatTalentSpellDamage(t, 15, 50)})
+		self.alchemy_golem:move(x, y, true)
 		game:playSoundNear(self, "talents/arcane")
 		return true
 	end,
 	info = function(self, t)
-		return ([[Imbue an alchemist gem with an explosive charge of mana and throw it.]]):format()
+		return ([[You invoke your golem to your side, granting it a temporary melee power increase of %d for 5 turns.]]):format(self:combatTalentSpellDamage(t, 15, 50))
 	end,
 }
diff --git a/game/modules/tome/data/talents/spells/spells.lua b/game/modules/tome/data/talents/spells/spells.lua
index 17ff36aca722eb2e7b05e146d06cc039eb9f7554..ff763ccf6cf6c4373ced4c84bdd0b14e50eff246 100644
--- a/game/modules/tome/data/talents/spells/spells.lua
+++ b/game/modules/tome/data/talents/spells/spells.lua
@@ -40,6 +40,7 @@ newTalentType{ type="spell/golemancy", name = "golemancy", description = "Learn
 newTalentType{ type="spell/advanced-golemancy", name = "advanced-golemancy", description = "Advanced golem operations." }
 newTalentType{ type="spell/gemology", name = "gemology", generic = true, description = "Manipulate gems, imbue their powers into other objects." }
 newTalentType{ type="spell/herbalism", name = "herbalism", generic = true, description = "Herbs lore." }
+newTalentType{ type="spell/staff-combat", name = "staff combat", generic = true, description = "Harness the power of magical staves." }
 
 -- Generic requires for spells based on talent level
 spells_req1 = {
@@ -79,3 +80,4 @@ load("/data/talents/spells/enhancement.lua")
 load("/data/talents/spells/alchemy.lua")
 load("/data/talents/spells/infusion.lua")
 load("/data/talents/spells/golemancy.lua")
+load("/data/talents/spells/staff-combat.lua")
diff --git a/game/modules/tome/data/talents/spells/staff-combat.lua b/game/modules/tome/data/talents/spells/staff-combat.lua
new file mode 100644
index 0000000000000000000000000000000000000000..d0a9d1e230ee06d33c2271ef11613d4b301ab4a6
--- /dev/null
+++ b/game/modules/tome/data/talents/spells/staff-combat.lua
@@ -0,0 +1,122 @@
+-- ToME - Tales of Middle-Earth
+-- Copyright (C) 2009, 2010 Nicolas Casalini
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-- Nicolas Casalini "DarkGod"
+-- darkgod@te4.org
+
+newTalent{
+	name = "Channel Staff",
+	type = {"spell/staff-combat", 1},
+	require = spells_req1,
+	points = 5,
+	mana = 5,
+	tactical = {
+		ATTACK = 10,
+	},
+	range = 10,
+	reflectable = true,
+	action = function(self, t)
+		local weapon = self:hasTwoStaffWeapon()
+		if not weapon then
+			game.logPlayer(self, "You need a staff to use this spell.")
+			return
+		end
+
+		local tg = {type="bolt", range=self:getTalentRange(t), talent=t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		local dam = self:combatDamage(weapon) * self:combatTalentWeaponDamage(t, 0.4, 1.1)
+		self:project(tg, x, y, weapon.combat.damtype or DamageType.ARCANE, self:spellCrit(dam), {type="manathrust"})
+		game:playSoundNear(self, "talents/arcane")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Channel raw mana through your staff, projecting a bolt your staff damage type doing %d%% staff damage.
+		This attack always hits and ignores target armour.]]):
+		format(self:combatTalentWeaponDamage(t, 0.4, 1.1) * 100)
+	end,
+}
+
+newTalent{
+	name = "Staff Mastery",
+	type = {"spell/staff-combat", 2},
+	mode = "passive",
+	require = spells_req2,
+	points = 5,
+	info = function(self, t)
+		return ([[Increases damage done with staves by %d%%.]]):format(100 * (math.sqrt(self:getTalentLevel(t) / 10)))
+	end,
+}
+
+newTalent{
+	name = "Defensive Posture",
+	type = {"spell/staff-combat", 3},
+	require = spells_req3,
+	mode = "sustained",
+	points = 5,
+	sustain_mana = 80,
+	cooldown = 30,
+	tactical = {
+		DEFEND = 20,
+	},
+	activate = function(self, t)
+		local power = self:combatTalentSpellDamage(t, 10, 20)
+		game:playSoundNear(self, "talents/arcane")
+		return {
+			power = self:addTemporaryValue("combat_def", power),
+		}
+	end,
+	deactivate = function(self, t, p)
+		self:removeTemporaryValue("combat_def", p.power)
+		return true
+	end,
+	info = function(self, t)
+		return ([[Adopt a defensive posture, reducing your staff attack power by %d and increasing your defense by %d.
+		The mana restored will increase with the Magic stat]]):format(self:combatTalentSpellDamage(t, 20, 230))
+	end,
+}
+
+newTalent{
+	name = "Disruption Shield",
+	type = {"spell/staff-combat",4},
+	require = spells_req4, no_sustain_autoreset = true,
+	points = 5,
+	mode = "sustained",
+	sustain_mana = 150,
+	tactical = {
+		DEFEND = 10,
+	},
+	activate = function(self, t)
+		local power = math.max(0.8, 3 - (self:combatSpellpower(1) * self:getTalentLevel(t)) / 280)
+		self.disruption_shield_absorb = 0
+		game:playSoundNear(self, "talents/arcane")
+		return {
+			shield = self:addTemporaryValue("disruption_shield", power),
+			particle = self:addParticles(Particles.new("disruption_shield", 1)),
+		}
+	end,
+	deactivate = function(self, t, p)
+		self:removeParticles(p.particle)
+		self:removeTemporaryValue("disruption_shield", p.shield)
+		self.disruption_shield_absorb = nil
+		return true
+	end,
+	info = function(self, t)
+		return ([[Uses mana instead of life to take damage. Uses %0.2f mana per damage point taken.
+		If your mana is brought too low by the shield, it will de-activate and the chain reaction will release a deadly arcane explosion of the amount of damage absorbed.
+		The damage to mana ratio increases with the Magic stat]]):format(math.max(0.8, 3 - (self:combatSpellpower(1) * self:getTalentLevel(t)) / 280))
+	end,
+}
diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua
index 25a712026254eeebfac8145a5d524a1717f00bae..741260449bca9a0b686b75072df07c84846c5e02 100644
--- a/game/modules/tome/data/timed_effects.lua
+++ b/game/modules/tome/data/timed_effects.lua
@@ -652,6 +652,22 @@ newEffect{
 	end,
 }
 
+newEffect{
+	name = "MIGHTY_BLOWS",
+	desc = "Migth Blows",
+	type = "physical",
+	status = "beneficial",
+	parameters = { power=10 },
+	on_gain = function(self, err) return "#Target# looks menacing." end,
+	on_lose = function(self, err) return "#Target# looks less menacing." end,
+	activate = function(self, eff)
+		eff.tmpid = self:addTemporaryValue("combat_dam", eff.power)
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("combat_dam", eff.tmpid)
+	end,
+}
+
 newEffect{
 	name = "ROTTING_DISEASE",
 	desc = "Rotting Disease",
diff --git a/game/modules/tome/data/zones/mount-doom/npcs.lua b/game/modules/tome/data/zones/mount-doom/npcs.lua
index 1a66b03837848af8d3da89b0e2d5ce98d4a996f9..ac54e8fd32d9f7de2965a5049469547757f81ade 100644
--- a/game/modules/tome/data/zones/mount-doom/npcs.lua
+++ b/game/modules/tome/data/zones/mount-doom/npcs.lua
@@ -265,7 +265,7 @@ newEntity{ base = "BASE_NPC_FAEROS", define_as = "FYRK",
 This one looks even nastier and looks toward you with what seems to be disdain. Flames swirly all around him.]],
 	level_range = {35, nil}, exp_worth = 2,
 	rank = 5,
-	max_life = resolvers.rngavg(300,400), life_rating = 20, fixed_rating = true,
+	max_life = resolvers.rngavg(800,900), life_rating = 20, fixed_rating = true,
 	combat_armor = 0, combat_def = 20,
 	on_melee_hit = { [DamageType.FIRE] = resolvers.mbonus(30, 10), },
 	move_others=true,
diff --git a/game/modules/tome/dialogs/CharacterSheet.lua b/game/modules/tome/dialogs/CharacterSheet.lua
index 3368e24629990302142a7342143d5cc0cd69c940..36e05b8087bd312b80f22708131f55a3cf5fc88d 100644
--- a/game/modules/tome/dialogs/CharacterSheet.lua
+++ b/game/modules/tome/dialogs/CharacterSheet.lua
@@ -388,7 +388,7 @@ function _M:dump()
 				if not self.filter or self.filter(o) then
 					local char = string.char(string.byte('a') + index)
 					nl(("%s) %s"):format(char, o:getName{force_id=true}))
-					nl(("   %s"):format(o:getTextualDesc()))
+					nl(("   %s"):format(table.concat(o:getTextualDesc(), "\n    ")))
 					index = index + 1
 				end
 			end
@@ -402,7 +402,7 @@ function _M:dump()
 		if not self.filter or self.filter(o) then
 			local char = string.char(string.byte('a') + item - 1)
 			nl(("%s) %s"):format(char, o:getName{force_id=true}))
-			nl(("   %s"):format(o:getTextualDesc()))
+			nl(("   %s"):format(table.concat(o:getTextualDesc(), "\n    ")))
 		end
 	end
 
diff --git a/ideas/crafting.ods b/ideas/crafting.ods
index 33659f50e225d4236e7a70c07f18d7171d639d60..25d04e752174cd90e1c0756ec4c1615e940813bb 100644
Binary files a/ideas/crafting.ods and b/ideas/crafting.ods differ