diff --git a/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm
new file mode 100644
index 00000000000..fbdf10f74a1
--- /dev/null
+++ b/_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm
@@ -0,0 +1,327 @@
+//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
+"a" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/structure/shuttle/engine/heater{
+ dir = 8
+ },
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"c" = (
+/obj/machinery/door/airlock/external{
+ id_tag = "s_docking_airlock";
+ name = "Shuttle Hatch";
+ req_access_txt = "109"
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"d" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 4
+ },
+/mob/living/simple_animal/hostile/retaliate/skeleton/warden{
+ dir = 4
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"e" = (
+/obj/structure/shuttle/engine/propulsion{
+ dir = 8;
+ icon_state = "burst_r"
+ },
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"f" = (
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"g" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/structure/shuttle/engine/heater{
+ dir = 8
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"h" = (
+/turf/simulated/wall/mineral/plastitanium,
+/area/ruin/space/sec_shuttle)
+"j" = (
+/obj/machinery/computer/nonfunctional{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"m" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood,
+/obj/effect/mob_spawn/human/corpse/skeleton/security_officer,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"n" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"o" = (
+/obj/structure/window/reinforced{
+ dir = 4
+ },
+/obj/structure/shuttle/engine/heater{
+ dir = 8
+ },
+/turf/space,
+/area/ruin/space/sec_shuttle)
+"t" = (
+/obj/effect/decal/cleanable/blood,
+/obj/effect/decal/cleanable/blood/footprints,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"w" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"y" = (
+/obj/effect/decal/cleanable/blood,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"z" = (
+/turf/space,
+/area/template_noop)
+"B" = (
+/obj/machinery/recharge_station/upgraded,
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"D" = (
+/obj/machinery/computer/nonfunctional,
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"E" = (
+/obj/structure/closet/crate/secure/sec_shuttle_ruin{
+ name = "emergency supplies crate"
+ },
+/obj/item/gun/medbeam/damaged,
+/obj/item/gun/projectile/automatic/pistol/enforcer,
+/obj/item/grenade/flashbang,
+/obj/item/storage/firstaid/regular,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"F" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/obj/effect/decal/cleanable/blood/footprints,
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"G" = (
+/obj/effect/decal/cleanable/blood/splatter,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"H" = (
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"J" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood/footprints,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"N" = (
+/obj/effect/mob_spawn/human/corpse/skeleton/prisoner,
+/turf/space,
+/area/space/nearstation)
+"Q" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/obj/effect/mob_spawn/human/corpse/skeleton/security_officer,
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"R" = (
+/obj/structure/chair/comfy/shuttle{
+ dir = 1
+ },
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"S" = (
+/obj/machinery/computer/security{
+ dir = 1;
+ network = list("SS13")
+ },
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+"T" = (
+/obj/machinery/door/airlock/external{
+ id_tag = "s_docking_airlock";
+ name = "Shuttle Hatch";
+ req_access_txt = "109"
+ },
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"U" = (
+/obj/structure/shuttle/engine/propulsion{
+ dir = 8
+ },
+/turf/space,
+/area/ruin/space/sec_shuttle)
+"V" = (
+/obj/structure/shuttle/engine/propulsion{
+ dir = 8
+ },
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"X" = (
+/obj/effect/decal/cleanable/blood/drip,
+/obj/effect/decal/cleanable/blood,
+/obj/effect/decal/cleanable/blood/footprints,
+/turf/simulated/floor/plating/airless,
+/area/ruin/space/sec_shuttle)
+"Y" = (
+/obj/structure/shuttle/engine/propulsion{
+ dir = 8;
+ icon_state = "burst_l"
+ },
+/turf/space,
+/area/ruin/space/sec_shuttle)
+"Z" = (
+/obj/structure/computerframe,
+/turf/simulated/floor/plasteel/airless{
+ icon_state = "dark"
+ },
+/area/ruin/space/sec_shuttle)
+
+(1,1,1) = {"
+z
+z
+z
+Y
+U
+V
+V
+e
+"}
+(2,1,1) = {"
+z
+z
+z
+h
+o
+g
+a
+h
+"}
+(3,1,1) = {"
+z
+z
+z
+h
+D
+d
+j
+h
+"}
+(4,1,1) = {"
+z
+z
+z
+h
+Z
+f
+S
+h
+"}
+(5,1,1) = {"
+z
+z
+z
+h
+B
+f
+Q
+h
+"}
+(6,1,1) = {"
+z
+z
+z
+c
+H
+H
+w
+h
+"}
+(7,1,1) = {"
+z
+z
+z
+c
+G
+J
+F
+h
+"}
+(8,1,1) = {"
+N
+z
+z
+t
+X
+J
+R
+h
+"}
+(9,1,1) = {"
+z
+z
+z
+y
+m
+n
+E
+h
+"}
+(10,1,1) = {"
+z
+z
+z
+h
+h
+H
+h
+h
+"}
+(11,1,1) = {"
+z
+z
+z
+z
+h
+T
+h
+z
+"}
diff --git a/code/datums/particles.dm b/code/datums/particles.dm
index 01206630faa..2b2dca7e396 100644
--- a/code/datums/particles.dm
+++ b/code/datums/particles.dm
@@ -107,3 +107,21 @@
velocity = generator(GEN_CIRCLE, 30, 30)
scale = 0.1
friction = 0.1
+
+/particles/fire_particles
+ icon = 'icons/effects/particles/generic_particles.dmi'
+ icon_state = "bonfire"
+ width = 100
+ height = 100
+ count = 1000
+ spawning = 8
+ lifespan = 0.7 SECONDS
+ fade = 1 SECONDS
+ grow = -0.01
+ velocity = list(0, 0)
+ position = generator("box", list(-16, -16), list(16, 16), NORMAL_RAND)
+ drift = generator("vector", list(0, -0.2), list(0, 0.2))
+ gravity = list(0, 0.95)
+ scale = generator("vector", list(0.3, 0.3), list(1,1), NORMAL_RAND)
+ rotation = 30
+ spin = generator("num", -20, 20)
diff --git a/code/datums/ruins/space_ruins.dm b/code/datums/ruins/space_ruins.dm
index 41d93e14769..03e494504d8 100644
--- a/code/datums/ruins/space_ruins.dm
+++ b/code/datums/ruins/space_ruins.dm
@@ -360,3 +360,10 @@
name = "Dorian Casino"
description = "A swanky space casino."
allow_duplicates = FALSE
+
+/datum/map_template/ruin/space/abandoned_security_shuttle
+ id = "abandoned_sec_shuttle"
+ suffix = "abandoned_sec_shuttle.dmm"
+ name = "Abandoned Security Shuttle"
+ description = "A security shuttle that has been floating in space."
+ allow_duplicates = FALSE
diff --git a/code/game/area/areas/ruins/space_areas.dm b/code/game/area/areas/ruins/space_areas.dm
index af8b7c6f9eb..24c22722040 100644
--- a/code/game/area/areas/ruins/space_areas.dm
+++ b/code/game/area/areas/ruins/space_areas.dm
@@ -244,3 +244,7 @@
/area/ruin/space/deepstorage
name = "Derelict Facility"
apc_starts_off = TRUE
+
+/area/ruin/space/sec_shuttle
+ name = "Abandoned Security Shuttle"
+ apc_starts_off = TRUE
diff --git a/code/game/objects/effects/effects.dm b/code/game/objects/effects/effects.dm
index 60107130674..4a9e2500c02 100644
--- a/code/game/objects/effects/effects.dm
+++ b/code/game/objects/effects/effects.dm
@@ -181,6 +181,7 @@
if(parent)
UnregisterSignal(parent, list(COMSIG_MOVABLE_MOVED, COMSIG_PARENT_QDELETING))
QDEL_NULL(particles)
+ holding_parent = null
parent.vis_contents -= src
return ..()
@@ -206,9 +207,9 @@
// Add new
if(isitem(attached_to) && ismob(attached_to.loc)) //special case we want to also be emitting from the mob
- var/mob/particle_mob = attached_to.loc
+ holding_parent = attached_to.loc
last_attached_location_type = attached_to.loc
- particle_mob.vis_contents += src
+ holding_parent.vis_contents += src
// Readd to ourselves
attached_to.vis_contents |= src
diff --git a/code/game/objects/structures/crates_lockers/crates.dm b/code/game/objects/structures/crates_lockers/crates.dm
index bf36273ab16..733cb21fbd6 100644
--- a/code/game/objects/structures/crates_lockers/crates.dm
+++ b/code/game/objects/structures/crates_lockers/crates.dm
@@ -678,3 +678,24 @@
log_admin(msg)
#undef RECURSION_PANIC_AMOUNT
+
+/obj/structure/closet/crate/secure/sec_shuttle_ruin
+ name = "locked crate"
+ desc = "The side of the crate has a slot for a keycard to be swiped."
+ can_be_emaged = FALSE
+
+/obj/structure/closet/crate/secure/sec_shuttle_ruin/allowed(mob/user)
+ if(!user)
+ return
+
+ var/obj/item/card/sec_shuttle_ruin/keycard = user.get_active_hand()
+ if(!istype(keycard))
+ return
+
+ to_chat(user, "You swipe [keycard] in [src]'s keycard slot.")
+ return TRUE
+
+/obj/item/card/sec_shuttle_ruin
+ name = "warden's card"
+ desc = "A card used by the warden to unlock their crate."
+ icon_state = "data"
diff --git a/code/modules/awaymissions/mob_spawn.dm b/code/modules/awaymissions/mob_spawn.dm
index ea51fed28d8..1741cdb69f1 100644
--- a/code/modules/awaymissions/mob_spawn.dm
+++ b/code/modules/awaymissions/mob_spawn.dm
@@ -379,6 +379,20 @@
flavour_text = "By unknown powers, your skeletal remains have been reanimated! Walk this mortal plain and terrorize all living adventurers who dare cross your path."
assignedrole = "Skeleton"
+/obj/effect/mob_spawn/human/corpse/skeleton/security_officer
+ outfit = /datum/outfit/job/officer
+ id_access = "Assistant" //no brig access for explorers
+
+/obj/effect/mob_spawn/human/corpse/skeleton/prisoner
+ uniform = /obj/item/clothing/under/color/orange/prison
+ shoes = /obj/item/clothing/shoes/orange
+
+/obj/effect/mob_spawn/human/corpse/skeleton/prisoner/equip(mob/living/carbon/human/prisoner) //put cuffs on the corpse
+ . = ..()
+ var/obj/item/restraints/handcuffs/cuffs = new(prisoner)
+ prisoner.handcuffed = cuffs
+ prisoner.update_handcuffed()
+
//////////Corpses, they can be used for "decoration" purpose.//////////
//Default Abductor corpse.
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
index 063ac6b55ea..2807b0860ee 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
@@ -76,6 +76,43 @@
del_on_death = TRUE
footstep_type = FOOTSTEP_MOB_SHOE
+/mob/living/simple_animal/hostile/retaliate/skeleton/warden
+ name = "skeleton warden"
+ desc = "The remains of a warden."
+ icon = 'icons/mob/simple_human.dmi'
+ icon_state = "skeleton_warden"
+ icon_living = "skeleton_warden"
+ wander = FALSE
+ loot = list(/obj/effect/decal/cleanable/shreds, /mob/living/simple_animal/hostile/skeleton/angered_warden)
+ maxHealth = 300
+ health = 300
+ melee_damage_lower = 15
+ melee_damage_upper = 15
+ deathmessage = null
+
+/mob/living/simple_animal/hostile/retaliate/skeleton/warden/Process_Spacemove(movement_dir)
+ return TRUE
+
+/mob/living/simple_animal/hostile/skeleton/angered_warden
+ name = "angered skeleton warden" //round 2
+ desc = "An angry skeleton."
+ icon = 'icons/mob/simple_human.dmi'
+ icon_state = "skeleton_warden_alt"
+ icon_living = "skeleton_warden_alt"
+
+ attacktext = "claws"
+ attack_sound = 'sound/hallucinations/growl1.ogg'
+
+ maxHealth = 200
+ health = 200
+ speed = -1
+ melee_damage_lower = 30
+ melee_damage_upper = 30
+ loot = list(/obj/effect/decal/remains/human, /obj/item/clothing/head/warden, /obj/item/card/sec_shuttle_ruin)
+
+/mob/living/simple_animal/hostile/skeleton/angered_warden/Process_Spacemove(movement_dir)
+ return TRUE
+
/mob/living/simple_animal/hostile/retaliate/zombie
name = "zombie"
icon = 'icons/mob/human.dmi'
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index d8f6535a23b..ba949775de1 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -10,14 +10,23 @@
throw_speed = 2
throw_range = 5
w_class = WEIGHT_CLASS_SMALL
- var/charge = 0 // note %age conveted to actual charge in New
+ ///How much charge the battery currently has
+ var/charge = 0
+ ///How much charge the battery can hold
var/maxcharge = 1000
+ ///How much charge the battery should start with
+ var/starting_charge
materials = list(MAT_METAL = 700, MAT_GLASS = 50)
- var/rigged = FALSE // true if rigged to explode
- var/chargerate = 100 //how much power is given every tick in a recharger
- var/self_recharge = 0 //does it self recharge, over time, or not?
+ ///If the battery will explode
+ var/rigged = FALSE
+ ///How much charge is given every tick when recharging
+ var/chargerate = 100
+ ///Whether it will recharge automatically
+ var/self_recharge = TRUE
+ ///Whether the description will include the maxcharge
var/ratingdesc = TRUE
- var/grown_battery = FALSE // If it's a grown that acts as a battery, add a wire overlay to it.
+ ///Additional overlay to signify battery being organic
+ var/grown_battery = FALSE
/obj/item/stock_parts/cell/get_cell()
return src
@@ -25,7 +34,7 @@
/obj/item/stock_parts/cell/New()
..()
START_PROCESSING(SSobj, src)
- charge = maxcharge
+ charge = !isnull(starting_charge) ? starting_charge : maxcharge
if(ratingdesc)
desc += " This one has a power rating of [DisplayPower(maxcharge)], and you should not swallow it."
update_icon(UPDATE_OVERLAYS)
@@ -164,9 +173,8 @@
return 0
// Cell variants
-/obj/item/stock_parts/cell/empty/New()
- ..()
- charge = 0
+/obj/item/stock_parts/cell/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/crap
name = "\improper Nanotrasen brand rechargeable AA battery"
@@ -175,10 +183,8 @@
materials = list(MAT_GLASS = 40)
rating = 2
-/obj/item/stock_parts/cell/crap/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/crap/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/upgraded
name = "upgraded power cell"
@@ -200,10 +206,8 @@
materials = list(MAT_GLASS = 40)
rating = 2.5
-/obj/item/stock_parts/cell/secborg/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/secborg/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/hos_gun
name = "\improper X-01 multiphase energy gun power cell"
@@ -242,10 +246,8 @@
maxcharge = 15000
chargerate = 2250
-/obj/item/stock_parts/cell/high/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/high/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/super
name = "super-capacity power cell"
@@ -256,10 +258,8 @@
rating = 4
chargerate = 2000
-/obj/item/stock_parts/cell/super/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/super/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/hyper
name = "hyper-capacity power cell"
@@ -270,10 +270,8 @@
rating = 5
chargerate = 3000
-/obj/item/stock_parts/cell/hyper/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/hyper/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/bluespace
name = "bluespace power cell"
@@ -285,10 +283,8 @@
rating = 6
chargerate = 4000
-/obj/item/stock_parts/cell/bluespace/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/bluespace/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/bluespace/charging
name = "self-charging bluespace power cell"
@@ -352,10 +348,8 @@
maxcharge = 500
rating = 3
-/obj/item/stock_parts/cell/emproof/empty/New()
- ..()
- charge = 0
- update_icon(UPDATE_OVERLAYS)
+/obj/item/stock_parts/cell/emproof/empty
+ starting_charge = 0
/obj/item/stock_parts/cell/emproof/emp_act(severity)
return
diff --git a/code/modules/projectiles/guns/medbeam.dm b/code/modules/projectiles/guns/medbeam.dm
index 945960fbb94..6c5836846ce 100644
--- a/code/modules/projectiles/guns/medbeam.dm
+++ b/code/modules/projectiles/guns/medbeam.dm
@@ -79,7 +79,7 @@
return
if(current_target)
- on_beam_tick(current_target)
+ on_beam_tick(source, current_target)
/obj/item/gun/medbeam/proc/los_check(mob/user,mob/target)
var/turf/user_turf = user.loc
@@ -105,7 +105,7 @@
qdel(dummy)
return TRUE
-/obj/item/gun/medbeam/proc/on_beam_tick(mob/living/target)
+/obj/item/gun/medbeam/proc/on_beam_tick(mob/living/user, mob/living/target)
if(ishuman(target))
var/mob/living/carbon/human/H = target
H.adjustBruteLoss(-4, robotic = TRUE)
@@ -124,3 +124,224 @@
/obj/effect/ebeam/medical
name = "medical beam"
+
+//Damaged beamgun loot, DO NOT let it break
+#define SCREWDRIVER_OPEN 8
+#define REMOVE_OLD_PARTS 7
+#define WELD_SHELL 6
+#define INSTALL_LENS 5
+#define INSTALL_ELECTRONICS 4
+#define INSTALL_CELL 3
+#define MULTITOOL_ELECTRONICS 2
+#define SCREWDRIVER_CLOSED 1
+
+/obj/item/gun/medbeam/damaged
+ name = "damaged beamgun"
+ desc = "Delivers volatile medical nanites in a focused beam. Don't cross the beams! It is damaged and will rapidly overheat."
+ ///How hot the beamgun is, if it hits max heat it will break
+ var/current_heat = 0
+ ///How much heat the beamgun needs to break
+ var/max_heat = 50
+ ///when current_heat / max_heat > damaging_heat_percent, it will burn the wielders hands
+ var/damaging_heat_percent = 0.6
+ ///If the gun has overheated and broke down
+ var/broken = FALSE
+ ///If the gun is still too hot to repair
+ var/overheated = FALSE
+ var/obj/effect/abstract/particle_holder/fire_particles
+
+/obj/item/gun/medbeam/damaged/Destroy()
+ . = ..()
+ if(fire_particles)
+ QDEL_NULL(fire_particles)
+
+/obj/item/gun/medbeam/damaged/examine(mob/user) //The 8 Trials of Asclepius
+ . = ..()
+ if(!broken)
+ return
+
+ . += "It is broken, and will not function without repairs."
+ switch(broken)
+ if(SCREWDRIVER_OPEN)
+ . += "The panel can be screwed open to access the internals."
+ if(REMOVE_OLD_PARTS)
+ . += "The old fried electronics and melted lens have to be pried out."
+ if(WELD_SHELL)
+ . += "The distorted shell needs to be welded back to form."
+ if(INSTALL_LENS)
+ . += "It needs a new glass lens."
+ if(INSTALL_ELECTRONICS)
+ . += "It needs new cabling for the electronics."
+ if(INSTALL_CELL)
+ . += "It needs a fully charged specialized battery to function."
+ if(MULTITOOL_ELECTRONICS)
+ . += "The electronics need to be tested and reactivated with a multitool."
+ if(SCREWDRIVER_CLOSED)
+ . += "The panel needs to be screwed shut before it is usable."
+
+/obj/item/gun/medbeam/damaged/process()
+ . = ..()
+ if(current_target)
+ return
+
+ current_heat = max(current_heat - 1, 0)
+
+/obj/item/gun/medbeam/damaged/can_trigger_gun(mob/living/user)
+ if(broken)
+ to_chat(user, "[src] fails to start! It's broken!")
+ return FALSE
+ return ..()
+
+/obj/item/gun/medbeam/damaged/on_beam_tick(mob/living/user, mob/living/target)
+ . = ..()
+ if(current_heat >= max_heat)
+ user.visible_message("[src] pops as it shuts off!", "[src] pops and hisses as it shuts off. It is broken.")
+ broken = SCREWDRIVER_OPEN
+ user.adjust_fire_stacks(20)
+ user.IgniteMob()
+ LoseTarget()
+ update_fire_overlay(COLOR_ORANGE)
+ overheated = TRUE
+ return
+
+ if(current_heat / max_heat > damaging_heat_percent)
+ to_chat(user, "[src] burns to hold!")
+ user.adjustFireLoss(0.1 * (current_heat / max_heat))
+
+ current_heat = min(current_heat + 1, max_heat)
+
+/obj/item/gun/medbeam/damaged/attackby(obj/item/attacking_item, mob/user, params)
+ . = ..()
+
+ if(broken == INSTALL_CELL)
+ if(istype(attacking_item, /obj/item/stock_parts/cell/medbeam))
+ var/obj/item/stock_parts/cell/medbeam/battery = attacking_item
+ if(battery.charge != battery.maxcharge)
+ to_chat(user, "[src] won't function without a fully charged [battery].")
+ return
+ to_chat(user, "You start replacing [src]'s battery.")
+ attempt_repair(user, attacking_item, MULTITOOL_ELECTRONICS)
+ return
+
+ if(broken == INSTALL_ELECTRONICS)
+ if(istype(attacking_item, /obj/item/stack/cable_coil))
+ to_chat(user, "You start replacing the fried electronics in [src].")
+ attempt_repair(user, attacking_item, INSTALL_CELL)
+ return
+
+ if(broken == INSTALL_LENS)
+ if(istype(attacking_item, /obj/item/stack/sheet/glass))
+ to_chat(user, "You start replacing the broken lens in [src].")
+ attempt_repair(user, attacking_item, INSTALL_ELECTRONICS)
+ return
+
+/obj/item/gun/medbeam/damaged/screwdriver_act(mob/user, obj/item/screwdriver)
+ if(broken == SCREWDRIVER_OPEN)
+ if(overheated)
+ to_chat(user, "[src] is still too hot for the screws to be safely removed from it.")
+ return
+ to_chat(user, "You start removing the screws from [src]'s shell.")
+ attempt_repair(user, screwdriver, REMOVE_OLD_PARTS)
+ return TRUE
+
+ if(broken == SCREWDRIVER_CLOSED)
+ to_chat(user, "You start replacing the screws on [src]'s shell.")
+ attempt_repair(user, screwdriver, FALSE)
+ return TRUE
+
+/obj/item/gun/medbeam/damaged/crowbar_act(mob/living/user, obj/item/crowbar)
+ if(broken == REMOVE_OLD_PARTS)
+ to_chat(user, "You start prying out the old electronics and lens from [src].")
+ attempt_repair(user, crowbar, WELD_SHELL)
+ return TRUE
+
+/obj/item/gun/medbeam/damaged/welder_act(mob/living/user, obj/item/welder)
+ . = ..()
+ if(broken == WELD_SHELL)
+ if(!welder.tool_start_check(src, user, 1))
+ to_chat(user, "[welder] isn't functioning.")
+ return
+ to_chat(user, "You start welding [src] back to form.")
+ attempt_repair(user, welder, INSTALL_LENS)
+ return TRUE
+
+/obj/item/gun/medbeam/damaged/multitool_act(mob/living/user, obj/item/multitool)
+ if(broken == MULTITOOL_ELECTRONICS)
+ if(user.electrocute_act(rand(1, 10), src))
+ do_sparks(6, FALSE, user)
+ return TRUE
+ to_chat(user, "You start to activate the electronics in [src].")
+ attempt_repair(user, multitool, SCREWDRIVER_CLOSED)
+ return TRUE
+
+/obj/item/gun/medbeam/damaged/proc/update_fire_overlay(new_color)
+ if(!fire_particles)
+ fire_particles = new(src, /particles/fire_particles)
+ fire_particles.color = COLOR_RED
+
+ animate(fire_particles, 20 SECONDS, color = COLOR_ORANGE)
+ animate(fire_particles, 10 SECONDS, color = COLOR_GRAY, delay = 20 SECONDS)
+ addtimer(VARSET_CALLBACK(src, overheated, FALSE), 30 SECONDS)
+
+/obj/item/gun/medbeam/damaged/proc/attempt_repair(mob/living/user, obj/item/tool_used, next_broken_state)
+ if(!do_after_once(user, 5 SECONDS, TRUE, src))
+ to_chat(user, "You stop repairing [src].")
+ return
+
+ if(!user.Adjacent(src))
+ return
+
+ if(!user.get_active_hand() == tool_used)
+ return
+
+ switch(broken)
+ if(REMOVE_OLD_PARTS)
+ user.put_in_hands(new /obj/item/stock_parts/cell/medbeam)
+
+ if(WELD_SHELL)
+ if(!tool_used.tool_use_check(user, 1))
+ return
+
+ if(INSTALL_LENS)
+ var/obj/item/stack/sheet/glass/lens = tool_used
+ if(!istype(lens))
+ return
+ if(!lens.use(5))
+ to_chat(user, "You need [5 - lens.get_amount()] more [lens] to repair [src]'s electronics.")
+ return
+
+ if(INSTALL_ELECTRONICS)
+ var/obj/item/stack/cable_coil/cable = tool_used
+ if(!istype(cable))
+ return
+ if(!cable.use(10))
+ to_chat(user, "You need [10 - cable.get_amount()] more [cable] to repair [src]'s electronics.")
+ return
+
+ if(INSTALL_CELL)
+ var/obj/item/stock_parts/cell/medbeam/battery = tool_used
+ if(!istype(battery))
+ return
+ if(!user.get_active_hand() == battery)
+ to_chat(user, "You lost [src]'s battery.")
+ return
+ qdel(battery)
+
+ if(SCREWDRIVER_CLOSED)
+ QDEL_NULL(fire_particles)
+
+ broken = next_broken_state
+
+#undef SCREWDRIVER_OPEN
+#undef REMOVE_OLD_PARTS
+#undef WELD_SHELL
+#undef INSTALL_LENS
+#undef INSTALL_ELECTRONICS
+#undef INSTALL_CELL
+#undef MULTITOOL_ELECTRONICS
+#undef SCREWDRIVER_CLOSED
+
+/obj/item/stock_parts/cell/medbeam
+ name = "beamgun cell"
+ desc = "A cell that fell out of a beamgun. It cannot be reused until fully charged. Only this brand of battery is compatible with medical beamguns."
+ starting_charge = 0
diff --git a/config/example/config.toml b/config/example/config.toml
index 0ed2c1da0de..83d590b8759 100644
--- a/config/example/config.toml
+++ b/config/example/config.toml
@@ -682,6 +682,7 @@ active_space_ruins = [
"_maps/map_files/RandomRuins/SpaceRuins/telecomns_returns.dmm",
"_maps/map_files/RandomRuins/SpaceRuins/casino.dmm",
"_maps/map_files/RandomRuins/SpaceRuins/rocky_motel.dmm",
+ "_maps/map_files/RandomRuins/SpaceRuins/abandoned_sec_shuttle.dmm",
### The following ruins are based from past pre-spawned Zlevel content ###
"_maps/map_files/RandomRuins/SpaceRuins/abandonedtele.dmm",
diff --git a/icons/effects/particles/generic_particles.dmi b/icons/effects/particles/generic_particles.dmi
index e322afcebbe..0eda2ecc2d6 100644
Binary files a/icons/effects/particles/generic_particles.dmi and b/icons/effects/particles/generic_particles.dmi differ
diff --git a/icons/mob/simple_human.dmi b/icons/mob/simple_human.dmi
index dd33948a4ca..16eb7497229 100644
Binary files a/icons/mob/simple_human.dmi and b/icons/mob/simple_human.dmi differ