diff --git a/game/engines/default/engine/PlayerProfile.lua b/game/engines/default/engine/PlayerProfile.lua
index 8813d3630ea1b58eb61e052e30e785287507dfd8..ab656b88daa28ff3e65d6e09bc51a9e25f0d990c 100644
--- a/game/engines/default/engine/PlayerProfile.lua
+++ b/game/engines/default/engine/PlayerProfile.lua
@@ -642,6 +642,15 @@ function _M:getCharball(id_profile, uuid)
 	return data
 end
 
+function _M:getDLCD(name, version, file)
+	if not self.auth then return end
+	local data = nil
+	core.profile.pushOrder(table.serialize{o="GetDLCD", name=name, version=version, file=file})
+	self:waitEvent("GetDLCD", function(e) data = e.data end, 30000)
+	if not data then return "" end
+	return zlib.decompress(data)
+end
+
 function _M:registerSaveCharball(module, uuid, data)
 	if not self.auth or not self.hash_valid then return end
 	core.profile.pushOrder(table.serialize{o="SaveCharball",
diff --git a/game/loader/init.lua b/game/loader/init.lua
index e8bff1270cf14a5d475c1003c57f22f9143ab3ed..a23a1b4db4248f340d8eccf5579d78d6c85b17aa 100644
--- a/game/loader/init.lua
+++ b/game/loader/init.lua
@@ -164,6 +164,15 @@ table.insert(package.loaders, 2, te4_loader)
 --table.insert(package.loaders, 2, function(name) return loadfile("/"..name:gsub("%.", "/")..".lua") end )
 --]]
 
+local dlcd_loader = function(name)
+	if not fs.exists("/"..name:gsub("%.", "/")..".stub") then return end
+	print("===DLCLOADER", "/"..name:gsub("%.", "/")..".stub")
+	local d = loadfile("/"..name:gsub("%.", "/")..".stub")()
+	local data = profile:getDLCD(d.name, d.version, name:gsub("%.", "/")..".lua")
+	return loadstring(data)
+end
+table.insert(package.loaders, 2, dlcd_loader)
+
 
 
 -- RUN engine RUN !!
diff --git a/game/modules/tome/data/birth/classes/wilder.lua b/game/modules/tome/data/birth/classes/wilder.lua
index eb5db03cdd7d31466879c41c452233637ab94abb..ac0dd2f3f8c946003e362152f76ccdb7116570b3 100644
--- a/game/modules/tome/data/birth/classes/wilder.lua
+++ b/game/modules/tome/data/birth/classes/wilder.lua
@@ -33,7 +33,6 @@ newBirthDescriptor{
 			__ALL__ = "disallow",
 			Summoner = "allow",
 			Wyrmic = "allow",
-			["Stone Warden"] = "allow",
 			Oozemancer = "allow",
 		},
 	},
@@ -141,51 +140,6 @@ newBirthDescriptor{
 	},
 }
 
