diff --git a/game/engines/default/engine/Entity.lua b/game/engines/default/engine/Entity.lua
index 4400a211e552b6529c11c6c2a4a0018f0ae68f43..ffbbdd1dda1046800a0f45c3bfe5d81a7ee5bc7b 100644
--- a/game/engines/default/engine/Entity.lua
+++ b/game/engines/default/engine/Entity.lua
@@ -940,6 +940,19 @@ function _M:addTemporaryValue(prop, v, noupdate)
 			else
 				base[prop] = (base[prop] or 0) + v
 			end
+--			print("addTmpVal", base, prop, v, " :=: ", #t, id, method)
+		elseif type(v) == "function" then
+			-- Only last works on functions
+			if true or method == "last" then
+				base["__tlast_"..prop] = base["__tlast_"..prop] or {[-1] = base[prop]}
+				local b = base["__tlast_"..prop]
+				b[id] = v
+				b = table.listify(b)
+				table.sort(b, function(a, b) return a[1] > b[1] end)
+				base[prop] = b[1] and b[1][2]
+			else
+				base[prop] = (base[prop] or 0) + v
+			end
 --			print("addTmpVal", base, prop, v, " :=: ", #t, id, method)
 		else
 			error("unsupported temporary value type: "..type(v).." :=: "..tostring(v).." (on key "..tostring(prop)..")")
@@ -1041,6 +1054,22 @@ function _M:removeTemporaryValue(prop, id, noupdate)
 				if not base[prop] then util.send_error_backtrace("Error removing property "..tostring(prop).." with value "..tostring(v).." : base[prop] is nil") return end
 				base[prop] = base[prop] - v
 			end
+--			print("delTmpVal", prop, v, method)
+		elseif type(v) == "function" then
+			-- Only last works on functions
+			if true or method == "last" then
+				base["__tlast_"..prop] = base["__tlast_"..prop] or {}
+				local b = base["__tlast_"..prop]
+				b[id] = nil
+				b = table.listify(b)
+				table.sort(b, function(a, b) return a[1] > b[1] end)
+				base[prop] = b[1] and b[1][2]
+				if b[1] and b[1][1] == -1 then base["__tlast_"..prop][-1] = nil end
+				if not next(base["__tlast_"..prop]) then base["__tlast_"..prop] = nil end
+			else
+				if not base[prop] then util.send_error_backtrace("Error removing property "..tostring(prop).." with value "..tostring(v).." : base[prop] is nil") return end
+				base[prop] = base[prop] - v
+			end
 --			print("delTmpVal", prop, v, method)
 		else
 			if config.settings.cheat then
diff --git a/game/engines/default/engine/interface/ActorTalents.lua b/game/engines/default/engine/interface/ActorTalents.lua
index 4cfebb6bccc0672cfa26929fc8f575a05b977eba..a5ed4288c65bff1bfc26c694cd6ded422d8d0ebc 100644
--- a/game/engines/default/engine/interface/ActorTalents.lua
+++ b/game/engines/default/engine/interface/ActorTalents.lua
@@ -1140,9 +1140,13 @@ end
 function _M:talentParticles(p, ...)
 	local Particles = require "engine.Particles"
 	if not p.__tmpparticles then p.__tmpparticles = {} end
+	local ret = {}
 	for _, ps in ipairs{...} do
-		p.__tmpparticles[#p.__tmpparticles+1] = self:addParticles(Particles.new(ps.type, 1, ps.args, ps.shader))
+		local pp = self:addParticles(Particles.new(ps.type, 1, ps.args, ps.shader))
+		p.__tmpparticles[#p.__tmpparticles+1] = pp
+		ret[#ret+1] = pp
 	end
+	return unpack(ret)
 end
 
 --- Trigger a talent method
diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index ef9465b819cb3f2f00b0ac8aaff0ddcf2333b601..440743211b1ba6caa3fa19ade79667582b3fdf8a 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -4554,6 +4554,15 @@ function _M:onWear(o, inven_id, bypass_set, silent)
 		-- o.wielder.wielded = true
 	end
 
+	if o.talents_add_levels_filters then
+		self.talents_add_levels_custom = self.talents_add_levels_custom or {}
+		for i = 1, #o.talents_add_levels_filters do
+			local id = util.uuid()
+			self.talents_add_levels_custom[id] = o.talents_add_levels_filters[i].filter
+			o.talents_add_levels_filters[i]._id = id
+		end
+	end
+
 	if o.talent_on_spell then
 		self.talent_on_spell = self.talent_on_spell or {}
 		for i = 1, #o.talent_on_spell do
@@ -4626,6 +4635,14 @@ end
 function _M:onTakeoff(o, inven_id, bypass_set, silent)
 	engine.interface.ActorInventory.onTakeoff(self, o, inven_id)
 
+	if o.talents_add_levels_filters then
+		self.talents_add_levels_custom = self.talents_add_levels_custom or {}
+		for i = 1, #o.talents_add_levels_filters do
+			local id = o.talents_add_levels_filters[i]._id
+			self.talents_add_levels_custom[id] = nil
+		end
+	end
+
 	if o.talent_on_spell then
 		self.talent_on_spell = self.talent_on_spell or {}
 		for i = 1, #o.talent_on_spell do
@@ -6786,8 +6803,14 @@ end
 
 --- Called if a talent level is > 0
 function _M:alterTalentLevelRaw(t, lvl)
-	if self.talents_add_levels and self.talents_add_levels[id] then lvl = lvl + self.talents_add_levels[id] end
+	if t.no_unlearn_last then return lvl end -- Those are dangerous, do not change them
+	if self.talents_add_levels and self.talents_add_levels[t.id] then lvl = lvl + self.talents_add_levels[t.id] end
 	if self:attr("spells_bonus_level") and t.is_spell then lvl = lvl + self:attr("spells_bonus_level") end
+	if self.talents_add_levels_custom and next(self.talents_add_levels_custom) then
+		for id, filter in pairs(self.talents_add_levels_custom) do if type(filter) == "function" then
+			lvl = filter(self, t, lvl) or lvl
+		end end
+	end
 	-- if self:attr("mind_bonus_level") and t.is_mind then lvl = lvl + self:attr("mind_bonus_level") end
 	-- if self:attr("nature_bonus_level") and t.is_nature then lvl = lvl + self:attr("nature_bonus_level") end
 	return lvl
diff --git a/game/modules/tome/class/Object.lua b/game/modules/tome/class/Object.lua
index c92055cb1097c32faaf1a85cc9436725268db602..de09a044542b09db907a725502aa07a4176187c3 100644
--- a/game/modules/tome/class/Object.lua
+++ b/game/modules/tome/class/Object.lua
@@ -2055,6 +2055,18 @@ function _M:getTextualDesc(compare_with, use_actor)
 		use_actor.__inscription_data_fake = nil
 	end
 
+	if self.wielder and self.wielder.talents_add_levels then
+		for tid, lvl in pairs(self.wielder.talents_add_levels) do
+			local t = use_actor:getTalentFromId(tid)
+			desc:add(lvl < 0 and {"color","FIREBRICK"} or {"color","OLIVE_DRAB"}, ("Talent level: %+d %s."):tformat(lvl, t and t.name or "???"), {"color","LAST"}, true)
+		end
+	end
+	if self.talents_add_levels_filters then
+		for _, data in ipairs(self.talents_add_levels_filters) do
+			desc:add(data.detrimental and {"color","FIREBRICK"} or {"color","OLIVE_DRAB"}, ("Talent level: %s."):tformat(data.desc), {"color","LAST"}, true)
+		end
+	end
+
 	local talents = {}
 	if self.talent_on_spell then
 		for _, data in ipairs(self.talent_on_spell) do if data.talent then
diff --git a/game/modules/tome/class/WorldNPC.lua b/game/modules/tome/class/WorldNPC.lua
index 9ad69ba50d7f6ab864843f107255025e67f41829..d52f4cdad32a38a5c8e44d3f8507fba13ebf35b5 100644
--- a/game/modules/tome/class/WorldNPC.lua
+++ b/game/modules/tome/class/WorldNPC.lua
@@ -187,5 +187,5 @@ function _M:tooltip(x, y, seen_by)
 end
 
 function _M:die(src)
-	engine.interface.ActorLife.die(self, src)
+	return engine.interface.ActorLife.die(self, src)
 end
diff --git a/game/modules/tome/class/interface/PartyDeath.lua b/game/modules/tome/class/interface/PartyDeath.lua
index 5092cbf225adef4596bd559970520168bc740775..cca7a45e887e65599fe4b4a994dd69e998ed1d3b 100644
--- a/game/modules/tome/class/interface/PartyDeath.lua
+++ b/game/modules/tome/class/interface/PartyDeath.lua
@@ -26,6 +26,10 @@ module(..., package.seeall, class.make)
 function _M:onPartyDeath(src, death_note)
 	if self.dead then if game.level:hasEntity(self) then game.level:removeEntity(self, true) end return true end
 
+	-- Die
+	death_note = death_note or {}
+	if not mod.class.Actor.die(self, src, death_note) then return end
+
 	-- Remove from the party if needed
 	if self.remove_from_party_on_death then
 		game.party:removeMember(self, true)
@@ -34,12 +38,8 @@ function _M:onPartyDeath(src, death_note)
 		game.party:setDeathTurn(self, game.turn)
 	end
 
-	-- Die
-	death_note = death_note or {}
-	mod.class.Actor.die(self, src, death_note)
-
 	-- Was not the current player, just die
-	if game.player ~= self then return end
+	if game.player ~= self then return true end
 
 	-- Check for any survivor that can be controlled
 	local game_ender = not game.party:findSuitablePlayer()
@@ -138,4 +138,5 @@ function _M:onPartyDeath(src, death_note)
 			profile.chat.uc_ext:sendKillerLink(msg, short_msg, src)
 		end
 	end
+	return true
 end
diff --git a/game/modules/tome/data/birth/classes/mage.lua b/game/modules/tome/data/birth/classes/mage.lua
index e59263825c7ed7e3c8434b2b26930db9fccb4d09..ef7e303de2179e7c4ca525a818416a6f0857a201 100644
--- a/game/modules/tome/data/birth/classes/mage.lua
+++ b/game/modules/tome/data/birth/classes/mage.lua
@@ -255,16 +255,16 @@ newBirthDescriptor{
 	talents_types = {
 		["spell/master-of-bones"]={true, 0.3},
 		["spell/master-of-flesh"]={true, 0.3},
-		["spell/master-necromancer"]={true, 0.3},
+		["spell/master-necromancer"]={false, 0.3},
 		["spell/grave"]={true, 0.3},
 		["spell/glacial-waste"]={true, 0.3},
-		["spell/rime-wraith"]={true, 0.3},
+		["spell/rime-wraith"]={false, 0.3},
 		["spell/nightfall"]={true, 0.3},
 		["spell/dreadmaster"]={true, 0.3},
-		["spell/age-of-dusk"]={true, 0.3},
+		["spell/age-of-dusk"]={false, 0.3},
 		["spell/death"]={true, 0.3},
 		["spell/animus"]={true, 0.3},
-		["spell/eradication"]={true, 0.3},
+		["spell/eradication"]={false, 0.3},
 		["spell/spectre"]={true, 0.3},
 		["spell/necrosis"]={true, 0.3},
 		["cunning/survival"]={true, 0.0},
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index 91791c504a6bce4cf9033d7a6f94229bcb29793b..5fcd7ec72f019df64fabe1dd0e72f1e4ec5ff0b1 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -4308,3 +4308,19 @@ newDamageType{
 		return realdam or 0
 	end,
 }
+
+newDamageType{
+	name = _t"boneyard", type = "BONEYARD", text_color = "#GREY#",
+	projector = function(src, x, y, type, dam, state)
+		state = initState(state)
+		useImplicitCrit(src, state)
+		local target = game.level.map(x, y, Map.ACTOR)
+		if not target then return end
+
+		if src:reactionToward(target) < 0 then
+			target:setEffect(target.EFF_BRITTLE_BONES, 1, {apply_power=src:combatSpellpower(), resist=dam.resist, cooldown=dam.cooldown})
+		elseif target.summoner == src and target.necrotic_minion then
+			target:setEffect(target.EFF_BONEYARD, 1, {power=dam.power})
+		end
+	end,
+}
diff --git a/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua b/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua
index 27e25496fc831bcb93a362fce8940dfe963c7344..902ded6247ce8d73bd1ae43ca864e4125d18454f 100644
--- a/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua
+++ b/game/modules/tome/data/general/objects/boss-artifacts-maj-eyal.lua
@@ -1749,7 +1749,7 @@ newEntity{ base = "BASE_GAUNTLETS", define_as = "STORM_BRINGER_GAUNTLETS",
 		inc_stats = { [Stats.STAT_MAG] = 6, },
 		combat_spellpower = 12,
 		resists = { [DamageType.LIGHTNING] = 15, },
-		inc_damage = { [DamageType.LIGHTNING] = 20 },
+		inc_damage = { [DamageType.LIGHTNING] = 15 },
 		combat_spellcrit = 5,
 		combat_critical_power = 20,
 		combat_armor = 5,
@@ -1760,10 +1760,20 @@ newEntity{ base = "BASE_GAUNTLETS", define_as = "STORM_BRINGER_GAUNTLETS",
 			physspeed = 0.2,
 			dammod = {dex=0.4, str=-0.6, cun=0.4 },
 			melee_project={ [DamageType.LIGHTNING] = 20, },
-			talent_on_hit = { [Talents.T_CHAIN_LIGHTNING] = {level=3, chance=20}, [Talents.T_NOVA] = {level=2, chance=15} },
+			talent_on_hit = { [Talents.T_CHAIN_LIGHTNING] = {level=2, chance=20}, [Talents.T_NOVA] = {level=1, chance=15} },
 			damrange = 0.3,
 		},
 	},
+	talents_add_levels_filters = {
+		{desc=_t"+1 to all lightning damage spells", filter=function(who, t, lvl)
+			if t.is_spell and t.tactical and (
+				table.get(t.tactical, "attack", "LIGHTNING") or
+				table.get(t.tactical, "attackarea", "LIGHTNING")
+			) then
+				return lvl + 1
+			end
+		end},
+	},
 	talent_on_spell = {
 		{chance=10, talent=Talents.T_LIGHTNING, level=1},
 	},
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_archer.png b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_archer.png
new file mode 100644
index 0000000000000000000000000000000000000000..713ed34cc420658f6b39a02447d67aecf8935822
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_archer.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_magus.png b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_magus.png
new file mode 100644
index 0000000000000000000000000000000000000000..68a473b3f510883827062b143a88e59749e1d373
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_magus.png differ
diff --git a/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_warrior.png b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_warrior.png
new file mode 100644
index 0000000000000000000000000000000000000000..9be69ee59bbff16824c013ac0bea307468385f0a
Binary files /dev/null and b/game/modules/tome/data/gfx/shockbolt/npc/lord_of_skulls_warrior.png differ
diff --git a/game/modules/tome/data/talents/spells/death.lua b/game/modules/tome/data/talents/spells/death.lua
index c3af1defd6f6d13e1a1f19834430ca6713339ba5..d91e95c8aaa7783d37b7f6edcece56c1691371d5 100644
--- a/game/modules/tome/data/talents/spells/death.lua
+++ b/game/modules/tome/data/talents/spells/death.lua
@@ -204,37 +204,30 @@ newTalent{
 	points = 5,
 	mode = "sustained",
 	cooldown = 30,
-	sustain_mana = 30,
-	getNb = function(self, t) return math.floor(self:combatTalentScale(t, 2, 8)) end,
-	getMana = function(self, t) return math.floor(self:combatTalentScale(t, 5, 30)) / 10 end,
-	getSpellpower = function(self, t) return math.floor(self:combatTalentScale(t, 10, 40)) end,
-	getResists = function(self, t) return math.floor(self:combatTalentLimit(t, 20, 5, 10)) end,
-	callbackOnActBase = function(self, t)
-		if not self.__old_reaping_souls then self.__old_reaping_souls = self:getSoul() end
-		if self.__old_reaping_souls == self:getSoul() then return end
-		self:updateTalentPassives(t)
-	end,
-	passives = function(self, t, p)
-		if not self:isTalentActive(t.id) then return end
-		local s = self:getSoul()
-		if s >= 2 then self:talentTemporaryValue(p, "mana_regen", t.getMana(self, t)) end
-		if s >= 5 then self:talentTemporaryValue(p, "combat_spellpower", t.getSpellpower(self, t)) end
-		if s >= 8 then self:talentTemporaryValue(p, "resists", {all=t.getResists(self, t)}) end
-		self:talentTemporaryValue(p, "max_soul", t.getNb(self, t))
+	sustain_mana = 15,
+	getMana = function(self, t) return math.floor(self:combatTalentScale(t, 10, 27)) end,
+	getDur = function(self, t) return math.floor(self:combatTalentScale(t, 2, 6)) end,
+	trigger = function(self, t)
+		self:incMana(t:_getMana(self))
+		if self:getTalentLevel(t) >= 3 then
+			self:setEffect(self.EFF_DEATH_RUSH, t:_getDur(self), {power=0.5})
+		end
+	end,
+	callbackOnKill = function(self, t, target, death_note)
+		t:_trigger(self)
+	end,
+	callbackOnSummonKill = function(self, t, minion, target, death_note)
+		t:_trigger(self)
 	end,
 	activate = function(self, t)
-		game:onTickEnd(function() self:updateTalentPassives(t) end)
 		return {}
 	end,
 	deactivate = function(self, t)
 		return true
 	end,
 	info = function(self, t)
-		return ([[You draw constant power from the souls you hold within your grasp.
-		If you hold at least 2, your mana regeneration is increased by %0.1f per turn.
-		If you hold at least 5, your spellpower is increased by %d.
-		If you hold at least 8, all your resistances are increased by %d.
-		Also increases your maximum souls capacity by %d.]]):
-		tformat(t.getMana(self, t), t.getSpellpower(self, t), t.getResists(self, t), t.getNb(self, t))
+		return ([[Whenever a creature is killed by yourself or a minion you feast on its essence, gaining %0.1f mana.
+		At level 3 the thrill of the death invigorates you, granting a movement sped bonus of 50%% for %d turns.]]):
+		tformat(t.getMana(self, t), t.getDur(self, t))
 	end,
 }
diff --git a/game/modules/tome/data/talents/spells/eradication.lua b/game/modules/tome/data/talents/spells/eradication.lua
new file mode 100644
index 0000000000000000000000000000000000000000..3e5c6063125dcbcca9d8562872241c905362ae6f
--- /dev/null
+++ b/game/modules/tome/data/talents/spells/eradication.lua
@@ -0,0 +1,228 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009 - 2020 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 = "Boneyard",
+	type = {"spell/eradication",1},
+	require = spells_req_high1,
+	points = 5,
+	soul = 1,
+	mana = 30,
+	range = 0,
+	radius = 5,
+	cooldown = 20,
+	tactical = { BUFF = 2 },
+	requires_target = true,
+	target = function(self, t) return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t), talent=t} end,
+	getResist = function(self, t) return math.floor(self:combatTalentScale(t, 5, 15)) end,
+	getCooldown = function(self, t) return math.floor(self:combatTalentScale(t, 10, 30)) end,
+	getPower = function(self, t) return math.floor(self:combatTalentScale(t, 10, 55)) end,
+	getResurrect = function(self, t) return math.floor(self:combatTalentScale(t, 1, 9)) end,
+	callbackOnSummonDeath = function(self, t, summon, src, death_note)
+		if summon.summoner ~= self or not summon.necrotic_minion or summon.boneyard_resurrected then return end
+		local ok = false
+		for i, e in ipairs(game.level.map.effects) do
+			if e.damtype == DamageType.BONEYARD and e.src == self and e.grids[summon.x] and e.grids[summon.x][summon.y] then ok = true break end
+		end		
+		if not ok then return end
+
+		if summon.summon_time_max then summon.summon_time = math.ceil(summon.summon_time_max * 0.66) end
+		summon.boneyard_resurrected = true
+		game.logSeen(summon, "#GREY#%s is resurrected by the boneyard!", summon:getName():capitalize())
+		return true
+	end,
+	action = function(self, t)
+		game.level.map:addEffect(self,
+			self.x, self.y, 8,
+			DamageType.BONEYARD, {resist=t:_getResist(self), cooldown=t:_getCooldown(self), power=t:_getPower(self), resurrect=t:_getResurrect(self)},
+			self:getTalentRadius(t),
+			5, nil,
+			{type="vapour"},
+			nil,
+			true, true
+		)
+		game:playSoundNear(self, "talents/skeleton")
+		return true
+	end,
+	info = function(self, t)
+		return ([[Spawn a boneyard of radius %d around you that lasts for 8 turns.
+		Any foes inside gain the brittle bones effect, reducing their physical resistance by %d%% and making all cooldowns %d%% longer.
+		When one of your minion stands in the boneyard they gain %d more physical and spell power.
+		At level 5 when a minion dies inside the boneyard it has %d%% chances to resurrect instantly. This effect may only happen once per minion.
+		]]):tformat(self:getTalentRadius(t), t:_getResist(self), t:_getCooldown(self), t:_getPower(self), t:_getResurrect(self))
+	end,
+}
+
+newTalent{
+	name = "To The Grave",
+	type = {"spell/eradication", 2},
+	require = spells_req_high2,
+	points = 5,
+	cooldown = 20,
+	soul = 1,
+	mana = 28,
+	requires_target = true,
+	direct_hit = true,
+	range = 0,
+	radius = function(self, t) return math.floor(self:combatTalentScale(t, 3, 9)) end,
+	getNb = function(self, t) return math.floor(self:combatTalentScale(t, 1, 5)) end,
+	target = function(self, t) return {type="ball", range=self:getTalentRange(t), radius=self:getTalentRadius(t)} end,
+	on_pre_use = function(self, t)
+		for i, e in ipairs(game.level.map.effects) do
+			if e.damtype == DamageType.BONEYARD and e.src == self then return true end
+		end		
+	end,
+	action = function(self, t)
+		local boneyard = nil
+		for i, e in ipairs(game.level.map.effects) do
+			if e.damtype == DamageType.BONEYARD and e.src == self then boneyard = e break end
+		end
+		if not boneyard then return end
+
+		local tg = self:getTalentTarget(t)
+		local list = {}
+		self:projectApply(tg, self.x, self.y, Map.ACTOR, function(target, x, y)
+			list[#list+1] = {target=target, dist=core.fov.distance(target.x, target.y, boneyard.x, boneyard.y)}
+		end, "hostile")
+		if #list == 0 then return end
+		table.sort(list, "dist")
+
+		local _, _, gs = util.findFreeGrid(boneyard.x, boneyard.y, boneyard.radius, true, {[Map.ACTOR]=true})
+		if #gs == 0 then return true end
+
+		while #gs > 0 and #list > 0 do
+			local foe = table.remove(list, 1).target
+			local spot = table.remove(gs, 1)
+			if foe:canBe("teleport") and target:checkHit(self:combatSpellpower(), target:combatSpellResist(), 0, 95, 15) then
+				foe:forceMoveAnim(spot[1], spot[2])
+			else
+				game.logSeen(foe, "%s resists the call of the boneyard!")
+			end
+		end
+
+		local nb = t:_getNb(self)
+		local t_skeleton = self:getTalentFromId(self.T_CALL_OF_THE_CRYPT)
+		local t_ghoul = self:getTalentFromId(self.T_CALL_OF_THE_MAUSOLEUM)
+		while #gs > 0 and nb > 0 do
+			local spot = table.remove(gs, 1)
+			nb = nb - 1
+			local m
+			if rng.percent(50) then
+				m = necroSetupSummon(self, t_ghoul.minions_list.ghoul, spot[1], spot[2], 0, 5, true)
+			else
+				m = necroSetupSummon(self, t_skeleton.minions_list.skel_warrior, spot[1], spot[2], 0, 5, true)
+			end
+		end
+
+		return true
+	end,	
+	info = function(self, t)
+		return ([[Teleport all foes in radius %d to your boneyard, as close to its center as possible.
+		Up to %d ghouls or skeletons are created around them by the boneyard, without any additional soul cost, but they only last 5 turns.
+		]]):tformat(self:getTalentRadius(t), t:_getNb(self))
+	end,
+}
+
+newTalent{
+	name = "Impending Doom",
+	type = {"spell/eradication", 3},
+	require = spells_req_high3,
+	points = 5,
+	mana = 50,
+	soul = 1,
+	cooldown = 25,
+	tactical = { ATTACK = { COLD = 2, DARKNESS = 2 }, DISABLE = 2 },
+	rnd_boss_restrict = function(self, t, data) return data.level < 15 end,
+	range = 7,
+	requires_target = true,
+	getMax = function(self, t) return 200 + self:combatTalentSpellDamage(t, 28, 850) end,
+	getDamage = function(self, t) return self:combatLimit(self:combatTalentSpellDamage(t, 10, 100), 150, 50, 0, 117, 67) end, -- Limit damage factor to < 150%
+	action = function(self, t)
+		local tg = {type="hit", range=self:getTalentRange(t), talent=t}
+		local x, y = self:getTarget(tg)
+		if not x or not y then return nil end
+		self:project(tg, x, y, function(px, py)
+			local target = game.level.map(px, py, Map.ACTOR)
+			if not target then return end
+			local dam = target.life * t.getDamage(self, t) / 100
+			dam = math.min(dam, t.getMax(self, t))
+			target:setEffect(target.EFF_IMPENDING_DOOM, 10, {apply_power=self:combatSpellpower(), dam=dam/10, src=self})
+		end, 1, {type="freeze"})
+		return true
+	end,
+	info = function(self, t)
+		return ([[Your target's doom draws near. Its healing factor is reduced by 80%%, and will take %d%% of its remaining life (or %0.2f, whichever is lower) over 10 turns as arcane damage.
+		This spell is so powerful that every 2 turns it tears a part of the target's soul, generating one soul for you.
+		The damage will increase with your Spellpower.]]):
+		tformat(t.getDamage(self, t), t.getMax(self, t))
+	end,
+}
+
+newTalent{
+	name = "Eternal Night",
+	type = {"spell/eradication",4},
+	require = spells_req_high4,
+	points = 5,
+	mode = "sustained",
+	sustain_mana = 50,
+	cooldown = 30,
+	tactical = { BUFF = 2 },
+	getDamageIncrease = function(self, t) return self:combatTalentScale(t, 2.5, 10) end,
+	getResistPenalty = function(self, t) return self:combatTalentLimit(t, 100, 17, 50, true) end,
+	getVampiric = function(self, t) return math.floor(self:combatTalentLimit(t, 60, 3, 8)) end,
+	callbackOnActBase = function(self, t)
+		local p = self:isTalentActive(t.id) if not p then return end
+		if p.cur_value > 0 then self:heal(p.cur_value, self) end
+		p.cur_value = 0
+	end,
+	callbackOnDealDamage = function(self, t, value, target, dead, death_node)
+		if value <= 0 then return end
+		local p = self:isTalentActive(t.id) if not p then return end
+		p.cur_value = p.cur_value + value * t:_getVampiric(self) / 100
+	end,
+	activate = function(self, t)
+		game:playSoundNear(self, "talents/spell_generic")
+		local ret = { cur_value = 0 }
+		self:talentTemporaryValue(ret, "inc_damage", {[DamageType.DARKNESS] = t.getDamageIncrease(self, t), [DamageType.COLD] = t.getDamageIncrease(self, t)})
+		self:talentTemporaryValue(ret, "resists_pen", {[DamageType.DARKNESS] = t.getResistPenalty(self, t), [DamageType.COLD] = t.getResistPenalty(self, t)})
+
+		local particle
+		if core.shader.active(4) then
+			local p1, p2 = self:talentParticles(ret, 
+				{type="shader_ring_rotating", args={rotation=0, radius=1.1, img="spinningwinds_black"}, shader={type="spinningwinds", ellipsoidalFactor={1,1}, time_factor=6000, noup=2.0, verticalIntensityAdjust=-3.0}},
+				{type="shader_ring_rotating", args={rotation=0, radius=1.1, img="spinningwinds_black"}, shader={type="spinningwinds", ellipsoidalFactor={1,1}, time_factor=6000, noup=1.0, verticalIntensityAdjust=-3.0}}
+			)
+			p1.toback = true
+		else
+			self:talentParticles(ret, {type="ultrashield", args={rm=0, rM=0, gm=0, gM=0, bm=10, bM=100, am=70, aM=180, radius=0.4, density=60, life=14, instop=20}})
+		end
+		return ret
+	end,
+	deactivate = function(self, t, p)
+		return true
+	end,
+	info = function(self, t)
+		local damageinc = t.getDamageIncrease(self, t)
+		local ressistpen = t.getResistPenalty(self, t)
+		local affinity = t.getVampiric(self, t)
+		return ([[Surround yourself with Frostdusk, increasing all your darkness and cold damage by %0.1f%%, and ignoring %d%% of the darkness and cold resistance of your targets.
+		In addition, at the end of each turn you are healed for %d%% of all damage you dealt.]])
+		:tformat(damageinc, ressistpen, affinity)
+	end,
+}
diff --git a/game/modules/tome/data/talents/spells/master-of-flesh.lua b/game/modules/tome/data/talents/spells/master-of-flesh.lua
index 69f66eb37432781437c2c40da17a4595517372a0..faa4693167fa1284724491c36b7fd342aea95b00 100644
--- a/game/modules/tome/data/talents/spells/master-of-flesh.lua
+++ b/game/modules/tome/data/talents/spells/master-of-flesh.lua
@@ -132,13 +132,13 @@ newTalent{
 	summonGhoul = function(self, t, possible_spots, def)
 		local pos = table.remove(possible_spots, 1)
 		if pos then
-			necroSetupSummon(self, def, pos.x, pos.y, lev, t:_getTurns(self), true)
+			necroSetupSummon(self, def, pos.x, pos.y, t.getLevel(self, t), t:_getTurns(self), true)
 			self.__call_mausoleum_count = (self.__call_mausoleum_count or 0) + 1
 			if self.__call_mausoleum_count == 4 then
 				self.__call_mausoleum_count = 0
 				if self:getTalentLevel(t) >= 5 then
 					local pos = table.remove(possible_spots, 1)
-					if pos then necroSetupSummon(self, t.minions_list.ghoulking, pos.x, pos.y, lev, t:_getTurns(self), true) end
+					if pos then necroSetupSummon(self, t.minions_list.ghoulking, pos.x, pos.y, t.getLevel(self, t), t:_getTurns(self), true) end
 				end
 			end
 			return true
diff --git a/game/modules/tome/data/talents/spells/spells.lua b/game/modules/tome/data/talents/spells/spells.lua
index 0707f350c4d52821cd655bc672d5a5e8c597eb46..7b02b85251d40b6f5f9d0e1b455b59d185612de7 100644
--- a/game/modules/tome/data/talents/spells/spells.lua
+++ b/game/modules/tome/data/talents/spells/spells.lua
@@ -152,7 +152,10 @@ function necroSetupSummon(self, def, x, y, level, turns, no_control)
 	m.faction = self.faction
 	m.summoner = self
 	m.summoner_gain_exp = true
-	if turns then m.summon_time = turns end
+	if turns then
+		m.summon_time_max = turns
+		m.summon_time = turns
+	end
 	m.exp_worth = 0
 	m.life_regen = 0
 	m.unused_stats = 0
@@ -308,6 +311,7 @@ load("/data/talents/spells/master-of-flesh.lua")
 load("/data/talents/spells/master-necromancer.lua")
 load("/data/talents/spells/animus.lua")
 load("/data/talents/spells/death.lua")
+load("/data/talents/spells/eradication.lua")
 load("/data/talents/spells/necrosis.lua")
 load("/data/talents/spells/spectre.lua")
 
diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua
index 4dfaf38fdda267af95bef7e176675c3df7e9ab14..d614ad37a7eeca156c7407cd00c030a0b6b2b735 100644
--- a/game/modules/tome/data/timed_effects/magical.lua
+++ b/game/modules/tome/data/timed_effects/magical.lua
@@ -2001,7 +2001,7 @@ newEffect{
 newEffect{
 	name = "IMPENDING_DOOM", image = "talents/impending_doom.png",
 	desc = _t"Impending Doom",
-	long_desc = function(self, eff) return ("The target's final doom is drawing near, reducing healing factor by 80%% and dealing %0.2f arcane damage per turn. The effect will stop if the caster dies."):tformat(eff.dam) end,
+	long_desc = function(self, eff) return ("The target's final doom is drawing near, reducing healing factor by 80%% and dealing %0.2f frostdusk damage per turn. The effect will stop if the caster dies."):tformat(eff.dam) end,
 	type = "magical",
 	subtype = { arcane=true },
 	status = "detrimental",
@@ -2010,10 +2010,16 @@ newEffect{
 	on_lose = function(self, err) return _t"#Target# is freed from the impending doom.", _t"-Doomed" end,
 	activate = function(self, eff)
 		eff.healid = self:addTemporaryValue("healing_factor", -0.8)
+		eff.soul_turn = false
 	end,
 	on_timeout = function(self, eff)
 		if eff.src.dead or not game.level:hasEntity(eff.src) then return true end
-		DamageType:get(DamageType.ARCANE).projector(eff.src, self.x, self.y, DamageType.ARCANE, eff.dam)
+		DamageType:get(DamageType.FROSTDUSK).projector(eff.src, self.x, self.y, DamageType.FROSTDUSK, eff.dam)
+		eff.soul_turn = not eff.soul_turn
+		if eff.soul_turn then
+			eff.src:incSoul(1)
+			game.logSeen(self, "#CRIMSON#A piece of the soul of %s is torn apart by Impending Doom!", self:getName())
+		end
 	end,
 	deactivate = function(self, eff)
 		self:removeTemporaryValue("healing_factor", eff.healid)
@@ -2035,6 +2041,21 @@ newEffect{
 	end,
 }
 
+newEffect{
+	name = "DEATH_RUSH", image = "talents/utterly_destroyed.png",
+	desc = _t"DEATH_RUSH",
+	long_desc = function(self, eff) return ("Movement speed increased by %d%%."):tformat(eff.power*100) end,
+	type = "magical",
+	subtype = { necrotic=true },
+	status = "beneficial",
+	parameters = {power=0.5},
+	on_gain = function(self, err) return _t"#Target# is invogorated by death!", true end,
+	on_lose = function(self, err) return _t"#Target# is less fast.", true end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "movement_speed", eff.power)
+	end,
+}
+
 newEffect{
 	name = "ABYSSAL_SHROUD", image = "talents/abyssal_shroud.png",
 	desc = _t"Abyssal Shroud",
@@ -4734,6 +4755,18 @@ newEffect{
 			elseif self.skeleton_minion == "mage" then self:learnTalent(self.T_METEORIC_CRASH, true)
 			end
 		end
+
+		local image
+		if self.skeleton_minion == "warrior" then image = "npc/lord_of_skulls_warrior.png"
+		elseif self.skeleton_minion == "archer" then image = "npc/lord_of_skulls_archer.png"
+		elseif self.skeleton_minion == "mage" then image = "npc/lord_of_skulls_magus.png"
+		end
+
+		self.replace_display = mod.class.Actor.new{
+			image = image, display_y = -1, display_h = 2
+		}
+		self:removeAllMOs()
+		game.level.map:updateMap(self.x, self.y)
 	end,
 	deactivate = function(self, eff)
 		self.lord_of_skulls = false
@@ -4744,6 +4777,9 @@ newEffect{
 			end
 		end
 		self.name = self.old_los_name
+		self.replace_display = nil
+		self:removeAllMOs()
+		game.level.map:updateMap(self.x, self.y)
 	end,
 }
 
@@ -4821,3 +4857,35 @@ newEffect{
 		eff.turn_list = {}
 	end,
 }
+
+newEffect{
+	name = "BRITTLE_BONES", image = "talents/boneyard.png",
+	desc = _t"Brittle Bones",
+	long_desc = function(self, eff) return ("Physical resistance reduced by %d%% and talents cooldowns increased by %d%%."):tformat(eff.resist, eff.cooldown) end,
+	type = "magical",
+	subtype = { necrotic=true, resistance=true, cooldown=true },
+	status = "detrimental",
+	parameters = {resist=10, cooldown=20},
+	on_gain = function(self, err) return nil, true end,
+	on_lose = function(self, err) return nil, true end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "resists", {[DamageType.PHYSICAL] = -eff.resist})
+		self:effectTemporaryValue(eff, "talent_cd_reduction", {allpct = -eff.cooldown/100})
+	end,
+}
+
+newEffect{
+	name = "BONEYARD", image = "talents/boneyard.png",
+	desc = _t"Boneyard",
+	long_desc = function(self, eff) return ("Spellpower and physical power increased by %d."):tformat(eff.power) end,
+	type = "magical",
+	subtype = { necrotic=true, power=true },
+	status = "beneficial",
+	parameters = {power=10},
+	on_gain = function(self, err) return nil, true end,
+	on_lose = function(self, err) return nil, true end,
+	activate = function(self, eff)
+		self:effectTemporaryValue(eff, "combat_spellpower", eff.power)
+		self:effectTemporaryValue(eff, "combat_dam", eff.power)
+	end,
+}