diff --git a/code/datums/antagonists/datum_cult.dm b/code/datums/antagonists/datum_cult.dm
index ef11dd8b16..ac19a732c9 100644
--- a/code/datums/antagonists/datum_cult.dm
+++ b/code/datums/antagonists/datum_cult.dm
@@ -112,10 +112,12 @@
/datum/antagonist/cult/master
var/datum/action/innate/cult/master/finalreck/reckoning = new
var/datum/action/innate/cult/master/cultmark/bloodmark = new
+ var/datum/action/innate/cult/master/pulse/throwing = new
/datum/antagonist/cult/master/Destroy()
QDEL_NULL(reckoning)
QDEL_NULL(bloodmark)
+ QDEL_NULL(throwing)
return ..()
/datum/antagonist/cult/master/on_gain()
@@ -136,6 +138,7 @@
if(!GLOB.reckoning_complete)
reckoning.Grant(current)
bloodmark.Grant(current)
+ throwing.Grant(current)
current.update_action_buttons_icon()
current.apply_status_effect(/datum/status_effect/cult_master)
@@ -146,5 +149,6 @@
current = mob_override
reckoning.Remove(current)
bloodmark.Remove(current)
+ throwing.Remove(current)
current.update_action_buttons_icon()
current.remove_status_effect(/datum/status_effect/cult_master)
\ No newline at end of file
diff --git a/code/game/gamemodes/cult/cult_comms.dm b/code/game/gamemodes/cult/cult_comms.dm
index 6651f68556..9620d30063 100644
--- a/code/game/gamemodes/cult/cult_comms.dm
+++ b/code/game/gamemodes/cult/cult_comms.dm
@@ -300,3 +300,91 @@
B.current.client.images -= GLOB.blood_target_image
QDEL_NULL(GLOB.blood_target_image)
GLOB.blood_target = null
+
+
+
+//////// ELDRITCH PULSE /////////
+
+
+
+/datum/action/innate/cult/master/pulse
+ name = "Eldritch Pulse"
+ desc = "Seize upon a fellow cultist or cult structure and teleport it to a nearby location."
+ button_icon_state = "arcane_barrage"
+ var/obj/effect/proc_holder/pulse/PM
+ var/cooldown = 0
+ var/base_cooldown = 150
+ var/throwing = FALSE
+ var/mob/living/throwee
+
+/datum/action/innate/cult/master/pulse/New()
+ PM = new()
+ PM.attached_action = src
+ ..()
+
+/datum/action/innate/cult/master/pulse/IsAvailable()
+ if(!owner.mind || !owner.mind.has_antag_datum(ANTAG_DATUM_CULT_MASTER))
+ return FALSE
+ if(cooldown > world.time)
+ if(!PM.active)
+ owner << "You need to wait [round((cooldown - world.time) * 0.1)] seconds before you can pulse again!"
+ return FALSE
+ return ..()
+
+/datum/action/innate/cult/master/pulse/Destroy()
+ QDEL_NULL(PM)
+ return ..()
+
+/datum/action/innate/cult/master/pulse/Activate()
+ PM.toggle(owner) //the important bit
+ return TRUE
+
+/obj/effect/proc_holder/pulse
+ active = FALSE
+ ranged_mousepointer = 'icons/effects/throw_target.dmi'
+ var/datum/action/innate/cult/master/pulse/attached_action
+
+/obj/effect/proc_holder/pulse/Destroy()
+ QDEL_NULL(attached_action)
+ return ..()
+
+/obj/effect/proc_holder/pulse/proc/toggle(mob/user)
+ if(active)
+ remove_ranged_ability("You cease your preparations...")
+ attached_action.throwing = FALSE
+ else
+ add_ranged_ability(user, "You prepare to tear through the fabric of reality...")
+
+/obj/effect/proc_holder/pulse/InterceptClickOn(mob/living/caller, params, atom/target)
+ if(..())
+ return
+ if(ranged_ability_user.incapacitated())
+ remove_ranged_ability()
+ return
+ var/turf/T = get_turf(ranged_ability_user)
+ if(!isturf(T))
+ return FALSE
+ if(target in view(7, get_turf(ranged_ability_user)))
+ if((!(iscultist(target) || istype(target, /obj/structure/destructible/cult)) || target == caller) && !(attached_action.throwing))
+ return
+ if(!attached_action.throwing)
+ attached_action.throwing = TRUE
+ attached_action.throwee = target
+ ranged_ability_user << 'sound/weapons/thudswoosh.ogg'
+ to_chat(ranged_ability_user,"You reach through the veil with your mind's eye and seize [target]!")
+ return
+ else
+ new /obj/effect/temp_visual/cult/sparks(get_turf(attached_action.throwee), ranged_ability_user.dir)
+ var/distance = get_dist(attached_action.throwee, target)
+ if(distance >= 16)
+ return
+ playsound(target,'sound/magic/exit_blood.ogg')
+ attached_action.throwee.Beam(target,icon_state="sendbeam",time=4)
+ attached_action.throwee.forceMove(get_turf(target))
+ new /obj/effect/temp_visual/cult/sparks(get_turf(target), ranged_ability_user.dir)
+ attached_action.throwing = FALSE
+ attached_action.cooldown = world.time + attached_action.base_cooldown
+ remove_mousepointer(ranged_ability_user.client)
+ remove_ranged_ability("A pulse of blood magic surges through you as you shift [attached_action.throwee] through time and space.")
+ caller.update_action_buttons_icon()
+ addtimer(CALLBACK(caller, /mob.proc/update_action_buttons_icon), attached_action.base_cooldown)
diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm
index 4be11267ef..02e8422575 100644
--- a/code/game/gamemodes/cult/cult_items.dm
+++ b/code/game/gamemodes/cult/cult_items.dm
@@ -381,7 +381,7 @@
on_damage = 15
slot_flags = null
on = 1
- var/charges = 3
+ var/charges = 5
/obj/item/device/flashlight/flare/culttorch/afterattack(atom/movable/A, mob/user, proximity)
if(!proximity)
@@ -408,6 +408,9 @@
to_chat(user, "[cultist_to_receive] is not a follower of the Geometer!")
log_game("Void torch failed - target was deconverted")
return
+ if(A in user.GetAllContents())
+ to_chat(user, "[A] must be on a surface in order to teleport it!")
+ return
to_chat(user, "You ignite [A] with \the [src], turning it to ash, but through the torch's flames you see that [A] has reached [cultist_to_receive]!")
cultist_to_receive.put_in_hands(A)
charges--
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 07c7e0ba00..ff7e5a9090 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -446,7 +446,7 @@ structure_check() searches for nearby cultist structures required for the invoca
icon_state = "rune_large"
pixel_x = -32 //So the big ol' 96x96 sprite shows up right
pixel_y = -32
- scribe_delay = 450 //how long the rune takes to create
+ scribe_delay = 500 //how long the rune takes to create
scribe_damage = 40.1 //how much damage you take doing it
var/used = FALSE
diff --git a/code/game/objects/effects/temporary_visuals/cult.dm b/code/game/objects/effects/temporary_visuals/cult.dm
index 78cc50cfc1..a649763435 100644
--- a/code/game/objects/effects/temporary_visuals/cult.dm
+++ b/code/game/objects/effects/temporary_visuals/cult.dm
@@ -18,11 +18,13 @@
icon_state = "bloodout"
/obj/effect/temp_visual/dir_setting/cult/phase // The veil shifter teleport
+ icon = 'icons/effects/cult_effects.dmi'
name = "phase glow"
duration = 7
icon_state = "cultin"
/obj/effect/temp_visual/dir_setting/cult/phase/out
+ icon = 'icons/effects/cult_effects.dmi'
icon_state = "cultout"
/obj/effect/temp_visual/cult/sac
diff --git a/icons/effects/cult_effects.dmi b/icons/effects/cult_effects.dmi
index 58a2d3c9c9..925950b9a3 100644
Binary files a/icons/effects/cult_effects.dmi and b/icons/effects/cult_effects.dmi differ
diff --git a/icons/effects/station_explosion.dmi b/icons/effects/station_explosion.dmi
index 385818b011..d8ced1f544 100644
Binary files a/icons/effects/station_explosion.dmi and b/icons/effects/station_explosion.dmi differ
diff --git a/icons/effects/throw_target.dmi b/icons/effects/throw_target.dmi
new file mode 100644
index 0000000000..660eafbf2b
Binary files /dev/null and b/icons/effects/throw_target.dmi differ