diff --git a/code/datums/spell.dm b/code/datums/spell.dm
index 2d514504c81..ef414e9269c 100644
--- a/code/datums/spell.dm
+++ b/code/datums/spell.dm
@@ -40,7 +40,7 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/selection_type = "view" //can be "range" or "view"
var/spell_level = 0 //if a spell can be taken multiple times, this raises
var/level_max = 4 //The max possible level_max is 4
- var/cooldown_min = 0 //This defines what spell quickened four timeshas as a cooldown. Make sure to set this for every spell
+ var/cooldown_min = 0 //This defines what spell quickened four times has as a cooldown. Make sure to set this for every spell
var/overlay = 0
var/overlay_icon = 'icons/obj/wizard.dmi'
diff --git a/code/datums/spells/bloodcrawl.dm b/code/datums/spells/bloodcrawl.dm
new file mode 100644
index 00000000000..0e5db631223
--- /dev/null
+++ b/code/datums/spells/bloodcrawl.dm
@@ -0,0 +1,32 @@
+/obj/effect/proc_holder/spell/bloodcrawl
+ name = "Blood crawl"
+ desc = "Use blood to travel."
+ charge_max = 10
+ clothes_req = 0
+ selection_type = "range"
+ range = 1
+ cooldown_min = 0
+ overlay = null
+ action_icon_state = "bloodcrawl"
+ var/phased = 0
+
+/obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr)
+ for(var/obj/effect/decal/cleanable/target in range(range, get_turf(user)))
+ if(istype(target, /obj/effect/decal/cleanable/blood) || istype(target, /obj/effect/decal/cleanable/trail_holder))
+ perform(target)
+ return
+ revert_cast()
+ user << "You need blood to blood crawl."
+
+/obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr)
+ if(istype(user))
+ if(phased)
+ if(user.phasein(target))
+ phased = 0
+ else
+ user.phaseout(target)
+ phased = 1
+ start_recharge()
+ return
+ revert_cast()
+ user << "You cannot blood crawl."
\ No newline at end of file
diff --git a/code/modules/mob/living/bloodcrawl.dm b/code/modules/mob/living/bloodcrawl.dm
index a58fd4401a4..3f7bfba90cf 100644
--- a/code/modules/mob/living/bloodcrawl.dm
+++ b/code/modules/mob/living/bloodcrawl.dm
@@ -1,94 +1,6 @@
-//Travel through pools of blood. Slaughter Demon powers for everyone!
-
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
-/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
- var/mob/living/kidnapped = null
- var/turf/mobloc = get_turf(src.loc)
- var/turf/bloodloc = get_turf(B.loc)
- if(Adjacent(bloodloc))
- src.notransform = TRUE
- spawn(0)
- src.visible_message("[src] sinks into the pool of blood.")
- playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
- var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
- src.ExtinguishMob()
- if(src.buckled)
- src.buckled.unbuckle_mob()
- if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
- if(istype(src.pulling, /mob/living))
- var/mob/living/victim = src.pulling
- if(victim.stat == CONSCIOUS)
- src.visible_message("[victim] kicks free of the [src] at the last second!")
- else
- victim.loc = holder
- src.visible_message("The [src] drags [victim] into the pool of blood!")
- kidnapped = victim
- src.loc = holder
- src.holder = holder
- if(kidnapped)
- src << "You begin to feast on [kidnapped]. You can not move while you are doing this."
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
- sleep(30)
- if(kidnapped)
- src << "You devour [kidnapped]. Your health is fully restored."
- src.adjustBruteLoss(-1000)
- src.adjustFireLoss(-1000)
- src.adjustOxyLoss(-1000)
- src.adjustToxLoss(-1000)
- kidnapped.ghostize()
- qdel(kidnapped)
- else
- src << "You happily devour...nothing? Your meal vanished at some point!"
- src.notransform = 0
-
-/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
- if(src.notransform)
- src << "Finish eating first!"
- else
- src.loc = B.loc
- src.client.eye = src
- src.visible_message("The [src] rises out of the pool of blood!")
- playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
- qdel(src.holder)
- src.holder = null
-
-/obj/effect/decal/cleanable/blood/CtrlClick(mob/living/user)
- ..()
- if(user.bloodcrawl)
- if(user.holder)
- user.phasein(src)
- else
- user.phaseout(src)
-
-
-/obj/effect/decal/cleanable/trail_holder/CtrlClick(mob/living/user)
- ..()
- if(user.bloodcrawl)
- if(user.holder)
- user.phasein(src)
- else
- user.phaseout(src)
-
-
-
-/turf/CtrlClick(var/mob/living/user)
- ..()
- if(user.bloodcrawl)
- for(var/obj/effect/decal/cleanable/B in src.contents)
- if(istype(B, /obj/effect/decal/cleanable/blood) || istype(B, /obj/effect/decal/cleanable/trail_holder))
- if(user.holder)
- user.phasein(B)
- break
- else
- user.phaseout(B)
- break
-
/obj/effect/dummy/slaughter //Can't use the wizard one, blocked by jaunt/slow
name = "water"
icon = 'icons/effects/effects.dmi'
@@ -116,3 +28,59 @@ obj/effect/dummy/slaughter/relaymove(mob/user, direction)
/obj/effect/dummy/slaughter/Destroy()
return QDEL_HINT_PUTINPOOL
+
+
+/mob/living/proc/phaseout(obj/effect/decal/cleanable/B)
+ var/mob/living/kidnapped = null
+ var/turf/mobloc = get_turf(src.loc)
+ src.notransform = TRUE
+ spawn(0)
+ src.visible_message("[src] sinks into the pool of blood.")
+ playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
+ var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
+ src.ExtinguishMob()
+ if(src.buckled)
+ src.buckled.unbuckle_mob()
+ if(src.pulling && src.bloodcrawl == BLOODCRAWL_EAT)
+ if(istype(src.pulling, /mob/living))
+ var/mob/living/victim = src.pulling
+ if(victim.stat == CONSCIOUS)
+ src.visible_message("[victim] kicks free of the [src] at the last second!")
+ else
+ victim.loc = holder
+ src.visible_message("The [src] drags [victim] into the pool of blood!")
+ kidnapped = victim
+ src.loc = holder
+ src.holder = holder
+ if(kidnapped)
+ src << "You begin to feast on [kidnapped]. You can not move while you are doing this."
+ playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
+ sleep(30)
+ playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
+ sleep(30)
+ playsound(get_turf(src),'sound/magic/Demon_consume.ogg', 100, 1)
+ sleep(30)
+ if(kidnapped)
+ src << "You devour [kidnapped]. Your health is fully restored."
+ src.adjustBruteLoss(-1000)
+ src.adjustFireLoss(-1000)
+ src.adjustOxyLoss(-1000)
+ src.adjustToxLoss(-1000)
+ kidnapped.ghostize()
+ qdel(kidnapped)
+ else
+ src << "You happily devour...nothing? Your meal vanished at some point!"
+ src.notransform = 0
+
+/mob/living/proc/phasein(obj/effect/decal/cleanable/B)
+ if(src.notransform)
+ src << "Finish eating first!"
+ return 0
+
+ src.loc = B.loc
+ src.client.eye = src
+ src.visible_message("The [src] rises out of the pool of blood!")
+ playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
+ qdel(src.holder)
+ src.holder = null
+ return 1
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
index ff0c9866215..5b4d228973d 100644
--- a/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
+++ b/code/modules/mob/living/simple_animal/slaughter/slaughter.dm
@@ -54,7 +54,7 @@
/mob/living/simple_animal/slaughter/phasein()
- ..()
+ . = ..()
speed = 0
boost = world.time + 30
@@ -70,7 +70,12 @@
/obj/item/weapon/demonheart/attack_self(mob/living/user)
visible_message("[user] feasts upon the [src].")
+ for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
+ if(knownspell.type == /obj/effect/proc_holder/spell/bloodcrawl)
+ user <<"You already know how to blood crawl."
+ qdel(src)
+ return
user << "You absorb some of the demon's power!"
- user.bloodcrawl = BLOODCRAWL
+ user.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl)
qdel(src)
diff --git a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
index de3e477ab6d..167dd6b9683 100644
--- a/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
+++ b/code/modules/mob/living/simple_animal/slaughter/slaughterevent.dm
@@ -42,6 +42,9 @@
player_mind.transfer_to(S)
player_mind.assigned_role = "Slaughter Demon"
player_mind.special_role = "Slaughter Demon"
+ var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
+ bloodspell.phased = 1
+ player_mind.AddSpell(bloodspell)
ticker.mode.traitors |= player_mind
S << S.playstyle_string
S << "You are currently not currently in the same plane of existence as the station. Ctrl+Click a blood pool to manifest."
diff --git a/html/changelogs/xxalpha-crawlinginmyskin.yml b/html/changelogs/xxalpha-crawlinginmyskin.yml
new file mode 100644
index 00000000000..04de682d000
--- /dev/null
+++ b/html/changelogs/xxalpha-crawlinginmyskin.yml
@@ -0,0 +1,7 @@
+author: xxalpha
+
+delete-after: True
+
+changes:
+ - tweak: "Blood crawling is now a spell."
+
diff --git a/icons/mob/actions.dmi b/icons/mob/actions.dmi
index 7419670c30b..04604530a6b 100644
Binary files a/icons/mob/actions.dmi and b/icons/mob/actions.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index e89d43409bb..b661e8ecf55 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -224,6 +224,7 @@
#include "code\datums\helper_datums\topic_input.dm"
#include "code\datums\spells\area_teleport.dm"
#include "code\datums\spells\barnyard.dm"
+#include "code\datums\spells\bloodcrawl.dm"
#include "code\datums\spells\charge.dm"
#include "code\datums\spells\conjure.dm"
#include "code\datums\spells\construct_spells.dm"