diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index e6f1dfa67ff..d9fcccb12d9 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -487,7 +487,21 @@
SA.health -= 20
..()
-
+/obj/item/weapon/batteringram
+ name = "battering ram"
+ desc = "A hydraulic compression/spreader-type mechanism which, when applied to a door, will charge before rapidly expanding and dislodging frames."
+ flags = TWOHANDABLE | MUSTTWOHAND | FPRINT
+ icon = 'icons/obj/weapons.dmi'
+ icon_state = "ram"
+ siemens_coefficient = 0
+ throwforce = 15
+ w_class = 3
+ w_type = RECYK_METAL
+ origin_tech = "combat=5"
+ attack_verb = list("rammed", "bludgeoned")
+ force = 15
+ throw_speed = 1
+ throw_range = 3
/obj/item/weapon/caution
desc = "Caution! Wet Floor!"
diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm
index d92aa135503..bfca3f0f061 100644
--- a/code/game/machinery/doors/airlock.dm
+++ b/code/game/machinery/doors/airlock.dm
@@ -986,6 +986,31 @@ About the new airlock wires panel:
if (shock(user, 75))
return
+ if(istype(I, /obj/item/weapon/batteringram))
+ user.delayNextAttack(30)
+ var/breaktime = 60 //Same amount of time as drilling a wall, then a girder
+ if(welded)
+ breaktime += 30 //Welding buys you a little time
+ src.visible_message("[user] is battering down [src]!", "You begin to batter [src].")
+ playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1)
+ if(do_after(user, breaktime))
+ //Calculate bolts separtely, in case they dropped in the last 6-9 seconds.
+ if(src.locked == 1)
+ playsound(get_turf(src), 'sound/effects/shieldbash.ogg', 50, 1)
+ src.visible_message("[user] is battering the bolts!", "You begin to smash the bolts...")
+ if(!do_after(user,190)) //Same amount as drilling an R-wall, longer if it was welded
+ return //If they moved, cancel us out
+ playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ src.visible_message("[user] broke down the door!", "You broke the door!")
+ playsound(get_turf(src), 'sound/items/Deconstruct.ogg', 50, 1)
+ operating = -1
+ var/obj/structure/door_assembly/DA = revert(user,user.dir)
+ DA.anchored = 0
+ DA.state = 0 //Completely smash the door here; reduce it to its lowest state, eject electronics smoked
+ DA.update_state()
+ qdel(src)
+ return
+
if (istype(I, /obj/item/weapon/weldingtool))
if (density && !operating)
var/obj/item/weapon/weldingtool/WT = I
@@ -1026,44 +1051,8 @@ About the new airlock wires panel:
// TODO: refactor the called proc
if (do_after(user, 40))
user << "You removed the airlock electronics!"
-
- var/obj/structure/door_assembly/DA = new assembly_type(loc)
- DA.anchored = 1
- DA.fingerprints += src.fingerprints
- DA.fingerprintshidden += src.fingerprintshidden
- DA.fingerprintslast = user.ckey
- if (mineral)
- DA.glass = mineral
- // TODO: check DA.glass
- else if (glass && !DA.glass)
- DA.glass = 1
-
- DA.state = 1
- DA.created_name = name
- DA.update_state()
-
- var/obj/item/weapon/circuitboard/airlock/A
-
- // TODO: check electronics
- if (!electronics)
- A = new/obj/item/weapon/circuitboard/airlock(loc)
-
- // TODO: recheck the vars
- if(req_access && req_access.len)
- A.conf_access = req_access
- else if(req_one_access && req_one_access.len)
- A.conf_access = req_one_access
- A.one_access = 1
- else
- A = electronics
- electronics = null
- A.loc = loc
-
- if (operating == -1)
- A.icon_state = "door_electronics_smoked"
- operating = 0
-
- del(src)
+ revert(user,null)
+ qdel(src)
return
else if(arePowerSystemsOn() && !(stat & NOPOWER))
user << "The airlock's motors resist your efforts to force it."
@@ -1102,6 +1091,43 @@ About the new airlock wires panel:
return
+/obj/machinery/door/airlock/proc/revert(mob/user as mob, var/direction)
+ var/obj/structure/door_assembly/DA = new assembly_type(loc)
+ DA.anchored = 1
+ DA.fingerprints += src.fingerprints
+ DA.fingerprintshidden += src.fingerprintshidden
+ DA.fingerprintslast = user.ckey
+ if (mineral)
+ DA.glass = mineral
+ else if (glass && !DA.glass)
+ DA.glass = 1
+
+ DA.state = 1
+ DA.created_name = name
+ DA.update_state()
+
+ var/obj/item/weapon/circuitboard/airlock/A
+
+ if (!electronics)
+ A = new/obj/item/weapon/circuitboard/airlock(loc)
+
+ if(req_access && req_access.len)
+ A.conf_access = req_access
+ else if(req_one_access && req_one_access.len)
+ A.conf_access = req_one_access
+ A.one_access = 1
+ else
+ A = electronics
+ electronics = null
+ A.loc = loc
+
+ if (operating == -1)
+ A.icon_state = "door_electronics_smoked"
+ operating = 0
+ if(direction)
+ A.throw_at(get_edge_target_turf(src, direction),10,4)
+ return DA //Returns the new assembly
+
/obj/machinery/door/airlock/plasma/attackby(C as obj, mob/user as mob)
if(C)
ignite(is_hot(C))
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 5912ac8fa90..f9f6d68f9b6 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -154,6 +154,7 @@
new /obj/item/weapon/melee/baton/loaded(src)
new /obj/item/weapon/gun/energy/taser(src)
new /obj/item/weapon/storage/box/bolas(src)
+ new /obj/item/weapon/batteringram(src)
return
@@ -189,6 +190,7 @@
new /obj/item/taperoll/police(src)
new /obj/item/device/hailer(src) //wonder if vg would spam this
new /obj/item/clothing/gloves/black(src)
+ new /obj/item/device/gps/secure(src)
return
diff --git a/code/modules/telesci/gps.dm b/code/modules/telesci/gps.dm
index c7c004eb37a..2f6b228b1b6 100644
--- a/code/modules/telesci/gps.dm
+++ b/code/modules/telesci/gps.dm
@@ -1,4 +1,6 @@
var/list/GPS_list = list()
+var/list/SPS_list = list()
+
/obj/item/device/gps
name = "global positioning system"
desc = "Helping lost spacemen find their way through the planets since 2016."
@@ -18,7 +20,10 @@ var/list/GPS_list = list()
overlays += "working"
/obj/item/device/gps/Destroy()
- GPS_list.Remove(src)
+ if(istype(src,/obj/item/device/gps/secure))
+ SPS_list.Remove(src)
+ else
+ GPS_list.Remove(src)
..()
/obj/item/device/gps/emp_act(severity)
@@ -32,13 +37,18 @@ var/list/GPS_list = list()
/obj/item/device/gps/attack_self(mob/user as mob)
var/obj/item/device/gps/t = ""
+ var/list/locallist = null
+ if(istype(src,/obj/item/device/gps/secure))
+ locallist = SPS_list.Copy()
+ else
+ locallist = GPS_list.Copy()
if(emped)
t += "ERROR"
else
t += "
Set Tag "
t += "
Tag: [gpstag]"
- for(var/obj/item/device/gps/G in GPS_list)
+ for(var/obj/item/device/gps/G in locallist)
var/turf/pos = get_turf(G)
var/area/gps_area = get_area(G)
var/tracked_gpstag = G.gpstag
@@ -101,3 +111,31 @@ var/list/GPS_list = list()
desc = "A more rugged looking GPS device. Useful for finding miners. Or their corpses."
icon_state = "gps-m"
gpstag = "MIN0"
+
+/obj/item/device/gps/secure
+ name = "secure positioning system"
+ desc = "A secure channel SPS with several features designed to keep its wearer safe."
+ icon_state = "sps"
+ gpstag = "SEC0"
+
+/obj/item/device/gps/secure/New()
+ SPS_list.Add(src)
+ gpstag = "SEC0"
+ name = "secure positioning system ([gpstag])"
+ overlays += "working"
+
+/obj/item/device/gps/secure/OnMobDeath(mob/wearer as mob)
+ ..()
+ for(var/obj/item/device/gps/secure/S in SPS_list)
+ S.announce(wearer, src, "died")
+
+/obj/item/device/gps/secure/dropped(mob/wearer as mob)
+ ..()
+ if(!istype(src.loc, /turf))
+ return
+ for(var/obj/item/device/gps/secure/S in SPS_list)
+ S.announce(wearer, src, "lost [wearer.gender == FEMALE ? "her" : "his"] SPS")
+
+/obj/item/device/gps/secure/proc/announce(var/mob/living/carbon/human/wearer, var/obj/item/device/gps/secure/SPS, var/reason)
+ src.visible_message("Your SPS beeps: Warning! [wearer] has [reason] at [get_area(SPS)].")
+
diff --git a/icons/obj/telescience.dmi b/icons/obj/telescience.dmi
index afbfa6573bd..5f05eab65fe 100644
Binary files a/icons/obj/telescience.dmi and b/icons/obj/telescience.dmi differ
diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi
index fcdc93070f0..a054a2c7db4 100644
Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