diff --git a/game/modules/tome/class/Actor.lua b/game/modules/tome/class/Actor.lua
index 49069afe1826e840f54f97f100c50f2e680bf895..aa2e65a81f7dcccc98c58795b88d8d9af067bfac 100644
--- a/game/modules/tome/class/Actor.lua
+++ b/game/modules/tome/class/Actor.lua
@@ -358,7 +358,7 @@ function _M:stripForExport()
 	self:setTarget(nil)
 
 	-- Disable all sustains, remove all effects
-	self:removeEffectsSustainsFilter(true, nil, nil, {silent=true, force=true, save_cleanup=true})
+	self:removeEffectsSustainsFilter(self, true, nil, nil, {silent=true, force=true, save_cleanup=true})
 end
 
 -- Dummy
@@ -3131,7 +3131,7 @@ function _M:die(src, death_note)
 
 		local effs = {}
 
-		self:removeEffectsSustainsFilter()
+		self:removeEffectsSustainsFilter(self, nil, nil, nil, {no_resist=true})
 
 		self.life = self.max_life
 		self.mana = self.max_mana
@@ -5995,6 +5995,8 @@ local sustainCallbackCheck = {
 	callbackOnDeathbox = "talents_on_deathbox",
 	callbackOnSummonDeath = "talents_on_summon_death",
 	callbackOnResurrect = "talents_on_resurrect",
+	callbackOnDispelled = "talents_on_dispelled",
+	callbackOnDispel = "talents_on_dispel",
 	callbackOnDie = "talents_on_die",
 	callbackOnKill = "talents_on_kill",
 	callbackOnSummonKill = "talents_on_summon_kill",
@@ -7064,12 +7066,13 @@ function _M:effectsFilter(t, nb)
 	return rng.tableSample(effs, nb)
 end
 
-function _M:removeEffectsFilter(t, nb, silent, force, check_remove)
+function _M:removeEffectsFilter(src, t, nb, silent, force, check_remove, allow_immunity)
+	if allow_immunity == nil then allow_immunity = true end
 	t = t or {}
 	local eff_ids = self:effectsFilter(t, nb)
 	for _, eff_id in ipairs(eff_ids) do
 		if not check_remove or check_remove(self, eff_id) then
-			self:removeEffect(eff_id, silent, force)
+			self:dispel(eff_id, src, not force and allow_immunity, {force=force, silent=silent})
 		end
 	end
 	return #eff_ids
@@ -7102,18 +7105,18 @@ function _M:sustainsFilter(t, nb)
 	return rng.tableSample(ids, nb)
 end
 
-function _M:removeSustainsFilter(t, nb, check_remove)
+function _M:removeSustainsFilter(src, t, nb, check_remove, allow_immunity)
 	t = t or {}
 	local found = self:sustainsFilter(t, nb)
 	for _, tid in ipairs(found) do
 		if not check_remove or check_remove(self, tid) then
-			self:forceUseTalent(tid, {ignore_energy=true})
+			self:dispel(tid, src, allow_immunity)
 		end
 	end
 	return #found
 end
 
-function _M:removeEffectsSustainsFilter(t, nb, check_remove, params)
+function _M:removeEffectsSustainsFilter(src, t, nb, check_remove, params)
 	if not params then params = {} end
 	if params.silent == nil then params.silent = false end
 	if params.force == nil then params.force = false end
@@ -7129,18 +7132,15 @@ function _M:removeEffectsSustainsFilter(t, nb, check_remove, params)
 	local nbr = 0
 	for obj in rng.tableSampleIterator(objects, nb) do
 		if not check_remove or check_remove(self, obj) then
-			if obj[1] == "effect" then
-				self:removeEffect(obj[2], silent, force)
-			else
-				self:forceUseTalent(obj[2], {ignore_energy=true, silent=silent})
+			if self:dispel(obj[2], src, not params.force and not params.no_resist, params) then
+				nbr = nbr + 1
 			end
-			nbr = nbr + 1
 		end
 	end
 	return nbr
 end
 
-function _M:removeEffectsSustainsTable(effs, susts, nb, check_remove, params)
+function _M:removeEffectsSustainsTable(src, effs, susts, nb, check_remove, params)
 	if not params then params = {} end
 	if params.silent == nil then params.silent = false end
 	if params.force == nil then params.force = false end
@@ -7156,17 +7156,73 @@ function _M:removeEffectsSustainsTable(effs, susts, nb, check_remove, params)
 	local nbr = 0
 	for obj in rng.tableSampleIterator(objects, nb) do
 		if not check_remove or check_remove(self, obj) then
-			if obj[1] == "effect" then
-				self:removeEffect(obj[2], params.silent, params.force)
-			else
-				self:forceUseTalent(obj[2], params)
+			if self:dispel(obj[2], src, not params.force and not params.no_resist, params) then
+				nbr = nbr + 1
 			end
-			nbr = nbr + 1
 		end
 	end
 	return nbr
 end
 
+--- Try to dispel an effect or sustain
+-- @param src who is doing the dispelling
+-- @param allow_immunity If true will check for canBe("dispel_XXX"), defaults to true
+function _M:dispel(effid_or_tid, src, allow_immunity, params)
+	if self:attr("invulnerable") then return end
+
+	if not params then params = {} end
+	if params.silent == nil then params.silent = false end
+	if params.force == nil then params.force = false end
+	if params.ignore_energy == nil then params.ignore_energy = true end
+	if allow_immunity == nil then allow_immunity = true end
+	local allowed = true
+
+	-- Dont resist yourself!
+	if src == self then allow_immunity = false end
+
+	-- Effect
+	if effid_or_tid:find("^EFF_") then
+		local eff = self:getEffectFromId(effid_or_tid)
+		if not eff or eff.type == "other" then return end -- NEVER touch other
+		if not self:hasEffect(effid_or_tid) then return end
+
+		if allow_immunity then
+			if not self:canBe("dispel_effects") then allowed = false end
+		end
+		if allowed and allow_immunity then
+			if self:fireTalentCheck("callbackOnDispel", "effect", effid_or_tid, src, allow_immunity) then allowed = false end
+		end
+		if allowed then
+			self:removeEffect(effid_or_tid, params.force)
+			self:fireTalentCheck("callbackOnDispelled", "effect", effid_or_tid, src, allow_immunity)
+			return true
+		else
+			game.logSeen(self, "%s resists the dispelling of %s!", self:getName():capitalize(), eff.desc)
+			return false
+		end
+	-- Sustain
+	else
+		local t = self:getTalentFromId(effid_or_tid)
+		if not t then return end
+		if not self:isTalentActive(t.id) then return end
+
+		if allow_immunity then
+			if not self:canBe("dispel_sustains") then allowed = false end
+		end
+		if allowed and allow_immunity then
+			if self:fireTalentCheck("callbackOnDispel", "sustain", effid_or_tid, src, allow_immunity) then allowed = false end
+		end
+		if allowed then
+			self:forceUseTalent(effid_or_tid, params)
+			self:fireTalentCheck("callbackOnDispelled", "sustain", effid_or_tid, src, allow_immunity)
+			return true
+		else
+			game.logSeen(self, "%s resists the dispelling of %s!", self:getName():capitalize(), t.name)
+			return false
+		end
+	end
+end
+
 --- Randomly reduce talent cooldowns based on a filter
 -- @param t the function to use as a filter on the talent definition or nil to apply to all talents on cooldown
 -- @param change the amount to change the cooldown by
@@ -7375,6 +7431,8 @@ end
 _M.StatusTypes = {poison=true,	disease=true, cut=true, confusion=true, blind=true,	silence=true,
 	disarm=true, stun=true, sleep=true, fear=true, stone=true, slow=true,
 	instakill=false, anomaly=false,
+	dispel_sustains=function(self) return 100 * ((self:attr("dispel_sustains_immune") or 0) + (self:attr("dispel_immune") or 0)) end,
+	dispel_effects=function(self) return 100 * ((self:attr("dispel_effects_immune") or 0) + (self:attr("dispel_immune") or 0)) end,
 	pin=function(self) return (self:attr("negative_status_effect_immune") or self:attr("levitation") or self:attr("fly")) and 100 or 100 * (self:attr("pin_immune") or 0) end,
 	knockback=function(self) return self:attr("never_move") and 100 or 100 * (self:attr("knockback_immune") or 0) end,
 	teleport=function(self) return self:attr("encased_in_ice") and 100 or 100 * (self:attr("teleport_immune") or 0) end,
diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua
index 781b4ec2f0b9c1250cdfc8538680ac42c53eba0a..7f0ff68ae0a44e6f58f1c2ca007a39f239614821 100644
--- a/game/modules/tome/class/Game.lua
+++ b/game/modules/tome/class/Game.lua
@@ -1340,7 +1340,7 @@ function _M:changeLevelReal(lev, zone, params)
 	self.zone_name_s = nil
 
 	-- Special stuff
-	for uid, act in pairs(self.level.entities) do if act.removeEffectsFilter then act:removeEffectsFilter(function(e) return e.zone_wide_effect end, nil, nil, true) end end
+	for uid, act in pairs(self.level.entities) do if act.removeEffectsFilter then act:removeEffectsFilter(act, function(e) return e.zone_wide_effect end, nil, nil, true) end end
 	for uid, act in pairs(self.level.entities) do
 		if act.setEffect then
 			if self.level.data.zero_gravity then act:setEffect(act.EFF_ZERO_GRAVITY, 1, {})
diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua
index b511edba41c04f0939d8b413c4c9a8e1b9b678a5..fb4762a40bd4dbe0979bf2189c5fd033406723a9 100644
--- a/game/modules/tome/data/damage_types.lua
+++ b/game/modules/tome/data/damage_types.lua
@@ -1823,7 +1823,7 @@ newDamageType{
 			end
 			if #effs > 0 then
 				local eff = rng.tableRemove(effs)
-				target:removeEffect(eff[2])
+				target:dispel(eff[2], src)
 			end
 		end
 		return realdam
@@ -2619,7 +2619,7 @@ newDamageType{
 					end
 					if #effs > 0 then
 						local eff = rng.tableRemove(effs)
-						target:removeEffect(eff[2])
+						target:dispel(eff[2], src)
 					end
 				end
 			end
diff --git a/game/modules/tome/data/general/objects/egos/charms.lua b/game/modules/tome/data/general/objects/egos/charms.lua
index ab4345eb17b8574b4f6a4197d7b2f97e577e857e..a5d08a4feefa1922e8b30a5f1919c5547aee7556 100644
--- a/game/modules/tome/data/general/objects/egos/charms.lua
+++ b/game/modules/tome/data/general/objects/egos/charms.lua
@@ -346,7 +346,7 @@ newEntity{
 	cleansing_amount = resolvers.mbonus_material(2, 1),
 	charm_on_use = {
 		{100, function(self, who) return ("cleanse %d total effects of type disease, wound, or poison"):tformat(self.cleansing_amount) end, function(self, who)
-			who:removeEffectsFilter(function(e) return e.subtype.poison or e.subtype.wound or e.subtype.disease end, self.cleansing_amount)	
+			who:removeEffectsFilter(who, function(e) return e.subtype.poison or e.subtype.wound or e.subtype.disease end, self.cleansing_amount)	
 		end},
 	},
 	use_power = {tactical = {CURE = 0.2}}
@@ -363,7 +363,7 @@ newEntity{
 	cleansing_amount = resolvers.mbonus_material(2, 1),
 	charm_on_use = {
 		{100, function(self, who) return ("cleanse %d total effects of type disease, wound, or poison"):tformat(self.cleansing_amount) end, function(self, who)
-			who:removeEffectsFilter(function(e) return e.subtype.poison or e.subtype.wound or e.subtype.disease end, self.cleansing_amount)	
+			who:removeEffectsFilter(who, function(e) return e.subtype.poison or e.subtype.wound or e.subtype.disease end, self.cleansing_amount)	
 		end},
 	},
 	use_power = {tactical = {CURE = 0.2}}
diff --git a/game/modules/tome/data/general/objects/egos/torques-powers.lua b/game/modules/tome/data/general/objects/egos/torques-powers.lua
index f2fb8d6d2909b4f998e946e158088b7f348bafa5..fdbf9627f2bf3b56126588be5d26b680a5b4a768 100644
--- a/game/modules/tome/data/general/objects/egos/torques-powers.lua
+++ b/game/modules/tome/data/general/objects/egos/torques-powers.lua
@@ -44,7 +44,7 @@ newEntity{
 	rarity = 20,
 	charm_power_def = {add=1, max=5, floor=true},
 	resolvers.charm(_t"remove 1 confusion or silence effect and prevent the application of %d detrimental mental effects for 5 turns", 25, function(self, who)
-		who:removeEffectsFilter(function(e) return (e.subtype.confusion or e.subtype.silence) end, 1)
+		who:removeEffectsFilter(who, function(e) return (e.subtype.confusion or e.subtype.silence) end, 1)
 		who:setEffect(who.EFF_CLEAR_MIND, 5, {power=self:getCharmPower(who)})
 		game.logSeen(who, "%s uses %s!", who:getName():capitalize(), self:getName{no_add_name=true, do_color=true})
 		return {id=true, used=true}
diff --git a/game/modules/tome/data/general/objects/world-artifacts.lua b/game/modules/tome/data/general/objects/world-artifacts.lua
index f259da6d5eb21dc1b01cefee664b644349159ca8..4c29dc1f52e52e945a33eaab9c626eeca829a6f0 100644
--- a/game/modules/tome/data/general/objects/world-artifacts.lua
+++ b/game/modules/tome/data/general/objects/world-artifacts.lua
@@ -3930,11 +3930,7 @@ newEntity{ base = "BASE_GAUNTLETS",
 						end
 						local eff = rng.tableRemove(effs)
 						if eff then
-							if eff[1] == "effect" then
-							target:removeEffect(eff[2])
-							else
-								target:forceUseTalent(eff[2], {ignore_energy=true})
-							end
+							target:dispel(eff[2], who)
 						end
 					end
 					if target.undead or target.construct then
@@ -4963,13 +4959,15 @@ newEntity{ base = "BASE_GREATMAUL",
 			local is_shield = false
 			-- Make them EXPLODE !!!, I mean, remove them.
 			for i, d in ipairs(shields) do
-				target:removeEffect(d.id)
-				is_shield=true
+				if target:dispel(d.id, who) then
+					is_shield = true
+				end
 			end
 
 			if target:attr("disruption_shield") then
-				target:forceUseTalent(target.T_DISRUPTION_SHIELD, {ignore_energy=true})
-				is_shield = true
+				if target:dispel(target.T_DISRUPTION_SHIELD, who) then
+					is_shield = true
+				end
 			end
 			if is_shield == true then
 				game.logSeen(target, "%s's magical shields are shattered!", target:getName():capitalize())
diff --git a/game/modules/tome/data/quests/high-peak.lua b/game/modules/tome/data/quests/high-peak.lua
index 15a797570f6e368050fd5527b86dadb703e8a9b6..2d04b87f43d689b7bd00960469466b916a445488 100644
--- a/game/modules/tome/data/quests/high-peak.lua
+++ b/game/modules/tome/data/quests/high-peak.lua
@@ -156,7 +156,7 @@ function win(self, how)
 		pwinner.ai_state = {talent_in=1, ai_move="move_astar"}
 		pwinner.faction="enemies"
 		pwinner.life = pwinner.max_life
-		pwinner:removeEffectsFilter(function() return true end, 9999, true, true)
+		pwinner:removeEffectsFilter(pwinner, function() return true end, 9999, true, true)
 		-- Remove some talents
 		local tids = {}
 		for tid, _ in pairs(pwinner.talents) do
diff --git a/game/modules/tome/data/quests/staff-absorption.lua b/game/modules/tome/data/quests/staff-absorption.lua
index d897d78cf0da274abc8f118cc40a2b3178d806fe..99670fb4601fa613adc124925fd19aecb8f03415 100644
--- a/game/modules/tome/data/quests/staff-absorption.lua
+++ b/game/modules/tome/data/quests/staff-absorption.lua
@@ -78,7 +78,7 @@ start_ambush = function(self, who)
 
 		-- Protect from other hits on the same turn
 		self:setEffect(self.EFF_DAMAGE_SHIELD, 3, {power=1000000})
-		self:removeEffectsFilter{status="detrimental"}
+		self:removeEffectsFilter(self, {status="detrimental"})
 
 		local carry, o, item, inven_id = game.party:findInAllInventoriesBy("define_as", "STAFF_ABSORPTION")
 		if carry and o then
diff --git a/game/modules/tome/data/talents/celestial/guardian.lua b/game/modules/tome/data/talents/celestial/guardian.lua
index dc86ffa761fa6b67a1df8f78559488e125f49e96..8d77b5c9e75f9c983bff4efd3532ba26fd744c6a 100644
--- a/game/modules/tome/data/talents/celestial/guardian.lua
+++ b/game/modules/tome/data/talents/celestial/guardian.lua
@@ -212,7 +212,7 @@ newTalent{
 		if hit then self:talentCooldownFilter(nil, 1, t.getCooldownReduction(self, t), true) end
 
 		local hit2 = self:attackTargetWith(target, shield_combat, DamageType.LIGHT, t.getShieldDamage(self, t))
-		if hit2 then self:removeEffectsFilter({status = "detrimental"}, t.getDebuff(self, t)) end
+		if hit2 then self:removeEffectsFilter(self, {status = "detrimental"}, t.getDebuff(self, t)) end
 
 		return true
 	end,
diff --git a/game/modules/tome/data/talents/chronomancy/energy.lua b/game/modules/tome/data/talents/chronomancy/energy.lua
index 8dbdc28756d8fa9799e73c3290508bc5304eb8d9..1bb2d53e62014e7b0b9c5a9cd54650f0a3d69a95 100644
--- a/game/modules/tome/data/talents/chronomancy/energy.lua
+++ b/game/modules/tome/data/talents/chronomancy/energy.lua
@@ -186,7 +186,7 @@ newTalent{
 		local target = game.level.map(x, y, Map.ACTOR)
 		if not x or not y or not target then return nil end
 
-		target:setEffect(target.EFF_ENTROPY, t.getDuration(self, t), {apply_power=getParadoxSpellpower(self, t)})
+		target:setEffect(target.EFF_ENTROPY, t.getDuration(self, t), {src=self, apply_power=getParadoxSpellpower(self, t)})
 
 		game:playSoundNear(self, "talents/dispel")
 
diff --git a/game/modules/tome/data/talents/chronomancy/guardian.lua b/game/modules/tome/data/talents/chronomancy/guardian.lua
index 850a8cc51aa6325291564170775695739847a4b2..f89be402fc98d71856c02c5b634e729ebe938020 100644
--- a/game/modules/tome/data/talents/chronomancy/guardian.lua
+++ b/game/modules/tome/data/talents/chronomancy/guardian.lua
@@ -141,7 +141,7 @@ newTalent{
 	end,
 	callbackOnActBase = function(self, t)
 		if rng.percent(t.getPower(self, t)) then
-			if self:removeEffectsFilter({status="detrimental", ignore_crosstier=true}, 1) > 0 then
+			if self:removeEffectsFilter(self, {status="detrimental", ignore_crosstier=true}, 1) > 0 then
 				game.logSeen(self, "#ORCHID#%s has recovered!#LAST#", self:getName():capitalize())
 			end
 		end
diff --git a/game/modules/tome/data/talents/chronomancy/matter.lua b/game/modules/tome/data/talents/chronomancy/matter.lua
index 975bbda37e118cf9ac158eee21905b85f81eab67..d5f020fcf17c9fc3de730c04a4bf4c7766d78281 100644
--- a/game/modules/tome/data/talents/chronomancy/matter.lua
+++ b/game/modules/tome/data/talents/chronomancy/matter.lua
@@ -290,15 +290,16 @@ newTalent{
 			if #effs > 0 then
 				local eff = rng.tableRemove(effs)
 				if eff[1] == "effect" then
-					target:removeEffect(eff[2])
-					game.logSeen(self, "#CRIMSON#%s's beneficial effect was stripped!#LAST#", target:getName():capitalize())
-					if what == "physical" then p.physical[target] = true end
-					if what == "magical" then p.magical[target] = true end
-					
-					-- The Cure achievement
-					local acheive = self.player and not target.training_dummy and target ~= self
-					if acheive then
-						world:gainAchievement("THE_CURE", self)
+					if target:removeEffect(eff[2], self) then
+						game.logSeen(self, "#CRIMSON#%s's beneficial effect was stripped!#LAST#", target:getName():capitalize())
+						if what == "physical" then p.physical[target] = true end
+						if what == "magical" then p.magical[target] = true end
+						
+						-- The Cure achievement
+						local acheive = self.player and not target.training_dummy and target ~= self
+						if acheive then
+							world:gainAchievement("THE_CURE", self)
+						end
 					end
 				end
 			end
diff --git a/game/modules/tome/data/talents/corruptions/blight.lua b/game/modules/tome/data/talents/corruptions/blight.lua
index 2ee53b1c83dd549db126ff0eead5898cf49f3b0c..4b3d2fc1e6f45b769042e967e7c8bb3f15628aa4 100644
--- a/game/modules/tome/data/talents/corruptions/blight.lua
+++ b/game/modules/tome/data/talents/corruptions/blight.lua
@@ -97,11 +97,7 @@ newTalent{
 
 				if self:checkHit(self:combatSpellpower(), target:combatSpellResist(), 0, 95, 5) then
 					target:crossTierEffect(target.EFF_SPELLSHOCKED, self:combatSpellpower())
-					if eff[1] == "effect" then
-						target:removeEffect(eff[2])
-					else
-						target:forceUseTalent(eff[2], {ignore_energy=true})
-					end
+					target:dispel(eff[2], self)
 				end
 			end
 
diff --git a/game/modules/tome/data/talents/corruptions/blood.lua b/game/modules/tome/data/talents/corruptions/blood.lua
index 0c2fa424e16ed50b5364ebcc62cef95acfd2df83..ae523cd60c8d03763f4a4c76e8b1bb44c74ccbed 100644
--- a/game/modules/tome/data/talents/corruptions/blood.lua
+++ b/game/modules/tome/data/talents/corruptions/blood.lua
@@ -143,7 +143,7 @@ newTalent{
 		self:project(tg, x, y, function(px, py)
 			local target = game.level.map(px, py, Map.ACTOR)
 			if not target then return end
-			local eff = target:removeEffectsFilter(function(e) return e.subtype.poison or e.subtype.disease or e.subtype.wound end, 1)
+			local eff = target:removeEffectsFilter(self, function(e) return e.subtype.poison or e.subtype.disease or e.subtype.wound end, 1)
 			if eff and eff > 0 then
 				local dealt = DamageType:get(DamageType.BLIGHT).projector(self, target.x, target.y, DamageType.BLIGHT, damage)
 				target:setEffect(target.EFF_SLOW, 5, {src=self, power=slow})
diff --git a/game/modules/tome/data/talents/corruptions/scourge.lua b/game/modules/tome/data/talents/corruptions/scourge.lua
index 6289b1552aca36aa77aecf2c8bc58ffa7bcd9c2f..b36f31aecb632512ce9acc5ccdf073091edb9e1b 100644
--- a/game/modules/tome/data/talents/corruptions/scourge.lua
+++ b/game/modules/tome/data/talents/corruptions/scourge.lua
@@ -206,7 +206,7 @@ newTalent{
 		if not target or not self:canProject(tg, x, y) then return nil end
 
 		-- Awkward to have this happen first, but part of the point of the talent is to help guarantee any misc disease on hit effects can't be immuned
-		target:removeSustainsFilter(function(e) return e.is_nature end, 2)
+		target:removeSustainsFilter(self, function(e) return e.is_nature end, 2)
 		target:setEffect(target.EFF_CORRUPTING_STRIKE, 2, {})
 
 		DamageType:projectingFor(self, {project_type={talent=t}})
diff --git a/game/modules/tome/data/talents/cunning/traps.lua b/game/modules/tome/data/talents/cunning/traps.lua
index e723838ebc22a370e1440a1d1b0a35679eea4328..78925bff0c60d418400e45505fa07bc665e63613 100644
--- a/game/modules/tome/data/talents/cunning/traps.lua
+++ b/game/modules/tome/data/talents/cunning/traps.lua
@@ -1907,11 +1907,7 @@ newTalent{
 							if #effs == 0 then break end
 							local eff = rng.tableRemove(effs)
 				
-							if eff[1] == "effect" then
-								who:removeEffect(eff[2])
-							else
-								who:forceUseTalent(eff[2], {ignore_energy=true})
-							end
+							who:dispel(eff[2], self.summoner)
 						end
 					end
 					engine.DamageType:get(engine.DamageType.MANABURN).projector(self.summoner, px, py, engine.DamageType.MANABURN, self.dam)
diff --git a/game/modules/tome/data/talents/cursed/one-with-shadows.lua b/game/modules/tome/data/talents/cursed/one-with-shadows.lua
index d11a73086b5e6157a0efdb1d209e09d5a7e5cf0f..5b6a1407abe10654d64c20bad6d77c9dda091ca5 100644
--- a/game/modules/tome/data/talents/cursed/one-with-shadows.lua
+++ b/game/modules/tome/data/talents/cursed/one-with-shadows.lua
@@ -117,7 +117,7 @@ newTalent{
 		target:move(sx, sy, true)
 		self:move(tx, ty, true)
 
-		self:removeEffectsFilter(function(t) return (t.type == "physical" or t.type == "magical") and t.status == "detrimental" end, t.getNb(self, t))
+		self:removeEffectsFilter(self, function(t) return (t.type == "physical" or t.type == "magical") and t.status == "detrimental" end, t.getNb(self, t))
 
 		return true
 	end,
diff --git a/game/modules/tome/data/talents/gifts/antimagic.lua b/game/modules/tome/data/talents/gifts/antimagic.lua
index 7f0593d2af6eb15f9742f2965623f9f00af27b85..66fc13d0397798f7e64ca98cf9e95d83ed9ae954 100644
--- a/game/modules/tome/data/talents/gifts/antimagic.lua
+++ b/game/modules/tome/data/talents/gifts/antimagic.lua
@@ -199,7 +199,7 @@ newTalent{
 			DamageType:get(DamageType.MANABURN).projector(self, px, py, DamageType.MANABURN, base)
 		
 			if self:knowTalent(self.T_ANTIMAGIC_ADEPT) then
-				target:removeSustainsFilter(function(o)
+				target:removeSustainsFilter(self, function(o)
 					if o.is_spell then return true else return false end
 				end, 4)
 			end
diff --git a/game/modules/tome/data/talents/gifts/eyals-fury.lua b/game/modules/tome/data/talents/gifts/eyals-fury.lua
index 9f8433b6f92bda15b29a5aedc0c9a5ed5c3b0f25..4ca385928f97dc9e8329f2472e6e777fb697b0ff 100644
--- a/game/modules/tome/data/talents/gifts/eyals-fury.lua
+++ b/game/modules/tome/data/talents/gifts/eyals-fury.lua
@@ -99,7 +99,7 @@ newTalent{
 	getDuration = function(self, t) return 5 end,
 	getDamage = function(self, t) return self:combatTalentMindDamage(t, 10, 120) end,
 	getChance = function(self, t) return self:combatTalentLimit(t, 100, 20, 40) end, --Limit < 100%
-	removeEffect = function(target) -- remove one random beneficial magical effect or sustain
+	removeEffect = function(self, target) -- remove one random beneficial magical effect or sustain
 	-- Go through all beneficial magical effects
 		local effs = {}
 		for eff_id, p in pairs(target.tmp) do
@@ -119,11 +119,7 @@ newTalent{
 		if #effs == 0 then return end
 		local eff = rng.tableRemove(effs)
 
-		if eff[1] == "effect" then
-			target:removeEffect(eff[2])
-		else
-			target:forceUseTalent(eff[2], {ignore_energy=true})
-		end
+		target:dispel(eff[2], self)
 	end,
 	action = function(self, t)
 		local tg = self:getTalentTarget(t)
@@ -144,7 +140,7 @@ newTalent{
 						act = game.level.map(i, j, engine.Map.ACTOR)
 						if act then
 							if rng.percent(eff.chance) then
-								eff.removeEffect(act)
+								eff.removeEffect(eff.src, act)
 							end
 						end
 					end
diff --git a/game/modules/tome/data/talents/gifts/mucus.lua b/game/modules/tome/data/talents/gifts/mucus.lua
index 2ad4661de3ca4a7f496da963d38831aaa0d31c59..bf888fb347253d4117f70ee3e265055ef0555312 100644
--- a/game/modules/tome/data/talents/gifts/mucus.lua
+++ b/game/modules/tome/data/talents/gifts/mucus.lua
@@ -299,7 +299,7 @@ newTalent{
 			game.logPlayer(self, "You can only Oozewalk from one area of mucus to another.")
 			return nil 
 		end
-		self:removeEffectsFilter(t.effectFilter, t.getNb(self, t))
+		self:removeEffectsFilter(self, t.effectFilter, t.getNb(self, t))
 
 		game.level.map:particleEmitter(self.x, self.y, 1, "slime")
 		self:move(x, y, true)
diff --git a/game/modules/tome/data/talents/misc/inscriptions.lua b/game/modules/tome/data/talents/misc/inscriptions.lua
index 51505d068750001fe7bf12eb5138868183d8f1db..d0f50cf242acba4aa96713363b7275b2d6f3156c 100644
--- a/game/modules/tome/data/talents/misc/inscriptions.lua
+++ b/game/modules/tome/data/talents/misc/inscriptions.lua
@@ -113,9 +113,9 @@ newInscription{
 		self:attr("disable_ancestral_life", -1)
 		self:attr("allow_on_heal", -1)
 
-		self:removeEffectsFilter(function(e) return e.subtype.wound end, 1)
-		self:removeEffectsFilter(function(e) return e.subtype.poison end, 1)
-		self:removeEffectsFilter(function(e) return e.subtype.disease end, 1)
+		self:removeEffectsFilter(self, function(e) return e.subtype.wound end, 1)
+		self:removeEffectsFilter(self, function(e) return e.subtype.poison end, 1)
+		self:removeEffectsFilter(self, function(e) return e.subtype.disease end, 1)
 
 		if core.shader.active(4) then
 			self:addParticles(Particles.new("shader_shield_temp", 1, {toback=true , size_factor=1.5, y=-0.3, img="healgreen", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=2.0}))
@@ -153,9 +153,9 @@ newInscription{
 		local force = {}
 		local removed = 0
 
-		removed = target:removeEffectsFilter({types=data.what, subtype={["cross tier"] = true}, status="detrimental"})
+		removed = target:removeEffectsFilter(self, {types=data.what, subtype={["cross tier"] = true}, status="detrimental"})
 		for k,v in pairs(data.what) do
-			removed = removed + target:removeEffectsFilter({type=k, status="detrimental"}, 1)
+			removed = removed + target:removeEffectsFilter(self, {type=k, status="detrimental"}, 1)
 		end
 
 		if removed > 0 then
@@ -952,11 +952,11 @@ newInscription{
 	action = function(self, t)
 		local data = self:getInscriptionData(t.short_name)
 		
-		local crosstiers = self:removeEffectsFilter({subtype={["cross tier"] = true}, status="detrimental"}, 3)
+		local crosstiers = self:removeEffectsFilter(self, {subtype={["cross tier"] = true}, status="detrimental"}, 3)
 		local cleansed = 0
-		cleansed = cleansed + self:removeEffectsFilter({type="physical", status="detrimental"}, 1)
-		cleansed = cleansed + self:removeEffectsFilter({type="magical", status="detrimental"}, 1)
-		cleansed = cleansed + self:removeEffectsFilter({type="mental", status="detrimental"}, 1)
+		cleansed = cleansed + self:removeEffectsFilter(self, {type="physical", status="detrimental"}, 1)
+		cleansed = cleansed + self:removeEffectsFilter(self, {type="magical", status="detrimental"}, 1)
+		cleansed = cleansed + self:removeEffectsFilter(self, {type="mental", status="detrimental"}, 1)
 
 		if crosstiers == 0 and cleansed == 0 then return nil end
 
@@ -1006,7 +1006,7 @@ newInscription{
 		if not (x and y) or not target or not self:canProject(tg, x, y) then return nil end
 
 		if self:reactionToward(target) < 0 then
-			target:removeSustainsFilter(function(o)
+			target:removeSustainsFilter(self, function(o)
 				if o.type == "magical" or o.is_spell then
 					if o.status and o.status == "detrimental" then return false end
 					return true
@@ -1015,7 +1015,7 @@ newInscription{
 			end,
 			8)
 		else
-			target:removeEffectsFilter({type="magical", status="detrimental"}, 999)
+			target:removeEffectsFilter(self, {type="magical", status="detrimental"}, 999)
 		end
 
 		game:playSoundNear(self, "talents/spell_generic")
@@ -1252,7 +1252,7 @@ newInscription{
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
 		self:project(tg, x, y, DamageType.ICE, data.power + data.inc_stat, {type="freeze"})
-		self:removeEffectsFilter({status="detrimental", type="mental", ignore_crosstier=true}, 1)
+		self:removeEffectsFilter(self, {status="detrimental", type="mental", ignore_crosstier=true}, 1)
 		game:playSoundNear(self, "talents/ice")
 		attack_rune(self, t.id)
 		return true
@@ -1301,7 +1301,7 @@ newInscription{
 		self:project(tg, x, y, DamageType.FIREBURN, {dur=5, initial=0, dam=data.power + data.inc_stat})
 		local _ _, x, y = self:canProject(tg, x, y)
 		game.level.map:particleEmitter(self.x, self.y, tg.radius, "flamebeam", {tx=x-self.x, ty=y-self.y})
-		self:removeEffectsFilter({status="detrimental", type="physical", ignore_crosstier=true}, 1)
+		self:removeEffectsFilter(self, {status="detrimental", type="physical", ignore_crosstier=true}, 1)
 		game:playSoundNear(self, "talents/fire")
 		attack_rune(self, t.id)
 		return true
@@ -1517,7 +1517,7 @@ newInscription{
 		local x, y = self:getTarget(tg)
 		if not x or not y then return nil end
 		self:projectile(tg, x, y, DamageType.INSIDIOUS_POISON, {dam=data.power + data.inc_stat, dur=7, heal_factor=data.heal_factor}, {type="slime"})
-		self:removeEffectsFilter({status="detrimental", type="magical", ignore_crosstier=true}, 1)
+		self:removeEffectsFilter(self, {status="detrimental", type="magical", ignore_crosstier=true}, 1)
 		game:playSoundNear(self, "talents/slime")
 		return true
 	end,
diff --git a/game/modules/tome/data/talents/misc/objects.lua b/game/modules/tome/data/talents/misc/objects.lua
index b241827c0b64f407be1ff6db84fb4fc753df5faa..075860a03715cb7d3194354537170bb61680194d 100644
--- a/game/modules/tome/data/talents/misc/objects.lua
+++ b/game/modules/tome/data/talents/misc/objects.lua
@@ -414,11 +414,7 @@ newTalent{
 			end
 				local eff = rng.tableRemove(effs)
 				if eff then
-					if eff[1] == "effect" then
-						target:removeEffect(eff[2])
-					else
-						target:forceUseTalent(eff[2], {ignore_energy=true})
-					end
+					target:dispel(eff[2], self)
 				end
 			end
 			if self:getTalentLevel(t)>=5 then
diff --git a/game/modules/tome/data/talents/misc/races.lua b/game/modules/tome/data/talents/misc/races.lua
index 55b8dd79fb504ff771da79c7cfab791472ae0a43..22dbdcbb801ef78e243381a1260c1a8d5bffe9ef 100644
--- a/game/modules/tome/data/talents/misc/races.lua
+++ b/game/modules/tome/data/talents/misc/races.lua
@@ -755,7 +755,7 @@ newTalent{
 		if self:isTalentCoolingDown(t) then return end
 		if not ( (self.life - dam) < (self.max_life * 0.5) ) then return end
 		
-		local nb = self:removeEffectsFilter({status = "detrimental", type = "mental"}, t.getDebuff(self, t))
+		local nb = self:removeEffectsFilter(self, {status = "detrimental", type = "mental"}, t.getDebuff(self, t))
 		if nb > 0 then
 			game.logSeen(self, "#CRIMSON#%s roars with rage shaking off %d mental debuffs!", self:getName():capitalize(), nb)
 			self:startTalentCooldown(t)
diff --git a/game/modules/tome/data/talents/psionic/psi-fighting.lua b/game/modules/tome/data/talents/psionic/psi-fighting.lua
index 6dd3c1ed860a2634dd3109eaac2fd831d7c6a457..897c9b81620ecf62d7a2f0325f6c8e31f031cb3e 100644
--- a/game/modules/tome/data/talents/psionic/psi-fighting.lua
+++ b/game/modules/tome/data/talents/psionic/psi-fighting.lua
@@ -183,8 +183,9 @@ newTalent{
 				local eff = rng.tableRemove(effs)
 
 				if eff[1] == "effect" then
-					game.logSeen(self, "#CRIMSON#%s shatters %s shield!", self:getName():capitalize(), target:getName())
-					target:removeEffect(eff[2])
+					if target:dispel(eff[2], self) then
+						game.logSeen(self, "#CRIMSON#%s shatters %s shield!", self:getName():capitalize(), target:getName())
+					end
 				end
 			end
 		end
diff --git a/game/modules/tome/data/talents/spells/acid-alchemy.lua b/game/modules/tome/data/talents/spells/acid-alchemy.lua
index b5f173c31dcbbf04507c819e0cf4edf3b5bf3c33..1f8a5307bbceeee8596e3c7df20e8def56047d16 100644
--- a/game/modules/tome/data/talents/spells/acid-alchemy.lua
+++ b/game/modules/tome/data/talents/spells/acid-alchemy.lua
@@ -169,11 +169,7 @@ newTalent{
 
 				if self:checkHit(self:combatSpellpower(), target:combatSpellResist(), 0, 95, 5) then
 					target:crossTierEffect(target.EFF_SPELLSHOCKED, self:combatSpellpower())
-					if eff[1] == "effect" then
-						target:removeEffect(eff[2])
-					else
-						target:forceUseTalent(eff[2], {ignore_energy=true})
-					end
+					target:dispel(eff[2], self)
 				end
 			end
 
diff --git a/game/modules/tome/data/talents/spells/aether.lua b/game/modules/tome/data/talents/spells/aether.lua
index fc27d309218a5079521791793fdc6a4808654bc2..cc3d94da9183a3ecf5b571718aa92a9a05995d05 100644
--- a/game/modules/tome/data/talents/spells/aether.lua
+++ b/game/modules/tome/data/talents/spells/aether.lua
@@ -247,7 +247,7 @@ newTalent{
 		local aegis
 		self:setEffect(self.EFF_AETHER_AVATAR, t.getNb(self, t), {})
 		if self:isTalentActive(self.T_PURE_AETHER) and self:getTalentLevel(self.T_PURE_AETHER) >= 5 then
-			self:removeEffectsFilter({type="physical", status="detrimental"}, self:callTalent(self.T_PURE_AETHER, "getNbRemove"))
+			self:removeEffectsFilter(self, {type="physical", status="detrimental"}, self:callTalent(self.T_PURE_AETHER, "getNbRemove"))
 		end
 		game:playSoundNear(self, "talents/arcane")
 		return true
diff --git a/game/modules/tome/data/talents/spells/meta.lua b/game/modules/tome/data/talents/spells/meta.lua
index b0594664cf37541facf255b2283958014e8dd604..88fe4e6326575f5d74aed4ed786ffde7c743ae5e 100644
--- a/game/modules/tome/data/talents/spells/meta.lua
+++ b/game/modules/tome/data/talents/spells/meta.lua
@@ -101,11 +101,7 @@ newTalent{
 			if #effs == 0 then break end
 			local eff = rng.tableRemove(effs)
 
-			if eff[1] == "effect" then
-				target:removeEffect(eff[2])
-			else
-				target:forceUseTalent(eff[2], {ignore_energy=true})
-			end
+			target:dispel(eff[2], self)
 		end
 		game:playSoundNear(self, "talents/spell_generic")
 		return true
diff --git a/game/modules/tome/data/talents/techniques/unarmed-discipline.lua b/game/modules/tome/data/talents/techniques/unarmed-discipline.lua
index bd496bed43d4ea59394e2e0023941bc6aeb2afba..3e29e09e550395bcb25c29f45b8e2e5c5c1ce327 100644
--- a/game/modules/tome/data/talents/techniques/unarmed-discipline.lua
+++ b/game/modules/tome/data/talents/techniques/unarmed-discipline.lua
@@ -75,7 +75,7 @@ newTalent{
 		talents = table.keys(talents)
 		while #talents > 0 and nb > 0 do
 			local tid = rng.tableRemove(talents)
-			target:forceUseTalent(tid, {ignore_energy=true})
+			target:dispel(tid, self)
 			nb = nb - 1
 			local tt = self:getTalentFromId(tid)
 			if tt.is_spell then dispeltypes.spell = true
diff --git a/game/modules/tome/data/talents/uber/const.lua b/game/modules/tome/data/talents/uber/const.lua
index 3ce4e782f7b595b75b55060c820d095b336048ed..3a410cf818a3295a9337df04fede6209b99af14d 100644
--- a/game/modules/tome/data/talents/uber/const.lua
+++ b/game/modules/tome/data/talents/uber/const.lua
@@ -159,7 +159,7 @@ uberTalent{
 			self:addParticles(Particles.new("shader_shield_temp", 1, {toback=true , size_factor=1.5, y=-0.3, img="healgreen", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=2.0, circleDescendSpeed=3.5}))
 			self:addParticles(Particles.new("shader_shield_temp", 1, {toback=false, size_factor=1.5, y=-0.3, img="healgreen", life=25}, {type="healing", time_factor=2000, beamsCount=20, noup=1.0, circleDescendSpeed=3.5}))
 		end
-		self:removeEffectsFilter({status="detrimental", type="magical"}, 10)
+		self:removeEffectsFilter(self, {status="detrimental", type="magical"}, 10)
 		self:removeEffect(self.EFF_FUNGAL_BLOOD)
 		return true
 	end,
diff --git a/game/modules/tome/data/talents/uber/cun.lua b/game/modules/tome/data/talents/uber/cun.lua
index 8541190a8440b5d643ceb5db6dd02fea98849663..0b5bd0567369f5b2f96897daafe314a3acece969 100644
--- a/game/modules/tome/data/talents/uber/cun.lua
+++ b/game/modules/tome/data/talents/uber/cun.lua
@@ -302,7 +302,7 @@ uberTalent{
 			if damtype == DamageType.PHYSICAL and not self:hasProc("elemental_surge_physical") then
 				self:setProc("elemental_surge_physical", true, 10)
 				game.logSeen(self, "%s surges with earthen power!", self:getName():capitalize())
-				self:removeEffectsFilter({status="detrimental", type="physical", ignore_crosstier=true}, 1)
+				self:removeEffectsFilter(self, {status="detrimental", type="physical", ignore_crosstier=true}, 1)
 				self:setEffect(self.EFF_ELEMENTAL_SURGE_PHYSICAL, 2, {})
 				t.doProject(self, t, damtype, "ball_earth")
 			elseif damtype == DamageType.ARCANE and not self:hasProc("elemental_surge_arcane") then
@@ -333,7 +333,7 @@ uberTalent{
 			elseif damtype == DamageType.NATURE and not self:hasProc("elemental_surge_nature") then
 				self:setProc("elemental_surge_nature", true, 10)
 				game.logSeen(self, "%s surges with #LIGHT_GREEN#natural#LAST# power!", self:getName():capitalize())
-				self:removeEffectsFilter({status="detrimental", type="magical", ignore_crosstier=true}, 1)
+				self:removeEffectsFilter(self, {status="detrimental", type="magical", ignore_crosstier=true}, 1)
 				self:setEffect(self.EFF_ELEMENTAL_SURGE_NATURE, 2, {})
 				t.doProject(self, t, damtype, "slime")
 			end
diff --git a/game/modules/tome/data/talents/uber/str.lua b/game/modules/tome/data/talents/uber/str.lua
index c38985c1184328c435d303986c1ccee71c73fd14..09d10c421940722fadff9ad7767e253d824ced94 100644
--- a/game/modules/tome/data/talents/uber/str.lua
+++ b/game/modules/tome/data/talents/uber/str.lua
@@ -58,7 +58,7 @@ uberTalent{
 			self:setMoveAnim(ox, oy, 8, 5)
 		end
 
-		self:removeEffectsFilter({subtype={stun=true, daze=true, pin=true, pinned=true, pinning=true}}, 50)
+		self:removeEffectsFilter(self, {subtype={stun=true, daze=true, pin=true, pinned=true, pinning=true}}, 50)
 
 		self:project(tg, self.x, self.y, function(px, py, tg, self)
 			local target = game.level.map(px, py, Map.ACTOR)
diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua
index 235d75dce9b9d76462561bd4c507331aa9d949c8..439577f2db4367dba40f40b285c94a86c319ec28 100644
--- a/game/modules/tome/data/timed_effects/magical.lua
+++ b/game/modules/tome/data/timed_effects/magical.lua
@@ -447,7 +447,7 @@ newEffect{
 	deactivate = function(self, eff)
 	end,
 	on_timeout = function(self, eff)
-		local cleanse = self:removeEffectsFilter({type="physical", status="detrimental"}, 1)
+		local cleanse = self:removeEffectsFilter(self, {type="physical", status="detrimental"}, 1)
 		if cleanse > 0 then eff.dur = eff.dur + 1 end
 	end,
 }
@@ -2372,7 +2372,7 @@ newEffect{
 		if #effs > 0 then
 			local eff = rng.tableRemove(effs)
 			if eff[1] == "effect" then
-				self:removeEffect(eff[2])
+				self:dispel(eff[2], eff.src)
 			end
 		end
 
@@ -3710,7 +3710,7 @@ newEffect{
 	status = "detrimental",
 	parameters = {},
 	on_timeout = function(self, eff)
-		self:removeSustainsFilter(nil, 1)
+		self:removeSustainsFilter(eff.src, nil, 1)
 	end,
 	activate = function(self, eff)
 		if core.shader.allow("adv") then
diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua
index 9b7e7e21ee550a6d17b8da88610fafbbdbe9a9d5..356ff70b3cd29d6c3f4aafc4f93672094b6b87a2 100644
--- a/game/modules/tome/data/timed_effects/mental.lua
+++ b/game/modules/tome/data/timed_effects/mental.lua
@@ -1641,7 +1641,7 @@ newEffect{
 		if rng.percent(chance) then
 			if self:attr("sleep") or self:checkHit(eff.src:combatMindpower(), self:combatMentalResist(), 0, 95, 5) then
 				t.summon_inner_demons(eff.src, self, t)
-				self:removeEffectsFilter({subtype={["sleep"] = true}}, 3) -- Allow the player to actually react to one of the biggest threats in the game before 50 more spawn
+				self:removeEffectsFilter(self, {subtype={["sleep"] = true}}, 3) -- Allow the player to actually react to one of the biggest threats in the game before 50 more spawn
 			else
 				eff.dur = 0
 			end
diff --git a/game/modules/tome/data/timed_effects/physical.lua b/game/modules/tome/data/timed_effects/physical.lua
index e8b5eec01e6cb5e99e4d98a18cae6a05451a36d8..6873ab91e6a79b8f4f81b0dda09ffacb8b2989c5 100644
--- a/game/modules/tome/data/timed_effects/physical.lua
+++ b/game/modules/tome/data/timed_effects/physical.lua
@@ -2542,11 +2542,7 @@ newEffect{
 
 			if #effs > 0 then
 				local eff = rng.tableRemove(effs)
-				if eff[1] == "effect" then
-					self:removeEffect(eff[2])
-				else
-					self:forceUseTalent(eff[2], {ignore_energy=true})
-				end
+				self:dispel(eff[2], eff.src)
 			end
 		end
 		self:setEffect(self.EFF_DISTORTION, 2, {power=eff.distort})
diff --git a/game/modules/tome/data/zones/dreams/grids.lua b/game/modules/tome/data/zones/dreams/grids.lua
index 323e63aa6c0281aae44b4d020ae4d6412f70e266..ff8925fac20e99a7026d9e53349d78d30cdd3a6c 100644
--- a/game/modules/tome/data/zones/dreams/grids.lua
+++ b/game/modules/tome/data/zones/dreams/grids.lua
@@ -85,7 +85,7 @@ newEntity{
 			local g = game.zone.grid_list.BAMBOO_HUT_FLOOR:clone()
 			game.zone:addEntity(game.level, g, "terrain", x, y)
 			who:heal(100, self)
-			who:removeEffectsFilter{status="detrimental"}
+			who:removeEffectsFilter(self, {status="detrimental"})
 			game.logPlayer(who, "You touch the dreamstone and it disappears. You feel better.")
 		end
 		return true