diff --git a/game/engines/default/engine/Birther.lua b/game/engines/default/engine/Birther.lua
index ebf578a8b100c0891f9366653e522c0e37bc8e81..6205e6f13104d1e8fd825c935224323d7f58896e 100644
--- a/game/engines/default/engine/Birther.lua
+++ b/game/engines/default/engine/Birther.lua
@@ -87,6 +87,7 @@ function _M:init(title, actor, order, at_end, quickbirth, w, h)
 	Dialog.init(self, title and title or ("Character Creation: "..actor.name), w or 600, h or 400)
 
 	self.descriptors = {}
+	self.descriptors_by_type = {}
 
 	self.c_tut = Textzone.new{width=math.floor(self.iw / 2 - 10), height=1, auto_height=true, no_color_bleed=true, text=[[
 Keyboard: #00FF00#up key/down key#FFFFFF# to select an option; #00FF00#Enter#FFFFFF# to accept; #00FF00#Backspace#FFFFFF# to go back.
@@ -183,7 +184,7 @@ function _M:selectType(type)
 		print("[BIRTHER] checking allowance for ", d.name)
 		for j, od in ipairs(self.descriptors) do
 			if od.descriptor_choices and od.descriptor_choices[type] then
-				local what = util.getval(od.descriptor_choices[type][d.name]) or util.getval(od.descriptor_choices[type].__ALL__)
+				local what = util.getval(od.descriptor_choices[type][d.name], self) or util.getval(od.descriptor_choices[type].__ALL__, self)
 				if what and what == "allow" then
 					allowed = true
 				elseif what and (what == "never" or what == "disallow") then
@@ -235,6 +236,7 @@ function _M:prev()
 	end
 	if not self.list then return end
 	self.changed = true
+	self.descriptors_by_type[self.current_type] = nil
 	table.remove(self.descriptors)
 	self.cur_order = self.cur_order - 1
 	self:selectType(self.order[self.cur_order])
@@ -248,6 +250,7 @@ end
 function _M:next()
 	self.changed = true
 	if self.list then
+		self.descriptors_by_type[self.current_type] = self.list[self.sel] or "none"
 		table.insert(self.descriptors, self.list[self.sel] or "none")
 		if self.list[self.sel] and self.list[self.sel].on_select then self.list[self.sel]:on_select() end
 
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 5e5cbba41847a78695d2d4aba5c9160b3e7b6ba5..28c6effee39e5dfb0d6cefd775e4a7ae30f898f3 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -246,6 +246,10 @@ function _M:actTurn()
 		local t = self:getTalentFromId(self.T_THUNDERSTORM)
 		t.do_storm(self, t)
 	end
+	if self:isTalentActive(self.T_STONE_VINES) then
+		local t = self:getTalentFromId(self.T_STONE_VINES)
+		t.do_vines(self, t)
+	end
 	if self:isTalentActive(self.T_BODY_OF_FIRE) then
 		local t = self:getTalentFromId(self.T_BODY_OF_FIRE)
 		t.do_fire(self, t)
diff --git a/game/modules/tome/class/interface/Combat.lua b/game/modules/tome/class/interface/Combat.lua
index f1a3a4a50c094314ff0fc48ee41a753f900109ee..5864630daee9afef664e2d156c606d3cd7bd71ec 100644
--- a/game/modules/tome/class/interface/Combat.lua
+++ b/game/modules/tome/class/interface/Combat.lua
@@ -127,14 +127,16 @@ function _M:attackTarget(target, damtype, mult, noenergy)
 		if self:getInven(self.INVEN_OFFHAND) then
 			local offmult = self:getOffHandMult(mult)
 			for i, o in ipairs(self:getInven(self.INVEN_OFFHAND)) do
-				if o.combat and not o.archery then
+				local combat = o.combat
+				if o.special_combat and o.subtype == "shield" and self:knowTalent(self.T_STONESHIELD) then combat = o.special_combat end
+				if combat and not o.archery then
 					print("[ATTACK] attacking with", o.name)
-					local s, h = self:attackTargetWith(target, o.combat, damtype, offmult)
+					local s, h = self:attackTargetWith(target, combat, damtype, offmult)
 					speed = math.max(speed or 0, s)
 					hit = hit or h
-					if hit and not sound then sound = o.combat.sound
-					elseif not hit and not sound_miss then sound_miss = o.combat.sound_miss end
-					if not o.combat.no_stealth_break then break_stealth = true end
+					if hit and not sound then sound = combat.sound
+					elseif not hit and not sound_miss then sound_miss = combat.sound_miss end
+					if not combat.no_stealth_break then break_stealth = true end
 				end
 			end
 		end
@@ -400,6 +402,13 @@ function _M:attackTargetWith(target, weapon, damtype, mult)
 	if hitted and not target.dead and target:attr("mana_regen_on_hit") then target:incMana(target.mana_regen_on_hit) end
 	if hitted and not target.dead and target:attr("equilibrium_regen_on_hit") then target:incEquilibrium(-target.equilibrium_regen_on_hit) end
 
+	if hitted and not target.dead and target:knowTalent(target.T_STONESHIELD) then
+		local t = target:getTalentFromId(target.T_STONESHIELD)
+		local m, mm, e, em = t.getValues(self, t)
+		target:incMana(math.min(dam * m, mm))
+		target:incEquilibrium(-math.min(dam * e, em))
+	end
+
 	-- Ablative Armor
 	if hitted and not target.dead and target:attr("carbon_spikes") then
 		if target.carbon_armor >= 1 then
diff --git a/game/modules/tome/data/birth/classes/wilder.lua b/game/modules/tome/data/birth/classes/wilder.lua
index 6895b0208e3eb2134e0fc3d4c78fd68d331cb105..0d5b4e15e26b1b8174b0d6a09452bb91d6220ddc 100644
--- a/game/modules/tome/data/birth/classes/wilder.lua
+++ b/game/modules/tome/data/birth/classes/wilder.lua
@@ -31,6 +31,7 @@ newBirthDescriptor{
 			__ALL__ = "disallow",
 			Summoner = function() return profile.mod.allow_build.wilder_summoner and "allow" or "disallow" end,
 			Wyrmic = function() return profile.mod.allow_build.wilder_wyrmic and "allow" or "disallow" end,
+			["Stone Warden"] = function(birth) return birth.descriptors_by_type.race and birth.descriptors_by_type.race.name == "Dwarf" and profile.mod.allow_build.wilder_stone_warden and "allow" or "disallow" end,
 		},
 	},
 	copy = {
@@ -121,33 +122,37 @@ newBirthDescriptor{
 	type = "subclass",
 	name = "Stone Warden",
 	desc = {
-		"",
+		"Stone Wardens are dwarves trained in both the eldritch arts and the worship of nature.",
+		"While other races are stuck in their belief that arcane forces and natural forces are meant to oppose, dwarves have found a way to combine them in harmony.",
+		"Stone Wardens are armoured fighters, using a shield to channel many of their powers.",
 		"#GOLD#Stat modifiers:",
-		"#LIGHT_BLUE# * +3 Strength, +0 Dexterity, +0 Constitution",
-		"#LIGHT_BLUE# * +3 Magic, +3 Willpower, +0 Cunning",
+		"#LIGHT_BLUE# * +2 Strength, +0 Dexterity, +0 Constitution",
+		"#LIGHT_BLUE# * +4 Magic, +3 Willpower, +0 Cunning",
 	},
-	stats = { str=3, wil=3, mag=3, },
+	stats = { str=2, wil=3, mag=4, },
 	talents_types = {
 		["wild-gift/call"]={true, 0.2},
-		["wild-gift/stone-mastery"]={true, 0.3},
-		["spell/earth"]={true, 0.3},
-		["spell/stone"]={true, 0.3},
-		["cunning/survival"]={false, 0},
-		["technique/shield-offense"]={true, 0.1},
-		["technique/combat-techniques-passive"]={true, 0},
+		["wild-gift/earthen-stone"]={true, 0.3},
+		["wild-gift/earthen-vines"]={true, 0.3},
+		["spell/arcane-shield"]={true, 0.3},
+		["spell/earth"]={true, 0.2},
+		["spell/stone"]={false, 0.2},
+		["cunning/survival"]={true, 0},
 		["technique/combat-training"]={true, 0},
 	},
 	talents = {
-		[ActorTalents.T_ICE_CLAW] = 1,
-		[ActorTalents.T_MEDITATION] = 1,
+		[ActorTalents.T_STONE_VINES] = 1,
+		[ActorTalents.T_STONESHIELD] = 1,
+		[ActorTalents.T_ELDRITCH_BLOW] = 1,
+		[ActorTalents.T_ARMOUR_TRAINING] = 3,
 		[ActorTalents.T_WEAPONS_MASTERY] = 1,
-		[ActorTalents.T_WEAPON_COMBAT] = 1,
 	},
 	copy = {
 		max_life = 110,
 		resolvers.equip{ id=true,
-			{type="weapon", subtype="battleaxe", name="iron battleaxe", autoreq=true, ego_chance=-1000},
-			{type="armor", subtype="light", name="rough leather armour", autoreq=true, ego_chance=-1000}
+			{type="weapon", subtype="mace", name="iron mace", autoreq=true, ego_chance=-1000, ego_chance=-1000},
+			{type="armor", subtype="shield", name="iron shield", autoreq=true, ego_chance=-1000, ego_chance=-1000},
+			{type="armor", subtype="heavy", name="iron mail armour", autoreq=true, ego_chance=-1000, ego_chance=-1000}
 		},
 	},
 	copy_add = {
diff --git a/game/modules/tome/data/birth/worlds.lua b/game/modules/tome/data/birth/worlds.lua
index 8f4bdaa2350fe9d707b86a4d519096ead27c0623..3645fb802825be512b4202c899b186e2e52c3336 100644
--- a/game/modules/tome/data/birth/worlds.lua
+++ b/game/modules/tome/data/birth/worlds.lua
@@ -19,6 +19,7 @@
 
 local default_eyal_descriptors = function(add)
 	local base = {
+
 	race =
 	{
 		__ALL__ = "disallow",
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index cda4b8af8c872de95978cbb3bb274da0028fe8c1..183f504cf336d6427437ca3cc145b5ff4375895e 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -88,6 +88,10 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr)
 			dam = t.css_on_damage(target, t, type, dam)
 		end
 
+		if type ~= DamageType.PHYSICAL and target.knowTalent and target:knowTalent(target.T_STONE_FORTRESS) and target:hasEffect(target.EFF_DWARVEN_RESILIENCE) then
+			dam = math.max(0, dam - target:combatArmor() * (50 + target:getTalentLevel(target.T_STONE_FORTRESS) * 10) / 100)
+		end
+
 		-- Reduce damage with resistance
 		if target.resists then
 			local pen = 0
diff --git a/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua
index caf07ac2c2afd48908a096d861aa0ef8a215d557..b81230d8d3c44a9ce201d37e9fb9e75aff6cc7f6 100644
--- a/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua
+++ b/game/modules/tome/data/general/encounters/maj-eyal-npcs.lua
@@ -92,7 +92,7 @@ newEntity{
 		type="ambush",
 		width=14,
 		height=14,
-		nb={2, 4},
+		nb={2, 3},
 		filters={{special_rarity="humanoid_random_boss", random_boss={
 			nb_classes=1,
 			rank=3,
diff --git a/game/modules/tome/data/general/npcs/aquatic_critter.lua b/game/modules/tome/data/general/npcs/aquatic_critter.lua
index a17278976cae7912222bcb6b0035a25043f797dc..31a59b67e4213e82308a2e226423db29f1fafe15 100644
--- a/game/modules/tome/data/general/npcs/aquatic_critter.lua
+++ b/game/modules/tome/data/general/npcs/aquatic_critter.lua
@@ -75,7 +75,7 @@ newEntity{ base = "BASE_NPC_AQUATIC_CRITTER",
 
 newEntity{ base = "BASE_NPC_AQUATIC_CRITTER",
 	name = "ancient dragon turtle", color=colors.DARK_SEA_GREEN,
-	desc = "A snake-like being, radiating electricity.",
+	desc = "A huge, elongated sea-green reptile, it looks old and impenetrable.",
 	level_range = {20, nil}, exp_worth = 1,
 	rarity = 10,
 	rank = 3,
diff --git a/game/modules/tome/data/general/npcs/bone-giant.lua b/game/modules/tome/data/general/npcs/bone-giant.lua
index 5c4a0cd4f784aacbbcd8270542f60b6ee7001abd..70e1d3057630b3c7790e893cc8e5976e677267f8 100644
--- a/game/modules/tome/data/general/npcs/bone-giant.lua
+++ b/game/modules/tome/data/general/npcs/bone-giant.lua
@@ -62,6 +62,7 @@ newEntity{ base = "BASE_NPC_BONE_GIANT",
 	name = "bone giant", color=colors.WHITE,
 	desc = [[A towering creature, made from the bones of dozens of dead bodies. It is covered by an unholy aura.]],
 	level_range = {25, nil}, exp_worth = 1,
+	resolvers.nice_tile{image="invis.png", add_mos = {{image="npc/undead_giant_bone_giant.png", display_h=2, display_y=-1}}},
 	rarity = 1,
 	max_life = resolvers.rngavg(100,120),
 	combat_armor = 20, combat_def = 0,
diff --git a/game/modules/tome/data/general/npcs/construct.lua b/game/modules/tome/data/general/npcs/construct.lua
index 6e31bff62a3eabab170c41001da018e82ed3ff7b..028f20f809d05f50027c4909e381d69d6d0cf422 100644
--- a/game/modules/tome/data/general/npcs/construct.lua
+++ b/game/modules/tome/data/general/npcs/construct.lua
@@ -54,7 +54,7 @@ newEntity{
 }
 
 newEntity{ base = "BASE_NPC_CONSTRUCT",
-	name = "broken golem", color=colors.LIGHT_UMBER, image = "npc/summoner_golem.png",
+	name = "broken golem", color=colors.LIGHT_UMBER,
 	desc = [[This golem is badly damaged.]],
 	level_range = {6, nil}, exp_worth = 1,
 	rarity = 1,
diff --git a/game/modules/tome/data/general/npcs/humanoid_random_boss.lua b/game/modules/tome/data/general/npcs/humanoid_random_boss.lua
index f35e502e3f9e899897d6f2fa0543e974a0c6e462..ff56f688f36a2326274f39e48bd3e708a71a2f7f 100644
--- a/game/modules/tome/data/general/npcs/humanoid_random_boss.lua
+++ b/game/modules/tome/data/general/npcs/humanoid_random_boss.lua
@@ -54,7 +54,7 @@ newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS",
 }
 
 newEntity{ base = "BASE_NPC_HUMANOID_RANDOM_BOSS",
-	name = "halflint", subtype = "halfling", color=colors.BLUE,
+	name = "halfling", subtype = "halfling", color=colors.BLUE,
 	humanoid_random_boss = 1,
 	resolvers.racial(),
 }
diff --git a/game/modules/tome/data/gfx/particles/stonevine.lua b/game/modules/tome/data/gfx/particles/stonevine.lua
new file mode 100644
index 0000000000000000000000000000000000000000..56e42c176af34fe1736e8e4109df46867f4e164c
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/stonevine.lua
@@ -0,0 +1,81 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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
+
+-- Make the 2 main forks
+local nb = 0
+local forks = {{}, {}}
+local m1 = forks[1]
+local m2 = forks[2]
+local tiles = math.ceil(math.sqrt(tx*tx+ty*ty))
+local tx = tx * engine.Map.tile_w
+local ty = ty * engine.Map.tile_h
+local breakdir = math.rad(rng.range(-8, 8))
+m1.bx = 0
+m1.by = 0
+m1.thick = 5
+m1.dir = math.atan2(ty, tx) + breakdir
+m1.size = math.sqrt(tx*tx+ty*ty) / 2
+
+m2.bx = m1.size * math.cos(m1.dir)
+m2.by = m1.size * math.sin(m1.dir)
+m2.thick = 5
+m2.dir = math.atan2(ty, tx) - breakdir
+m2.size = math.sqrt(tx*tx+ty*ty) / 2
+
+-- Add more forks
+for i = 1, math.min(math.max(3, m1.size / 5), 20) do
+	local m = rng.percent(50) and forks[1] or forks[2]
+	if rng.percent(60) then m = rng.table(forks) end
+	local f = {}
+	f.thick = 2
+	f.dir = m.dir + math.rad(rng.range(-30,30))
+	f.size = rng.range(6, 25)
+	local br = rng.range(1, m.size)
+	f.bx = br * math.cos(m.dir) + m.bx
+	f.by = br * math.sin(m.dir) + m.by
+	forks[#forks+1] = f
+end
+
+-- Populate the lightning based on the forks
+return { generator = function()
+	local f = rng.table(forks)
+	local a = f.dir
+	local rad = rng.range(-3,3)
+	local ra = math.rad(rad)
+	local r = rng.range(1, f.size)
+
+	return {
+		life = life or 4,
+		size = f.thick, sizev = 0, sizea = 0,
+
+		x = r * math.cos(a) + 3 * math.cos(ra) + f.bx, xv = 0, xa = 0,
+		y = r * math.sin(a) + 3 * math.sin(ra) + f.by, yv = 0, ya = 0,
+		dir = 0, dirv = 0, dira = 0,
+		vel = 0, velv = 0, vela = 0,
+
+		r = 0xD7/255, rv = 0, ra = 0,
+		g = 0x8E/255, gv = 0, ga = 0,
+		b = 0x45/255, bv = 0, ba = 0,
+		a = rng.range(230, 255)/255, av = 0, aa = 0,
+	}
+end, },
+function(self)
+	if nb < 4 then self.ps:emit(20*tiles) nb = nb + 1 end
+end,
+4*(20)*tiles
diff --git a/game/modules/tome/data/gfx/particles/stonevine_static.lua b/game/modules/tome/data/gfx/particles/stonevine_static.lua
new file mode 100644
index 0000000000000000000000000000000000000000..0d865c3cae2ebffa95dcd22af05e1b50d1f39828
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/stonevine_static.lua
@@ -0,0 +1,46 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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
+
+base_size = 32
+
+return { generator = function()
+	local ad = rng.range(0, 360)
+	local a = math.rad(ad)
+	local dir = math.rad(ad)
+	local r = rng.range(8, 18)
+
+	return {
+		life = 10,
+		size = 1, sizev = 0.3, sizea = -0.01,
+
+		x = r * math.cos(a), xv = 0, xa = 0,
+		y = r * math.sin(a), yv = 0, ya = 0,
+		dir = 0, dirv = 0, dira = 0,
+		vel = 0, velv = 0, vela = 0,
+
+		r = 0xD7/255, rv = 0, ra = 0,
+		g = 0x8E/255, gv = 0, ga = 0,
+		b = 0x45/255, bv = 0, ba = 0,
+		a = rng.range(100, 220)/255,	av = 0.05, aa = 0,
+	}
+end, },
+function(self)
+	self.ps:emit(2)
+end,
+10
diff --git a/game/modules/tome/data/gfx/shockbolt/invis.png b/game/modules/tome/data/gfx/shockbolt/invis.png
new file mode 100644
index 0000000000000000000000000000000000000000..4d828ca986e40aeb43a1fa001bfd876541370d63
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/invis.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/animal_bird_phoenix.png b/game/modules/tome/data/gfx/shockbolt/npc/animal_bird_phoenix.png
new file mode 100644
index 0000000000000000000000000000000000000000..a1f3e334eb48fa612ea5654571e127b4588208a9
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/animal_bird_phoenix.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/construct_golem_broken_golem.png b/game/modules/tome/data/gfx/shockbolt/npc/construct_golem_broken_golem.png
new file mode 100644
index 0000000000000000000000000000000000000000..12fe6e2a9be025e89fc3af7582f169c58bad1038
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/construct_golem_broken_golem.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/dragon_cold_cold_drake_hatchling.png b/game/modules/tome/data/gfx/shockbolt/npc/dragon_cold_cold_drake_hatchling.png
new file mode 100644
index 0000000000000000000000000000000000000000..d774be02a586201a4d3b394e2a3b5800c50760e1
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/dragon_cold_cold_drake_hatchling.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_elven_mage.png b/game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_elven_mage.png
new file mode 100644
index 0000000000000000000000000000000000000000..99f2cbc0d77dace46907ad24e45b4b149c769636
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/humanoid_shalore_elven_mage.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/undead_giant_bone_giant.png b/game/modules/tome/data/gfx/shockbolt/npc/undead_giant_bone_giant.png
new file mode 100644
index 0000000000000000000000000000000000000000..4063d8a76f014e20db48c06f3f8cedecf2fc503d
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/undead_giant_bone_giant.png differ
diff --git a/game/modules/tome/data/quests/escort-duty.lua b/game/modules/tome/data/quests/escort-duty.lua
index 775eab120965357f7f235c82ab5aa1e3c90de36e..bf9b3888ba9c26391cf1543a1a7337b59796db60 100644
--- a/game/modules/tome/data/quests/escort-duty.lua
+++ b/game/modules/tome/data/quests/escort-duty.lua
@@ -47,7 +47,7 @@ local possible_types = {
 	{ name="lost warrior", random="male", chance=70,
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
-			type = "humanoid", subtype = "human",
+			type = "humanoid", subtype = "human", image = "player/higher_male.png",
 			display = "@", color=colors.UMBER,
 			name = "%s, the lost warrior",
 			desc = [[He looks tired and wounded.]],
@@ -75,7 +75,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I will not be able to continue the road alone. Would you help me?]],
 		actor = {
 			name = "%s, the injured seer",
-			type = "humanoid", subtype = "elf", female=true,
+			type = "humanoid", subtype = "elf", female=true, image = "player/halfling_female.png",
 			display = "@", color=colors.LIGHT_BLUE,
 			desc = [[She looks tired and wounded.]],
 			autolevel = "caster",
@@ -101,7 +101,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
 			name = "%s, the repented thief",
-			type = "humanoid", subtype = "halfling",
+			type = "humanoid", subtype = "halfling", image = "player/cornac_male.png",
 			display = "@", color=colors.BLUE,
 			desc = [[He looks tired and wounded.]],
 			autolevel = "rogue",
@@ -128,7 +128,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
 			name = "%s, the lone alchemist",
-			type = "humanoid", subtype = "human",
+			type = "humanoid", subtype = "human", image = "player/shalore_male.png",
 			display = "@", color=colors.AQUAMARINE,
 			desc = [[He looks tired and wounded.]],
 			autolevel = "rogue",
@@ -154,7 +154,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
 			name = "%s, the lost sun paladin",
-			type = "humanoid", subtype = "human", female=true,
+			type = "humanoid", subtype = "human", female=true, image = "player/higher_female.png",
 			display = "@", color=colors.GOLD,
 			desc = [[She looks tired and wounded.]],
 			autolevel = "warriormage",
@@ -181,7 +181,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
 			name = "%s, the lost anorithil",
-			type = "humanoid", subtype = "human", female=true,
+			type = "humanoid", subtype = "human", female=true, image = "player/higher_female.png",
 			display = "@", color=colors.YELLOW,
 			desc = [[She looks tired and wounded.]],
 			autolevel = "caster",
@@ -208,7 +208,7 @@ local possible_types = {
 		text = [[Please help me! I am afraid I lost myself in this place. I know there is a recall portal left around here by a friend, but I have fought too many battles, and I fear I will not make it. Would you help me?]],
 		actor = {
 			name = "%s, the worried loremaster",
-			type = "humanoid", subtype = "human", female=true,
+			type = "humanoid", subtype = "human", female=true, image = "player/thalore_female.png",
 			display = "@", color=colors.LIGHT_GREEN,
 			desc = [[She looks tired and wounded.]],
 			autolevel = "wildcaster",
diff --git a/game/modules/tome/data/talents/gifts/earthen-power.lua b/game/modules/tome/data/talents/gifts/earthen-power.lua
new file mode 100644
index 0000000000000000000000000000000000000000..bab1522f2951eaa808954424dcab053d501605aa
--- /dev/null
+++ b/game/modules/tome/data/talents/gifts/earthen-power.lua
@@ -0,0 +1,127 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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 = "Stoneshield",
+	type = {"wild-gift/earthen-power", 1},
+	mode = "passive",
+	require = gifts_req1,
+	points = 5,
+	getValues = function(self, t)
+		return
+			(5 + self:getTalentLevel(t) * 2) / 100,
+			5 + self:getTalentLevel(t),
+			(5 + self:getTalentLevel(t) * 1.7) / 100,
+			4 + self:getTalentLevel(t)
+	end,
+	info = function(self, t)
+		local m, mm, e, em = t.getValues(self, t)
+		return ([[Each time you get hit you regenerate %d%% of the damage dealt as mana (up to a maximun of %0.2f) and %d%% as equilibrium (up to %0.2f).
+		Also makes all your melee attack also do a shield bash.]]):format(100 * m, mm, 100 * e, em)
+	end,
+}
+
+newTalent{
+	name = "Stone Fortress",
+	type = {"wild-gift/earthen-power", 2},
+	require = gifts_req2,
+	points = 5,
+	mode = "passive",
+	info = function(self, t)
+		return ([[When you use your Resilience of the Dwarves racial power your skin becomes so thick that it even absorbs damage from non physical attacks.
+		Non physical damages are reduced by %d%% of your armour value (ignoring hardiness).]]):
+		format(50 + self:getTalentLevel(t) * 10)
+	end,
+}
+
+newTalent{
+	name = "Shards",
+	type = {"wild-gift/earthen-power", 3},
+	require = gifts_req3,
+	points = 5,
+	equilibrium = 4,
+	cooldown = 30,
+	tactical = { ATTACK = 2 },
+	range = 10,
+	direct_hit = true,
+	proj_speed = 8,
+	action = function(self, t)
+		local tg = {type="bolt", range=self:getTalentRange(t), display={particle="bolt_arcane"}}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		self:projectile(tg, x, y, DamageType.SLIME, self:combatTalentStatDamage(t, "dex", 30, 290), {type="slime"})
+		game:playSoundNear(self, "talents/stone")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Spit slime at your target doing %0.2f nature damage and slowing it down by 30%% for 3 turns.
+		The damage will increase with the Dexterity stat]]):format(damDesc(self, DamageType.NATURE, self:combatTalentStatDamage(t, "dex", 30, 290)))
+	end,
+}
+
+newTalent{
+	name = "Eldritch Stone",
+	type = {"wild-gift/earthen-power", 4},
+	require = gifts_req4,
+	points = 5,
+	equilibrium = 5,
+	cooldown = 20,
+	tactical = { CLOSEIN = 2 },
+	requires_target = true,
+	range = function(self, t)
+		return 5 + self:getTalentLevel(t)
+	end,
+	radius = function(self, t)
+		return util.bound(4 - self:getTalentLevel(t) / 2, 1, 4)
+	end,
+	getDuration = function(self, t)
+		return util.bound(7 - self:getTalentLevel(t) / 2, 2, 7)
+	end,
+	action = function(self, t)
+		local range = self:getTalentRange(t)
+		local radius = self:getTalentRadius(t)
+		local tg = {type="ball", nolock=true, pass_terrain=true, nowarning=true, range=range, radius=radius, requires_knowledge=false}
+		local x, y = self:getTarget(tg)
+		if not x then return nil end
+		-- Target code does not restrict the self coordinates to the range, it lets the project function do it
+		-- but we cant ...
+		local _ _, x, y = self:canProject(tg, x, y)
+		game.level.map:particleEmitter(self.x, self.y, 1, "slime")
+		self:teleportRandom(x, y, self:getTalentRadius(t))
+		game.level.map:particleEmitter(self.x, self.y, 1, "slime")
+
+		local duration = t.getDuration(self, t)
+
+		for tid, lev in pairs(self.talents) do
+			local t = self:getTalentFromId(tid)
+			if t.mode == "activated" and not t.innate then
+				self.talents_cd[t.id] = duration
+			end
+		end
+		game:playSoundNear(self, "talents/stone")
+		return true
+	end,
+	info = function(self, t)
+		local range = self:getTalentRange(t)
+		local radius = self:getTalentRadius(t)
+		local duration = t.getDuration(self, t)
+		return ([[You extend slimy roots into the ground, follow them, and re-appear somewhere else in a range of %d with error margin of %d.
+		The process is quite a strain on your body and all your talents will be put on cooldown for %d turns.]]):format(range, radius, duration)
+	end,
+}
diff --git a/game/modules/tome/data/talents/gifts/earthen-vines.lua b/game/modules/tome/data/talents/gifts/earthen-vines.lua
new file mode 100644
index 0000000000000000000000000000000000000000..b5dd3df410504c082a7093224bc040a0e29380e4
--- /dev/null
+++ b/game/modules/tome/data/talents/gifts/earthen-vines.lua
@@ -0,0 +1,167 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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 = "Stone Vines",
+	type = {"wild-gift/earthen-vines", 1},
+	require = gifts_req1,
+	points = 5,
+	mode = "sustained",
+	sustain_equilibrium = 15,
+	cooldown = 30,
+	tactical = { ATTACK = 2, BUFF = 2, DISABLE = 2 },
+	radius = function(self, t) return 4 + math.ceil(self:getTalentLevel(t) / 2) end,
+	getValues = function(self, t) return 4 + self:getTalentLevelRaw(t), self:combatTalentStatDamage(t, "wil", 3, 50) end,
+	do_vines = function(self, t)
+		local p = self:isTalentActive(t.id)
+		local rad = self:getTalentRadius(t)
+
+		local tgts = {}
+		local grids = core.fov.circle_grids(self.x, self.y, rad, true)
+		for x, yy in pairs(grids) do for y, _ in pairs(grids[x]) do
+			local a = game.level.map(x, y, Map.ACTOR)
+			if a and self:reactionToward(a) < 0 and not a:hasEffect(a.EFF_STONE_VINE) then
+				tgts[#tgts+1] = a
+			end
+		end end
+		if #tgts <= 0 then return end
+
+		-- Randomly take targets
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local a, id = rng.table(tgts)
+		local hit, chance = a:checkHit(self:combatTalentStatDamage(t, "wil", 5, 110), a:combatPhysicalResist(), 0, 95, 5)
+		if a:canBe("pin") and hit then
+			local turns, dam = t.getValues(self, t)
+			a:setEffect(a.EFF_STONE_VINE, turns, {dam=dam, src=self, free=rad*2, free_chance=100-chance})
+			game.level.map:particleEmitter(self.x, self.y, math.max(math.abs(a.x-self.x), math.abs(a.y-self.y)), "stonevine", {tx=a.x-self.x, ty=a.y-self.y})
+			game:playSoundNear(self, "talents/stone")
+		end
+	end,
+	activate = function(self, t)
+		return {
+			movid = self:addTemporaryValue("movement_speed", -0.5),
+			particle = self:addParticles(Particles.new("stonevine_static", 1, {})),
+		}
+	end,
+	deactivate = function(self, t, p)
+		self:removeTemporaryValue("movement_speed", p.movid)
+		self:removeParticles(p.particle)
+		return true
+	end,
+	info = function(self, t)
+		local rad = self:getTalentRadius(t)
+		local turns, dam = t.getValues(self, t)
+		return ([[Living stone vines extend from your feet, each turn the vines will randomly target a creature in a radius of %d.
+		Affected creatures are pinned to the ground and take %0.2f physical damage for %d turns.
+		Targets will be free from the vines if they are at least %d grids away from you.
+		While earthen vines are active your movement speed is reduced by 50%%.
+		Each turn a creature entangled by the vines will have a chance to break free.
+		The damage will increase with Willpower stats.]]):
+		format(rad, damDesc(self, DamageType.PHYSICAL, dam), turns, rad*2)
+	end,
+}
+
+newTalent{
+	name = "Eldritch Vines",
+	type = {"wild-gift/earthen-vines", 2},
+	require = gifts_req2,
+	points = 5,
+	mode = "passive",
+	info = function(self, t)
+		return ([[Each time a vine deal damage to a creature it will restore %0.2f equilibrium and %0.2f mana.]])
+		:format(self:getTalentLevel(t) / 4, self:getTalentLevel(t) / 3)
+	end,
+}
+
+newTalent{
+	name = "Rockwalk",
+	type = {"wild-gift/earthen-vines", 3},
+	require = gifts_req3,
+	points = 5,
+	equilibrium = 15,
+	cooldown = 10,
+	requires_target = true,
+	range = 20,
+	tactical = { HEAL = 2, CLONEIN = 2 },
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t)}
+		local x, y, target = self:getTarget(tg)
+		if not x or not y or not target then return nil end
+		if not target:hasEffect(target.EFF_STONE_VINE) then return nil end
+
+		self:heal(100 + self:combatTalentStatDamage(t, "wil", 40, 630))
+		local tx, ty = util.findFreeGrid(x, y, 2, true, {[Map.ACTOR]=true})
+		if tx and ty then
+			local ox, oy = self.x, self.y
+			self:move(tx, ty, true)
+			if config.settings.tome.smooth_move > 0 then
+				self:resetMoveAnim()
+				self:setMoveAnim(ox, oy, 8, 5)
+			end
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		return ([[Merge with a stone vine, travelling alongside it to reappear near an entangled creature.
+		Merging with the stone is beneficial for you, healing %0.2f life.
+		Healing will increase with Willpower.]])
+		:format(100 + self:combatTalentStatDamage(t, "wil", 40, 630))
+	end,
+}
+
+newTalent{
+	name = "Rockswallow",
+	type = {"wild-gift/earthen-vines", 4},
+	require = gifts_req4,
+	points = 5,
+	equilibrium = 15,
+	cooldown = 10,
+	requires_target = true,
+	range = 20,
+	tactical = { ATTACK = 2, CLONEIN = 2 },
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t)}
+		local x, y, target = self:getTarget(tg)
+		if not x or not y or not target then return nil end
+		if not target:hasEffect(target.EFF_STONE_VINE) then return nil end
+
+		DamageType:get(DamageType.PHYSICAL).projector(self, target.x, target.y, DamageType.PHYSICAL, 80 + self:combatTalentStatDamage(t, "wil", 40, 330))
+
+		if target.dead then return end
+
+		local tx, ty = util.findFreeGrid(self.x, self.y, 2, true, {[Map.ACTOR]=true})
+		if tx and ty then
+			local ox, oy = target.x, target.y
+			target:move(tx, ty, true)
+			if config.settings.tome.smooth_move > 0 then
+				target:resetMoveAnim()
+				target:setMoveAnim(ox, oy, 8, 5)
+			end
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		return ([[Merge your target with a stone vine, forcing it to travel alongside it to reappear near you.
+		Merging with the stone is detrimental for the target, dealing %0.2f physical damage.
+		Damage will increase with Willpower.]])
+		:format(80 + self:combatTalentStatDamage(t, "wil", 40, 330))
+	end,
+}
diff --git a/game/modules/tome/data/talents/gifts/gifts.lua b/game/modules/tome/data/talents/gifts/gifts.lua
index e836daf5ce2d891007733812ab5a9f9a74e6f944..f357049946bcf9a0b2c5af614ee04fff5f5480c0 100644
--- a/game/modules/tome/data/talents/gifts/gifts.lua
+++ b/game/modules/tome/data/talents/gifts/gifts.lua
@@ -29,6 +29,8 @@ newTalentType{ allow_random=true, type="wild-gift/sand-drake", name = "sand drak
 newTalentType{ allow_random=true, type="wild-gift/fire-drake", name = "fire drake aspect", description = "Take on the defining aspects of a Fire Drake." }
 newTalentType{ allow_random=true, type="wild-gift/cold-drake", name = "cold drake aspect", description = "Take on the defining aspects of a Cold Drake." }
 newTalentType{ allow_random=true, type="wild-gift/storm-drake", name = "storm drake aspect", description = "Take on the defining aspects of a Storm Drake." }
+newTalentType{ allow_random=true, type="wild-gift/earthen-power", name = "earthen power", description = "Dwarves have learned to imbue their shields with the power of stone itself." }
+newTalentType{ allow_random=true, type="wild-gift/earthen-vines", name = "earthen vines", description = "Control the stone itself and bring it alive in the form of dreadful vines." }
 
 -- Generic requires for gifts based on talent level
 gifts_req1 = {
@@ -131,3 +133,6 @@ load("/data/talents/gifts/summon-melee.lua")
 load("/data/talents/gifts/summon-distance.lua")
 load("/data/talents/gifts/summon-utility.lua")
 load("/data/talents/gifts/summon-augmentation.lua")
+
+load("/data/talents/gifts/earthen-power.lua")
+load("/data/talents/gifts/earthen-vines.lua")
diff --git a/game/modules/tome/data/talents/spells/arcane-shield.lua b/game/modules/tome/data/talents/spells/arcane-shield.lua
new file mode 100644
index 0000000000000000000000000000000000000000..410cf2edd2e18772dbc0274cf11afc313897bfea
--- /dev/null
+++ b/game/modules/tome/data/talents/spells/arcane-shield.lua
@@ -0,0 +1,161 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009, 2010, 2011 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 = "Eldritch Blow",
+	type = {"spell/arcane-shield", 1},
+	require = spells_req1,
+	points = 5,
+	equilibrium = 3,
+	mana = 10,
+	cooldown = 6,
+	range = 1,
+	tactical = { ATTACK = 2, DISABLE = 2 },
+	requires_target = true,
+	pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldricth Blow without a shield!") end return false end return true end,
+	action = function(self, t)
+		local shield = self:hasShield()
+
+		local tg = {type="hit", range=self:getTalentRange(t)}
+		local x, y, target = self:getTarget(tg)
+		if not x or not y or not target then return nil end
+		if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
+
+		-- First attack with both weapon & shield (since we have the Stoneshield talent)
+		local hit = self:attackTarget(target, DamageType.ARCANE, self:combatTalentWeaponDamage(t, 0.6, (100 + self:combatTalentSpellDamage(t, 50, 300)) / 100), true)
+
+		-- Try to stun !
+		if hit then
+			if target:checkHit(self:combatAttackStr(shield.special_combat), target:combatSpellResist(), 0, 95, 5) and target:canBe("stun") then
+				target:setEffect(target.EFF_STUNNED, 2 + math.floor(self:getTalentLevel(t) / 2), {})
+			else
+				game.logSeen(target, "%s resists the stun!", target.name:capitalize())
+			end
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		return ([[Channel eldritch forces in your attack, hitting the target with your weapon and shield doing %d%% arcane damage.
+		If the any of the attacks hit, the target is stunned for %d turns.
+		The stun is considered a magical attack and thus is resisted with spell save, not physical save.]])
+		:format(100 * self:combatTalentWeaponDamage(t, 0.6, (100 + self:combatTalentSpellDamage(t, 50, 300)) / 100), 2 + math.floor(self:getTalentLevel(t) / 2))
+	end,
+}
+
+newTalent{
+	name = "Eldritch Infusion",
+	type = {"spell/arcane-shield", 2},
+	require = spells_req2,
+	points = 5,
+	mode = "sustained",
+	sustain_equilibrium = 15,
+	sustain_mana = 15,
+	cooldown = 30,
+	tactical = { ATTACK = 3, BUFF = 2 },
+	activate = function(self, t)
+		local power = 5 * self:getTalentLevel(t) + (self:getWil() + self:getMag()) / 5
+		return {
+			onhit = self:addTemporaryValue("melee_project", {[DamageType.ARCANE]=power}),
+		}
+	end,
+	deactivate = function(self, t, p)
+		self:removeTemporaryValue("melee_project", p.onhit)
+		return true
+	end,
+	info = function(self, t)
+		return ([[Imbues your weapon with arcane power, dealing %0.2f arcane damage with each attacks.
+		The damage will increase with Willpower and Magic stats.]]):format(damDesc(self, DamageType.ARCANE, 5 * self:getTalentLevel(t) + (self:getWil() + self:getMag()) / 5))
+	end,
+}
+
+newTalent{
+	name = "Eldritch Fury",
+	type = {"spell/arcane-shield", 3},
+	require = spells_req3,
+	points = 5,
+	equilibrium = 20,
+	mana = 30,
+	cooldown = 12,
+	requires_target = true,
+	tactical = { ATTACK = 3, DISABLE = 1 },
+	range = 1,
+	pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldricth Fury without a shield!") end return false end return true end,
+	action = function(self, t)
+		local shield = self:hasShield()
+
+		local tg = {type="hit", range=self:getTalentRange(t)}
+		local x, y, target = self:getTarget(tg)
+		if not x or not y or not target then return nil end
+		if math.floor(core.fov.distance(self.x, self.y, x, y)) > 1 then return nil end
+
+		-- First attack with both weapon & shield (since we have the Stoneshield talent)
+		local hit1 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
+		local hit2 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
+		local hit3 = self:attackTarget(target, DamageType.NATURE, self:combatTalentWeaponDamage(t, 0.6, 1.6), true)
+
+		-- Try to stun !
+		if hit then
+			if target:checkHit(self:combatAttackStr(shield.special_combat), target:combatSpellResist(), 0, 95, 5) and target:canBe("stun") then
+				target:setEffect(target.EFF_DAZED, 3 + math.floor(self:getTalentLevel(t)), {})
+			else
+				game.logSeen(target, "%s resists the dazing blows!", target.name:capitalize())
+			end
+		end
+
+		return true
+	end,
+	info = function(self, t)
+		return ([[Channel eldritch forces to speed up your attacks, hitting the target three times with your weapon and shield doing %d%% nature damage.
+		If the any of the attacks hit, the target is dazed for %d turns.
+		The daze is considered a magical attack and thus is resisted with spell save, not physical save.]])
+		:format(100 * self:combatTalentWeaponDamage(t, 0.6, 1.6), 3 + math.floor(self:getTalentLevel(t)))
+	end,
+}
+
+newTalent{
+	name = "Eldritch Slam",
+	type = {"spell/arcane-shield", 4},
+	require = spells_req4,
+	points = 5,
+	equilibrium = 10,
+	mana = 30,
+	cooldown = 20,
+	tactical = { ATTACKAREA = 3 },
+	requires_target = true,
+	range = 1,
+	radius = function(self, t) return 1 + self:getTalentLevelRaw(t) end,
+	pre_use = function(self, t, silent) local shield = self:hasShield() if not shield then if not silent then game.logPlayer(self, "You cannot use Eldritch Slam without a shield!") end return false end return true end,
+	action = function(self, t)
+		local shield = self:hasShield()
+
+		local tg = {type="ball", radius=self:getTalentRadius(t)}
+		self:project(tg, self.x, self.y, function(px, py)
+			local target = game.level.map(px, py, Map.ACTOR)
+			if not target or target == self then return end
+			self:attackTargetWith(target, shield.special_combat, nil, self:combatTalentWeaponDamage(t, 1.3, 2.6), true)
+		end)
+
+		return true
+	end,
+	info = function(self, t)
+		return ([[Slam your shield on the ground, doing %d%% damage in a radius of %d.]])
+		:format(100 * self:combatTalentWeaponDamage(t, 1.3, 2.6), self:getTalentRadius(t))
+	end,
+}
diff --git a/game/modules/tome/data/talents/spells/spells.lua b/game/modules/tome/data/talents/spells/spells.lua
index 352e5e0a1dbd460c930c602cc414bd423b787b9a..7c019bb2b35cfe923d0c5dfc25346ff54639716f 100644
--- a/game/modules/tome/data/talents/spells/spells.lua
+++ b/game/modules/tome/data/talents/spells/spells.lua
@@ -52,6 +52,9 @@ newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/st
 newTalentType{ type="golem/fighting", name = "fighting", description = "Golem melee capacity." }
 newTalentType{ type="golem/arcane", name = "arcane", description = "Golem arcane capacity." }
 
+-- Stone Warden spells
+newTalentType{ allow_random=true, no_silence=true, is_spell=true, type="spell/arcane-shield", name = "arcane shield", description = "Infuse arcane forces in your shield." }
+
 -- Generic requires for spells based on talent level
 spells_req1 = {
 	stat = { mag=function(level) return 12 + (level-1) * 2 end },
@@ -119,3 +122,5 @@ load("/data/talents/spells/staff-combat.lua")
 load("/data/talents/spells/fire-alchemy.lua")
 load("/data/talents/spells/stone-alchemy.lua")
 load("/data/talents/spells/golem.lua")
+
+load("/data/talents/spells/arcane-shield.lua")
diff --git a/game/modules/tome/data/timed_effects.lua b/game/modules/tome/data/timed_effects.lua
index 31bcf9ffc8c297c722ead5e6d432f4649b47d1e1..c0e8a73420c4ee3036fe3377d3086493262badba 100644
--- a/game/modules/tome/data/timed_effects.lua
+++ b/game/modules/tome/data/timed_effects.lua
@@ -435,7 +435,7 @@ newEffect{
 		eff.tmpid = self:addTemporaryValue("never_move", 1)
 	end,
 	on_timeout = function(self, eff)
-		if math.floor(core.fov.distance(self.x, self.y, eff.src.x, eff.src.y)) > 1 or eff.src.dead then
+		if math.floor(core.fov.distance(self.x, self.y, eff.src.x, eff.src.y)) > 1 or eff.src.dead or not game.level:hasEntity(eff.src) then
 			return true
 		end
 		self:suffocate(eff.power, eff.src)
@@ -2961,7 +2961,7 @@ newEffect{
 	on_gain = function(self, err) return "#Target# speeds up.", "+Quick" end,
 	on_lose = function(self, err) return "#Target# slows down.", "-Quick" end,
 	activate = function(self, eff)
-		eff.tmpid = self:addTemporaryValue("movement_speed", {mod=eff.power})
+		eff.tmpid = self:addTemporaryValue("movement_speed", eff.power)
 	end,
 	deactivate = function(self, eff)
 		self:removeTemporaryValue("movement_speed", eff.tmpid)
@@ -3841,3 +3841,42 @@ newEffect{
 		self:removeTemporaryValue("movement_speed", eff.tmpid)
 	end,
 }
+
+newEffect{
+	name = "STONE_VINE",
+	desc = "Stone Vine",
+	long_desc = function(self, eff) return ("A living stone vine holds the target on the ground and doing %0.2f physical damage per turn."):format(eff.dam) end,
+	type = "physical",
+	status = "detrimental",
+	parameters = { dam=10 },
+	on_gain = function(self, err) return "#Target# is grabbed by a stone vine.", "+Stone Vine" end,
+	on_lose = function(self, err) return "#Target# is free from the stone vine.", "-Stone Vine" end,
+	activate = function(self, eff)
+		eff.last_x = eff.src.x
+		eff.last_y = eff.src.y
+		eff.tmpid = self:addTemporaryValue("never_move", 1)
+		eff.particle = self:addParticles(Particles.new("stonevine_static", 1, {}))
+	end,
+	deactivate = function(self, eff)
+		self:removeTemporaryValue("never_move", eff.tmpid)
+		self:removeParticles(eff.particle)
+	end,
+	on_timeout = function(self, eff)
+		local severed = false
+		if math.floor(core.fov.distance(self.x, self.y, eff.src.x, eff.src.y)) >= eff.free or eff.src.dead or not game.level:hasEntity(eff.src) then severed = true end
+		if rng.percent(eff.free_chance) then severed = true end
+
+		if severed then
+			return true
+		else
+			DamageType:get(DamageType.PHYSICAL).projector(eff.src or self, self.x, self.y, DamageType.PHYSICAL, eff.dam)
+			if eff.src:knowTalent(eff.src.T_ELDRITCH_VINE) then
+				local l = eff.src:getTalentLevel(eff.src.T_ELDRITCH_VINE)
+				eff.src:incEquilibrium(-l / 4)
+				eff.src:incMana(l / 3)
+			end
+		end
+		eff.last_x = eff.src.x
+		eff.last_y = eff.src.y
+	end,
+}
diff --git a/game/modules/tome/data/zones/reknor-escape/npcs.lua b/game/modules/tome/data/zones/reknor-escape/npcs.lua
index 89f499ac3942366c0af41bdc6bc341c1c5f9519e..ad3e2062cb15b84e7139f1889d4ccffe5c9d5b56 100644
--- a/game/modules/tome/data/zones/reknor-escape/npcs.lua
+++ b/game/modules/tome/data/zones/reknor-escape/npcs.lua
@@ -71,7 +71,7 @@ newEntity{ define_as = "BROTOQ",
 -- Your ally
 newEntity{ define_as = "NORGAN",
 	type = "humanoid", subtype = "dwarf", unique = true,
-	name = "Norgan",
+	name = "Norgan", image = "player/dwarf_male.png",
 	display = "@", color=colors.UMBER,
 	faction = "iron-throne",
 	desc = [[Norgan and you are the sole survivors of the Reknor expedition, your duty is to make sure the news come back to the Iron Council.]],
diff --git a/game/modules/tome/data/zones/rhaloren-camp/npcs.lua b/game/modules/tome/data/zones/rhaloren-camp/npcs.lua
index 940fd9df397857788e16dc416543e13c8fbfe194..6006b6d000bb5196c7334857ff593723b0318e89 100644
--- a/game/modules/tome/data/zones/rhaloren-camp/npcs.lua
+++ b/game/modules/tome/data/zones/rhaloren-camp/npcs.lua
@@ -31,8 +31,8 @@ newEntity{ define_as = "INQUISITOR",
 	allow_infinite_dungeon = true,
 	type = "humanoid", subtype = "elf", unique = true,
 	name = "Rhaloren Inquisitor",
-	display = "p", color=colors.VIOLET,
-	desc = [[This tall elf rush to you, wielding both his greatsword and magical spells.]],
+	display = "p", color=colors.VIOLET, female = true,
+	desc = [[This tall elf rush to you, wielding both her greatsword and magical spells.]],
 	level_range = {7, nil}, exp_worth = 2,
 	max_life = 150, life_rating = 15, fixed_rating = true,
 	rank = 4,
diff --git a/game/modules/tome/resolvers.lua b/game/modules/tome/resolvers.lua
index 2a43b3a5c9b44d7e079c5103b9b2aaeb90f4b365..6fa26a75d061afc3a64980ac03d52408d96dffde 100644
--- a/game/modules/tome/resolvers.lua
+++ b/game/modules/tome/resolvers.lua
@@ -530,3 +530,13 @@ function resolvers.calc.emote_random(t, e)
 	end
 	return def
 end
+
+function resolvers.nice_tile(def)
+	return {__resolver="nice_tile", def}
+end
+function resolvers.calc.nice_tile(t, e)
+	if engine.Map.tiles.nicer_tiles then
+		table.merge(e, t[1])
+	end
+	return nil
+end
diff --git a/ideas/DLCs.ods b/ideas/DLCs.ods
index 540891dc99367fa124192ebb74eaf789cf4fe578..574c9bde3d447f47500279037b7f23c37e6de32b 100644
Binary files a/ideas/DLCs.ods and b/ideas/DLCs.ods differ
diff --git a/ideas/gifts.ods b/ideas/gifts.ods
index dda424ad2b63212f47bfb6f43c4b1d961a1039f1..2838eca7b6fa49da33d8a4deebb83c1fa40f5dd7 100644
Binary files a/ideas/gifts.ods and b/ideas/gifts.ods differ
diff --git a/ideas/spells.ods b/ideas/spells.ods
index 8e18a080a028a93e25d61023426bf6128bfafc6b..713e083834f0693c4e52e1381145b8a1e420842f 100644
Binary files a/ideas/spells.ods and b/ideas/spells.ods differ