-newBirthDescriptor{
-	type = "subclass",
-	name = "Stone Warden",
-	locked = function() return profile.mod.allow_build.wilder_stone_warden and true or "hide" end,
-	locked_desc = "",
-	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# * +2 Strength, +0 Dexterity, +0 Constitution",
-		"#LIGHT_BLUE# * +4 Magic, +3 Willpower, +0 Cunning",
-	},
-	power_source = {nature=true, arcane=true},
-	not_on_random_boss = true,
-	stats = { str=2, wil=3, mag=4, },
-	talents_types = {
-		["wild-gift/call"]={true, 0.2},
-		["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_STONE_VINES] = 1,
-		[ActorTalents.T_STONESHIELD] = 1,
-		[ActorTalents.T_ELDRITCH_BLOW] = 1,
-		[ActorTalents.T_ARMOUR_TRAINING] = 3,
-		[ActorTalents.T_WEAPONS_MASTERY] = 1,
-	},
-	copy = {
-		max_life = 110,
-		resolvers.equip{ id=true,
-			{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 = {
-		life_rating = 2,
-	},
-}
 
 newBirthDescriptor{
 	type = "subclass",
diff --git a/game/modules/tome/data/gfx/particles/stonevine.lua b/game/modules/tome/data/gfx/particles/stonevine.lua
deleted file mode 100644
index 6e8dafa6e99c26028273eb46d8fe08c879f27cd5..0000000000000000000000000000000000000000
--- a/game/modules/tome/data/gfx/particles/stonevine.lua
+++ /dev/null
@@ -1,81 +0,0 @@
--- ToME - Tales of Maj'Eyal
--- Copyright (C) 2009, 2010, 2011, 2012 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
deleted file mode 100644
index dd9e41a6e257524627dd469a26e9379d89c97749..0000000000000000000000000000000000000000
--- a/game/modules/tome/data/gfx/particles/stonevine_static.lua
+++ /dev/null
@@ -1,46 +0,0 @@
--- ToME - Tales of Maj'Eyal
--- Copyright (C) 2009, 2010, 2011, 2012 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/talents.lua b/game/modules/tome/data/talents.lua
index d33af734c0b00fb00a6fbd24715e573ba8e5f3aa..34f3fd27acb7ebb3a1f8d649526b638d7b144a96 100644
--- a/game/modules/tome/data/talents.lua
+++ b/game/modules/tome/data/talents.lua
@@ -58,6 +58,7 @@ damDesc = function(self, type, dam)
 end
 
 Talents.damDesc = damDesc
+Talents.main_env = getfenv(1)
 
 load("/data/talents/misc/misc.lua")
 load("/data/talents/techniques/techniques.lua")
diff --git a/game/modules/tome/data/talents/gifts/earthen-power.lua b/game/modules/tome/data/talents/gifts/earthen-power.lua
deleted file mode 100644
index 63332ad76383ea7425267d4544c04d58feb522c9..0000000000000000000000000000000000000000
--- a/game/modules/tome/data/talents/gifts/earthen-power.lua
+++ /dev/null
@@ -1,128 +0,0 @@
--- ToME - Tales of Maj'Eyal
--- Copyright (C) 2009, 2010, 2011, 2012 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,
-	is_teleport = true,
-	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
deleted file mode 100644
index 71d34884c1e8c8dd76c60bfeffbc6abcaca7f06f..0000000000000000000000000000000000000000
--- a/game/modules/tome/data/talents/gifts/earthen-vines.lua
+++ /dev/null
@@ -1,169 +0,0 @@
--- ToME - Tales of Maj'Eyal
--- Copyright (C) 2009, 2010, 2011, 2012 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 = { PHYSICAL = 2 }, BUFF = 2, DISABLE = { pin = 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, CLOSEIN = 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:attr("allow_on_heal", 1)
-		self:heal(100 + self:combatTalentStatDamage(t, "wil", 40, 630))
-		self:attr("allow_on_heal", -1)
-		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 = { PHYSICAL = 2 }, CLOSEIN = 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 8bf272c191d5930b347984e728bb38ccaef11eaa..e1cd2ec144e3dc3a9ba12990ca85f91cfcb077be 100644
--- a/game/modules/tome/data/talents/gifts/gifts.lua
+++ b/game/modules/tome/data/talents/gifts/gifts.lua
@@ -33,8 +33,6 @@ newTalentType{ allow_random=true, is_nature=true, type="wild-gift/fire-drake", n
 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/cold-drake", name = "cold drake aspect", description = "Take on the defining aspects of a Cold Drake." }
 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/storm-drake", name = "storm drake aspect", description = "Take on the defining aspects of a Storm Drake." }
 newTalentType{ allow_random=true, is_nature=true, type="wild-gift/mindstar-mastery", name = "mindstar mastery", generic = true, description = "Learn to channel your mental power through mindstars, forming powerful psionic blades." }
-newTalentType{ allow_random=true, is_nature=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, is_nature=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 = {
@@ -201,6 +199,3 @@ load("/data/talents/gifts/summon-augmentation.lua")
 load("/data/talents/gifts/summon-advanced.lua")
 
 load("/data/talents/gifts/mindstar-mastery.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
deleted file mode 100644
index 46ed99165bb861d239d6f5730e437e8dd60de410..0000000000000000000000000000000000000000
--- a/game/modules/tome/data/talents/spells/arcane-shield.lua
+++ /dev/null
@@ -1,162 +0,0 @@
--- ToME - Tales of Maj'Eyal
--- Copyright (C) 2009, 2010, 2011, 2012 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 = { ARCANE = 2 }, DISABLE = { stun = 2 } },
-	requires_target = true,
-	on_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 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:canBe("stun") then
-				target:setEffect(target.EFF_STUNNED, 2 + math.floor(self:getTalentLevel(t) / 2), {apply_power=self:combatPhysicalpower()})
-			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 = { NATURE = 3 }, DISABLE = { stun = 1 } },
-	range = 1,
-	on_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 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 hit1 or hit2 or hit3 then
-			if target:canBe("stun") then
-				target:setEffect(target.EFF_DAZED, 3 + math.floor(self:getTalentLevel(t)), {apply_power=self:combatPhysicalpower(), apply_save="combatSpellResist"})
-			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 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 = { PHYSICAL = 3 } },
-	requires_target = true,
-	range = 1,
-	radius = function(self, t) return 1 + self:getTalentLevelRaw(t) end,
-	on_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))
-		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 92bf3ead1615d9bf403b0820a98ba9305e676385..59d48c8868afc2dd97bb38f5cb901244a6156089 100644
--- a/game/modules/tome/data/talents/spells/spells.lua
+++ b/game/modules/tome/data/talents/spells/spells.lua
@@ -61,9 +61,6 @@ newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=tru
 newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=true, type="spell/necrosis", name = "necrosis", description = "Gain control over death, eventually turning into a lich." }
 newTalentType{ allow_random=true, no_silence=true, is_spell=true, mana_regen=true, type="spell/grave", name = "grave", description = "Use the rotting cold doom of the tomb to fell your foes." }
 
--- 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 },
@@ -242,8 +239,6 @@ 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")
-
 load("/data/talents/spells/necrotic-minions.lua")
 load("/data/talents/spells/advanced-necrotic-minions.lua")
 load("/data/talents/spells/nightfall.lua")
diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua
index f6e189d881a019020d20a3af09c3ca3ef101d5a0..6d4a827a71ff3acbfd88de61dc43e6a7bd8c53f4 100644
--- a/game/modules/tome/data/timed_effects/physical.lua
+++ b/game/modules/tome/data/timed_effects/physical.lua
@@ -1266,46 +1266,6 @@ newEffect{
 	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",
-	subtype = { earth=true, pin=true },
-	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 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_VINES) then
-				local l = eff.src:getTalentLevel(eff.src.T_ELDRITCH_VINES)
-				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,
-}
-
 newEffect{
 	name = "WATERS_OF_LIFE", image = "talents/waters_of_life.png",
 	desc = "Waters of Life",
diff --git a/game/profile-thread/Client.lua b/game/profile-thread/Client.lua
index d3c4342016e7d7245466443ed670bddaa3d4028c..f5f41c5b7adbc23bc5f3f718c93aa6cd7ba9c975 100644
--- a/game/profile-thread/Client.lua
+++ b/game/profile-thread/Client.lua
@@ -442,6 +442,19 @@ function _M:orderChatChannelList(o)
 	end
 end
 
+function _M:orderGetDLCD(o)
+	self:command("DLCD", o.name, o.version, o.file)
+	if self:read("200") then
+		local _, _, size = self.last_line:find("^([0-9]+)")
+		size = tonumber(size)
+		if not size or size < 1 then return end
+		local body = self:receive(size)
+		cprofile.pushEvent(string.format("e='GetDLCD' data=%q", body))
+	else
+		cprofile.pushEvent("e='GetDLCD' data=''")
+	end
+end
+
 function _M:orderPing(o)
 	local time = core.game.getTime()
 	self:command("PING")