diff --git a/code/modules/overmap/sectors.dm b/code/modules/overmap/sectors.dm
index 21456cb7cc2..9748963d84c 100644
--- a/code/modules/overmap/sectors.dm
+++ b/code/modules/overmap/sectors.dm
@@ -25,6 +25,7 @@
var/hide_from_reports = FALSE
var/has_distress_beacon
+ var/list/levels_for_distress
/obj/effect/overmap/visitable/Initialize()
. = ..()
@@ -164,6 +165,40 @@
// prior to being moved to the overmap. This blocks that. Use set_invisibility to adjust invisibility as needed instead.
/obj/effect/overmap/visitable/sector/hide()
+/obj/effect/overmap/visitable/proc/distress(mob/user)
+ if(has_distress_beacon)
+ return FALSE
+ has_distress_beacon = TRUE
+
+ admin_chat_message(message = "Overmap panic button hit on z[z] ([scanner_name || name]) by '[user.ckey]'", color = "#FF2222") //VOREStation Add
+ var/message = "A distress signal has been received from a beacon conforming to MIL-DTL-93352. The signal has been relayed via the local telecomms array. \
+ The beacon was launched from '[scanner_name || name]'. It provided this information: [get_distress_info()]. \
+ Per the Interplanetary Convention on Space SAR, which your organization is party to, those receiving this message must attempt rescue, \
+ or relay the message to those who can. This message will repeat once in 5 minutes. Thank you for your cooperation."
+
+ if(!levels_for_distress)
+ levels_for_distress = list(1)
+ for(var/zlevel in levels_for_distress)
+ priority_announcement.Announce(message, new_title = "Distress Beacon Detected", new_sound = 'sound/misc/interference.ogg', zlevel = zlevel)
+
+ var/image/I = image(icon, icon_state = "distress")
+ I.plane = PLANE_LIGHTING_ABOVE
+ I.appearance_flags = KEEP_APART|RESET_TRANSFORM|RESET_COLOR
+ add_overlay(I)
+
+ addtimer(CALLBACK(src, .proc/distress_update), 5 MINUTES)
+ return TRUE
+
+/obj/effect/overmap/visitable/proc/get_distress_info()
+ return "\[X:[x],Y:[y]\]"
+
+/obj/effect/overmap/visitable/proc/distress_update()
+ var/message = "This is the final message from the distress beacon launched from '[scanner_name || name]'. The beacon sent this update: [get_distress_info()].\
+ Please render assistance under your obligations per the Interplanetary Convention on Space SAR, or relay this message to a party who can. Thank you for your cooperation."
+
+ for(var/zlevel in levels_for_distress)
+ priority_announcement.Announce(message, new_title = "Distress Beacon Update", new_sound = 'sound/misc/interference.ogg', zlevel = zlevel)
+
/proc/build_overmap()
if(!global.using_map.use_overmap)
return 1
@@ -186,3 +221,4 @@
testing("Overmap build complete.")
return 1
+
diff --git a/code/modules/overmap/ships/panicbutton.dm b/code/modules/overmap/ships/panicbutton.dm
new file mode 100644
index 00000000000..4e819db6426
--- /dev/null
+++ b/code/modules/overmap/ships/panicbutton.dm
@@ -0,0 +1,74 @@
+/obj/structure/panic_button
+ name = "distress beacon trigger"
+ desc = "WARNING: Will deploy ship's distress beacon and request help. Misuse may result in fines and jail time."
+ description_info = "Using this device (smashing the glas on harm intent, and then pressing the button) will send a message to people on other z-levels requesting their aid. It may take them a while to come get you, as they'll need to prepare. You should only use this if you really need it."
+ icon = 'icons/obj/objects_vr.dmi'
+ icon_state = "panicbutton"
+ anchored = TRUE
+
+ var/glass = TRUE
+ var/launched = FALSE
+
+// In case we're annihilated by a meteor
+/obj/structure/panic_button/Destroy()
+ if(!launched)
+ launch()
+ return ..()
+
+/obj/structure/panic_button/update_icon()
+ if(launched)
+ icon_state = "[initial(icon_state)]_launched"
+ else if(!glass)
+ icon_state = "[initial(icon_state)]_open"
+ else
+ icon_state = "[initial(icon_state)]"
+
+/obj/structure/panic_button/attack_hand(mob/living/user)
+ if(!istype(user))
+ return ..()
+
+ if(user.incapacitated())
+ return
+
+ // Already launched
+ if(launched)
+ to_chat(user, "The button is already depressed; the beacon has been launched already.")
+ // Glass present
+ else if(glass)
+ if(user.a_intent == I_HURT)
+ user.custom_emote(VISIBLE_MESSAGE, "smashes the glass on [src]!")
+ glass = FALSE
+ playsound(src, 'sound/effects/hit_on_shattered_glass.ogg')
+ update_icon()
+ else
+ user.custom_emote(VISIBLE_MESSAGE, "pats [src] in a friendly manner.")
+ to_chat(user, "If you're trying to break the glass, you'll have to hit it harder than that...")
+ // Must be !glass and !launched
+ else
+ user.custom_emote(VISIBLE_MESSAGE, "pushes the button on [src]!")
+ launch(user)
+ playsound(src, get_sfx("button"))
+ update_icon()
+
+/obj/structure/panic_button/proc/launch(mob/living/user)
+ if(launched)
+ return
+ launched = TRUE
+ var/obj/effect/overmap/visitable/S = get_overmap_sector(z)
+ if(!S)
+ error("Distress button hit on z[z] but that's not an overmap sector...")
+ return
+ S.distress(user)
+ //Kind of pricey, but this is a one-time thing that can't be reused, so I'm not too worried.
+ var/list/hear_z = GetConnectedZlevels(z) // multiz 'physical' connections only, not crazy overmap connections
+
+ var/mapsize = (world.maxx+world.maxy)*0.5
+ var/turf/us = get_turf(src)
+
+ for(var/hz in hear_z)
+ for(var/m in GLOB.players_by_zlevel[hz])
+ var/mob/M = m
+ var/sound/SND = sound('sound/misc/emergency_beacon_launched.ogg') // Inside the loop because playsound_local modifies it for each person, so, need separate instances
+ var/turf/them = get_turf(M)
+ var/volume = max(0.20, 1-(get_dist(us,them) / mapsize*0.8))*100
+ M.playsound_local(get_turf(M), SND, vol = volume)
diff --git a/code/modules/overmap/ships/ship.dm b/code/modules/overmap/ships/ship.dm
index 94a19e36dc7..11230a5300d 100644
--- a/code/modules/overmap/ships/ship.dm
+++ b/code/modules/overmap/ships/ship.dm
@@ -260,6 +260,12 @@
/obj/effect/overmap/visitable/ship/proc/get_landed_info()
return "This ship cannot land."
+/obj/effect/overmap/visitable/ship/get_distress_info()
+ var/turf/T = get_turf(src) // Usually we're on the turf, but sometimes we might be landed or something.
+ var/x_to_use = T?.x || "UNK"
+ var/y_to_use = T?.y || "UNK"
+ return "\[X:[x_to_use],Y:[y_to_use],VEL:[get_speed() * 1000],HDG:[get_heading_degrees()]\]"
+
#undef MOVING
#undef SANITIZE_SPEED
#undef CHANGE_SPEED_BY
\ No newline at end of file
diff --git a/icons/obj/objects_vr.dmi b/icons/obj/objects_vr.dmi
index d5343a995d5..19c7947b4be 100644
Binary files a/icons/obj/objects_vr.dmi and b/icons/obj/objects_vr.dmi differ
diff --git a/icons/obj/overmap.dmi b/icons/obj/overmap.dmi
index 20523513b34..d46f1065f2b 100644
Binary files a/icons/obj/overmap.dmi and b/icons/obj/overmap.dmi differ
diff --git a/sound/misc/emergency_beacon_launched.ogg b/sound/misc/emergency_beacon_launched.ogg
new file mode 100644
index 00000000000..bd730fe2f52
Binary files /dev/null and b/sound/misc/emergency_beacon_launched.ogg differ
diff --git a/vorestation.dme b/vorestation.dme
index d49fb524b49..bc441864d4e 100644
--- a/vorestation.dme
+++ b/vorestation.dme
@@ -3270,6 +3270,7 @@
#include "code\modules\overmap\events\generation.dm"
#include "code\modules\overmap\events\overmap_event.dm"
#include "code\modules\overmap\ships\landable.dm"
+#include "code\modules\overmap\ships\panicbutton.dm"
#include "code\modules\overmap\ships\ship.dm"
#include "code\modules\overmap\ships\computers\computer_shims.dm"
#include "code\modules\overmap\ships\computers\engine_control.dm"