diff --git a/game/modules/tome/data/gfx/particles/blood_trail.lua b/game/modules/tome/data/gfx/particles/blood_trail.lua
new file mode 100644
index 0000000000000000000000000000000000000000..f4ece9a47196aa4c0b34722e27d139fd53aa8ef6
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/blood_trail.lua
@@ -0,0 +1,66 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009 - 2019 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 sizeratio = 64 / engine.Map.tile_w
+
+local dir = dir
+local dist = (range or 1) * engine.Map.tile_w
+
+local life = 32
+local points = {}
+points[#points+1] = {size=4, x=0, y=0, prev=-1, angle=0, vel=0}
+for i = 1, 16 do
+	local x = rng.range(-2, 2) / sizeratio
+	local y = -dist / 16 * i
+	-- local si = math.sqrt(i) * 0.8
+	local size
+	if i <= 4 then size = 16 - i * 3
+	else size = points[#points].size * 0.92
+	end
+	points[#points+1] = {angle=-math.pi/2, vel=y/life/sizeratio * ((grab and 1) or -1), size=(i==16) and 1 or size, x=x, y=y, prev=#points-1}
+end
+local nbp = #points
+
+return { engine=core.particles.ENGINE_LINES, system_rotation=dir, generator = function()
+	local p = table.remove(points, 1)
+	if not p then return nil end
+
+	return {
+		life = life, trail=p.prev,
+		size = p.size, sizev = 0, sizea = 0,
+
+		x = p.x, xv = 0, xa = 0,
+		y = p.y, yv = 0, ya = 0,
+		dir = p.angle, dirv = 0, dira = 0,
+		vel = p.vel, velv = 0, vela = 0,
+
+		r = 1, rv = 0, ra = 0,
+		g = 1, gv = 0, ga = 0,
+		b = 1, bv = 0, ba = 0,
+		a = 0.5, av = 0, aa = -1/(life^2)*2,
+	}
+end, },
+function(self)
+	if nbp > 0 then
+		nbp = nbp - self.ps:emit(nbp)
+	end
+end,
+nbp, "particles_images/"..img
diff --git a/game/modules/tome/data/gfx/particles/dripping_hands.lua b/game/modules/tome/data/gfx/particles/dripping_hands.lua
new file mode 100644
index 0000000000000000000000000000000000000000..fef9b9bf04d4f754eb6e69be06eac0d8b27dde6f
--- /dev/null
+++ b/game/modules/tome/data/gfx/particles/dripping_hands.lua
@@ -0,0 +1,59 @@
+-- ToME - Tales of Maj'Eyal
+-- Copyright (C) 2009 - 2019 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 = 64
+toback = false
+can_shift = true
+
+local r = r or 168
+local g = g or 10
+local b = b or 10
+
+local run = true
+return { generator = function()
+	local ad = rng.range(0, 360)
+	local a = math.rad(ad)
+	local dir = math.rad(90)
+	local r = rng.range(18, 22)
+	local dirchance = rng.chance(2)
+	local x = rng.range(-6, 6) + x * 64
+	local y = rng.range(-6, -2) + y * 64
+
+	return {
+		trail = 2,
+		life = 32,
+		size = rng.range(6, 12), sizev = 0, sizea = -0.016,
+
+		x = x, xv = 0, xa = 0,
+		y = y, yv = 0.2, ya = 0.04,
+		dir = 0, dirv = 0, dira = 0,
+		vel = 0, velv = 0, vela = 0,
+
+		r = r/255, rv = 0, ra = 0,
+		g = g/255, gv = 0, ga = 0,
+		b = b/255, bv = 0, ba = 0,
+		a = 1.0, av = -1.0/32, aa = 0,
+	}
+end, },
+function(self)
+	if run then self.ps:emit(1) end
+	run = not run
+end,
+32,
+"particles_images/apply_poison"..rng.range(1, 4)
diff --git a/game/modules/tome/data/gfx/particles_images/blood_rush_mark.png b/game/modules/tome/data/gfx/particles_images/blood_rush_mark.png
new file mode 100644
index 0000000000000000000000000000000000000000..9fe0fef97c0505cdd6881e94cfeec59bb4c674d5
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_rush_mark.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/blood_sigil_dark.png b/game/modules/tome/data/gfx/particles_images/blood_sigil_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..179b7f5d65d9dfdcdd2a9c6b0127a5afbb8cf708
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_sigil_dark.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/blood_sigil_light.png b/game/modules/tome/data/gfx/particles_images/blood_sigil_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..4a337abd87e45ea6a8d46d700156ec6897337b9c
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_sigil_light.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/blood_trail_segment.png b/game/modules/tome/data/gfx/particles_images/blood_trail_segment.png
new file mode 100644
index 0000000000000000000000000000000000000000..8aefff3dfaa11e1a0259b6d3310002c23d0f8a09
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_trail_segment.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thick.png b/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thick.png
new file mode 100644
index 0000000000000000000000000000000000000000..8b105a4f83e93f8cea922c67c2784ca7adf56e2d
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thick.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thin.png b/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thin.png
new file mode 100644
index 0000000000000000000000000000000000000000..fc71f4f82e0275836b26e70b9c66f2f461298151
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/blood_trail_segment_thin.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/devourer_shield.png b/game/modules/tome/data/gfx/particles_images/devourer_shield.png
new file mode 100644
index 0000000000000000000000000000000000000000..85ccfc99edfce0e90123199a5165726a5f65ab0a
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/devourer_shield.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/mark_vampire.png b/game/modules/tome/data/gfx/particles_images/mark_vampire.png
new file mode 100644
index 0000000000000000000000000000000000000000..d1efe38a11226ed4006768b3512db6a3433e5acd
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/mark_vampire.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/spiral_dark.png b/game/modules/tome/data/gfx/particles_images/spiral_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..e8ca7c9b1767f4a5de319eb695a6c9d4bb9253bc
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/spiral_dark.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/spiral_light.png b/game/modules/tome/data/gfx/particles_images/spiral_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..46d72a3dcea1df3879dadf03b143a9473d47e2d6
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/spiral_light.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/sun_sigil_dark.png b/game/modules/tome/data/gfx/particles_images/sun_sigil_dark.png
new file mode 100644
index 0000000000000000000000000000000000000000..6ccd6ceafcda5da9d7814a5e6188cc38ad5c6f90
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/sun_sigil_dark.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/sun_sigil_light.png b/game/modules/tome/data/gfx/particles_images/sun_sigil_light.png
new file mode 100644
index 0000000000000000000000000000000000000000..bb45234200a2ab727ce6020f1040be4b3036eb19
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/sun_sigil_light.png differ
diff --git a/game/modules/tome/data/gfx/particles_images/vampire_circle.png b/game/modules/tome/data/gfx/particles_images/vampire_circle.png
new file mode 100644
index 0000000000000000000000000000000000000000..04f74329964c4ec5ad3f383255e92d7d34949b71
Binary files /dev/null and b/game/modules/tome/data/gfx/particles_images/vampire_circle.png differ
diff --git a/game/modules/tome/data/talents/celestial/dark-sun.lua b/game/modules/tome/data/talents/celestial/dark-sun.lua
index 13315b55cd206b12520c0a00b2e783043d078fb8..8a9b9c1ab0f1ceb1b4f3dc357cd7a43bf41cd1a6 100644
--- a/game/modules/tome/data/talents/celestial/dark-sun.lua
+++ b/game/modules/tome/data/talents/celestial/dark-sun.lua
@@ -20,7 +20,7 @@
 local Object = require "mod.class.Object"
 
 newTalent{
-	name = "Collapse", short_name = "FALLEN_BREACH",
+	name = "Collapse",
 	type = {"celestial/dark-sun", 1},
 	require = divi_str_req_high1,
 	points = 5,
diff --git a/game/modules/tome/data/talents/celestial/darkside.lua b/game/modules/tome/data/talents/celestial/darkside.lua
index 1034a1492920c3fc95354603dfd1ecb2be194289..86d854f7f7d28d5e93cb66447e915fef80d63bae 100644
--- a/game/modules/tome/data/talents/celestial/darkside.lua
+++ b/game/modules/tome/data/talents/celestial/darkside.lua
@@ -104,7 +104,7 @@ newTalent{
 		if not x or not y then return nil end
 		local _ _, x, y = self:canProject(tg, x, y)
 		
-		game.level.map:particleEmitter(self.x, self.y, 1, "temporal_teleport")
+		game.level.map:particleEmitter(self.x, self.y, 1, "circle", {oversize=0.7, a=187, limit_life=8, appear=8, speed=4, img="spiral_dark", radius=1})
 		
 		if not self:teleportRandom(x, y, 0) then
 			game.logSeen(self, "%s's teleportation fizzles!", self.name:capitalize())
@@ -114,7 +114,7 @@ newTalent{
 			local btg = t.getBlastTarget(self, t)
 			local dam = self:spellCrit(t.getDamage(self, t))
 			self:project(btg, self.x, self.y, DamageType.LIGHT, dam)
-			game.level.map:particleEmitter(self.x, self.y, 1, "temporal_teleport")
+			game.level.map:particleEmitter(self.x, self.y, 1, "circle", {oversize=0.7, a=187, limit_life=8, appear=8, speed=4, img="spiral_light", radius=1})
 		end
 		
 		game:playSoundNear(self, "talents/fallen_stardust")
diff --git a/game/modules/tome/data/talents/cursed/bloodstained.lua b/game/modules/tome/data/talents/cursed/bloodstained.lua
index c7ef439a00a3337e6e1c01028502dca0ff85b93b..d82d263d33ae269f55388352f10bcbb8a514a576 100644
--- a/game/modules/tome/data/talents/cursed/bloodstained.lua
+++ b/game/modules/tome/data/talents/cursed/bloodstained.lua
@@ -179,6 +179,9 @@ newTalent{
 	on_unlearn = function(self, t) self:unlearnTalent(self.T_BLOOD_CLOT) end,
 	activate = function(self, t)
 		local ret = {}
+		local h1x, h1y = self:attachementSpot("hand1", true) if h1x then self:talentParticles(ret, {type="dripping_hands", args={x=h1x, y=h1y, r=168, b=13}}) end
+		local h2x, h2y = self:attachementSpot("hand2", true) if h2x then self:talentParticles(ret, {type="dripping_hands", args={x=h2x, y=h2y, r=168, b=13}}) end
+		self:talentParticles(ret, {type="apply_poison", args={}})
 		return ret
 	end,
 	deactivate = function(self, t, p)
diff --git a/game/modules/tome/data/talents/cursed/crimson-templar.lua b/game/modules/tome/data/talents/cursed/crimson-templar.lua
index 9fa29c32da7b5cd0672d7ff9e86e7e9976ef7be5..173a132dcdb5c04d9c657768766260fae386af4a 100644
--- a/game/modules/tome/data/talents/cursed/crimson-templar.lua
+++ b/game/modules/tome/data/talents/cursed/crimson-templar.lua
@@ -66,6 +66,10 @@ newTalent{
 				state.no_reflect = nil
 				
 				game:delayedLogDamage(src, self, 0, ("%s(%d shared agony)#LAST#"):tformat(DamageType:get(type).text_color or "#aaaaaa#", displace), false)
+
+				local hx, hy = self:attachementSpot("back", true)
+				local ps = Particles.new("blood_trail", 1, {range=core.fov.distance(self.x, self.y, a.x, a.y), dir=math.deg(math.atan2(a.y-self.y, a.x-self.x)+math.pi/2), img="blood_trail_segment_thin", dx=hx, dy=hy, grab=false})
+				self:addParticles(ps)
 			end
 		end
 		
@@ -103,7 +107,7 @@ newTalent{
 														 DamageType.SOLAR_BLOOD, {dam=self:spellCrit(t.getStrength(self, t)), pow=self:combatSpellpower()},
 														 self:getTalentRadius(t),
 														 5, nil,
-														 MapEffect.new{zdepth=6, overlay_particle={zdepth=6, only_one=true, type="circle", args={appear=8, oversize=0, img="celestial_circle", radius=self:getTalentRadius(t)*2}}, color_br=255, color_bg=187, color_bb=187, alpha=10, effect_shader="shader_images/sunlight_effect.png"},
+														 MapEffect.new{zdepth=6, overlay_particle={zdepth=6, only_one=true, type="circle", args={appear=8, oversize=0, img="sun_sigil_dark", radius=self:getTalentRadius(t)*2}}, color_br=255, color_bg=187, color_bb=187, alpha=10, effect_shader="shader_images/sunlight_effect.png"},
 														 nil, true
 														)
 	end,
@@ -161,7 +165,7 @@ newTalent{
 									 target:setEffect(target.EFF_MARK_OF_THE_VAMPIRE, 20, {src=self, dam=dam, power=t.getBleedIncrease(self, t), apply_power=self:combatSpellpower()})
 													 end)
 		local _ _, _, _, x, y = self:canProject(tg, x, y)
-		game.level.map:particleEmitter(x, y, tg.radius, "circle", {oversize=0.7, g=90, b=100, a=100, limit_life=8, appear=8, speed=2, img="blight_circle", radius=self:getTalentRadius(t)})
+		game.level.map:particleEmitter(x, y, tg.radius, "circle", {oversize=0.7, g=90, b=100, a=100, limit_life=8, appear=8, speed=2, img="vampire_circle", radius=self:getTalentRadius(t)})
 		game:playSoundNear(self, "talents/slime")
 		return true
 	end,
@@ -236,6 +240,9 @@ newTalent{
 										 end
 										 
 										 if bleeding and target:canBe("sleep") then
+											 local hx, hy = self:attachementSpot("back", true)
+											 local ps = Particles.new("blood_trail", 1, {range=core.fov.distance(self.x, self.y, target.x, target.y), dir=math.deg(math.atan2(target.y-self.y, target.x-self.x)+math.pi/2), img="blood_trail_segment_thick", grab=true, dx=hx, dy=hy})
+											 self:addParticles(ps)
 											 target:setEffect(target.EFF_SLEEP, dur+t.getExtension(self, t), {src=self, power = math.ceil(sleepPower * sleepMultiplier * 1.5), contagious=0, waking=is_waking, insomnia=t.getInsomniaPower(self, t), no_ct_effect=true, apply_power=self:combatSpellpower()})
 										 else
 											 game.logSeen(self, "%s resists the sleep!", target.name:capitalize())
diff --git a/game/modules/tome/data/timed_effects/magical.lua b/game/modules/tome/data/timed_effects/magical.lua
index ca65a7db2d388b52547dde3cc905da10357136d0..38b4a9ab1b558aebb24d4f63e9658034f5ba2f6c 100644
--- a/game/modules/tome/data/timed_effects/magical.lua
+++ b/game/modules/tome/data/timed_effects/magical.lua
@@ -5564,6 +5564,10 @@ newEffect{
 		eff.counter = 0
 		local damtype = DamageType.BLACK_HOLE_GRAVITY
 		eff.onhit = self:addTemporaryValue("melee_project", {[damtype] = eff.gravity})
+		if core.shader.active() then
+			self:effectParticles(eff, {type="shader_shield", args={toback=true,  size_factor=1, img="devourer_shield"}, shader={type="rotatingshield", noup=2.0, cylinderRotationSpeed=1.7, appearTime=0.2}})
+			self:effectParticles(eff, {type="shader_shield", args={toback=false, size_factor=1, img="devourer_shield"}, shader={type="rotatingshield", noup=1.0, cylinderRotationSpeed=1.7, appearTime=0.2}})
+		end
 	end,
 	deactivate = function(self, eff)
 		self:removeTemporaryValue("melee_project", eff.onhit)
diff --git a/game/modules/tome/data/timed_effects/mental.lua b/game/modules/tome/data/timed_effects/mental.lua
index 68944e9fa3f839b83b1cb2738905b17db98a9f33..5278f0b11856aadd005d54321f3246ce9bd971c9 100644
--- a/game/modules/tome/data/timed_effects/mental.lua
+++ b/game/modules/tome/data/timed_effects/mental.lua
@@ -3082,5 +3082,9 @@ newEffect{
 	
 	on_gain = function(self, err) return _t"#Target# is doomed!", _t"+Vampire Mark" end,
 	on_lose = function(self, err) return _t"#Target# is free from their doom.", _t"-Vampire Mark" end,
-}
-
+	activate = function(self, eff)
+		self:effectParticles(eff, {type="circle", args={shader=true, oversize=1, a=225, appear=8, speed=0, img="mark_vampire", base_rot=0, radius=0}})
+	end,
+	deactivate = function(self, eff)
+	end,
+}
\ No newline at end of file
diff --git a/game/modules/tome/data/timed_effects/other.lua b/game/modules/tome/data/timed_effects/other.lua
index 784acae5172802bcca5a8e9171811fad809e610e..be19352cccbf18cc131c05a028467b99fe7dd7ae 100644
--- a/game/modules/tome/data/timed_effects/other.lua
+++ b/game/modules/tome/data/timed_effects/other.lua
@@ -4124,8 +4124,12 @@ newEffect{
 	subtype = { status=true, },
 	status = "detrimental",
 	parameters = { },
-	activate = function(self, eff) end,
-	deactivate = function(self, eff) end,
+	activate = function(self, eff) 
+		eff.particle = self:addParticles(Particles.new("circle", 1, {base_rot=1, oversize=1.0, a=200, appear=8, speed=0, img="blood_rush_mark", radius=0}))
+	end,
+	deactivate = function(self, eff)
+		self:removeParticles(eff.particle)
+	end,
 	callbackOnDeath = function(self, eff, src, note)
 		marker = eff.src
 		reduc = eff.dur * 2