Skip to content
This repository has been archived by the owner on Feb 19, 2023. It is now read-only.

Commit

Permalink
Airlock Seals 2: I'm dumb and a fool edition (#53114)
Browse files Browse the repository at this point in the history
Adds door seals to the game, inspired by the ones used in Alien Isolation and SOMA. Trivially easy for a human to remove, but makes it a nightmare to try and smash through if you're an alien, an evil robot, or don't have hands. I also slightly changed how airlock reinforcement works, as now there are two ways to increase the integrity, the previous way of just resetting the max_integrity after the removal of the plating wouldn't work.
  • Loading branch information
Jimmius authored Sep 13, 2020
1 parent 899a9e0 commit a9c538f
Show file tree
Hide file tree
Showing 23 changed files with 140 additions and 7 deletions.
96 changes: 90 additions & 6 deletions code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@

#define AIRLOCK_INTEGRITY_N 300 // Normal airlock integrity
#define AIRLOCK_INTEGRITY_MULTIPLIER 1.5 // How much reinforced doors health increases
/// How much extra health airlocks get when braced with a seal
#define AIRLOCK_SEAL_MULTIPLIER 2
#define AIRLOCK_DAMAGE_DEFLECTION_N 21 // Normal airlock damage deflection
#define AIRLOCK_DAMAGE_DEFLECTION_R 30 // Reinforced airlock damage deflection

Expand Down Expand Up @@ -70,6 +72,8 @@
var/obj/item/electronics/airlock/electronics
COOLDOWN_DECLARE(shockCooldown)
var/obj/item/note //Any papers pinned to the airlock
/// The seal on the airlock
var/obj/item/seal
var/detonated = FALSE
var/abandoned = FALSE
var/doorOpen = 'sound/machines/airlock.ogg'
Expand Down Expand Up @@ -294,6 +298,7 @@
for(var/obj/machinery/door_buttons/D in GLOB.machines)
D.removeMe(src)
QDEL_NULL(note)
QDEL_NULL(seal)
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.remove_from_hud(src)
return ..()
Expand All @@ -302,6 +307,9 @@
if(A == note)
note = null
update_icon()
if(A == seal)
seal = null
update_icon()

/obj/machinery/door/airlock/bumpopen(mob/living/user) //Airlocks now zap you when you 'bump' them open when they're electrified. --NeoFite
if(!issilicon(usr))
Expand Down Expand Up @@ -431,6 +439,7 @@
var/mutable_appearance/damag_overlay
var/mutable_appearance/sparks_overlay
var/mutable_appearance/note_overlay
var/mutable_appearance/seal_overlay
var/notetype = note_type()

switch(state)
Expand All @@ -447,6 +456,8 @@
panel_overlay = get_airlock_overlay("panel_closed", overlays_file)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(seal)
seal_overlay = get_airlock_overlay("sealed", overlays_file)
if(obj_integrity < integrity_failure * max_integrity)
damag_overlay = get_airlock_overlay("sparks_broken", overlays_file)
else if(obj_integrity < (0.75 * max_integrity))
Expand Down Expand Up @@ -478,6 +489,8 @@
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(seal)
seal_overlay = get_airlock_overlay("sealed", overlays_file)
lights_overlay = get_airlock_overlay("lights_denied", overlays_file)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)
Expand All @@ -500,6 +513,8 @@
damag_overlay = get_airlock_overlay("sparks_damaged", overlays_file)
if(welded)
weld_overlay = get_airlock_overlay("welded", overlays_file)
if(seal)
seal_overlay = get_airlock_overlay("sealed", overlays_file)
if(note)
note_overlay = get_airlock_overlay(notetype, note_overlay_file)

Expand Down Expand Up @@ -560,6 +575,7 @@
add_overlay(sparks_overlay)
add_overlay(damag_overlay)
add_overlay(note_overlay)
add_overlay(seal_overlay)
check_unres()

/proc/get_airlock_overlay(icon_state, icon_file)
Expand Down Expand Up @@ -618,7 +634,8 @@
else
. += "There's a [note.name] pinned to the front..."
. += note.examine(user)

if(seal)
. += "It's been braced with a pneumatic seal."
if(panel_open)
switch(security_level)
if(AIRLOCK_SECURITY_NONE)
Expand Down Expand Up @@ -813,7 +830,7 @@
user.visible_message("<span class='notice'>[user] reinforces \the [src] with plasteel.</span>",
"<span class='notice'>You reinforce \the [src] with plasteel.</span>")
security_level = AIRLOCK_SECURITY_PLASTEEL
modify_max_integrity(normal_integrity * AIRLOCK_INTEGRITY_MULTIPLIER)
modify_max_integrity(max_integrity * AIRLOCK_INTEGRITY_MULTIPLIER)
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_R
update_icon()
return
Expand Down Expand Up @@ -844,7 +861,7 @@
user.visible_message("<span class='notice'>[user] remove \the [src]'s shielding.</span>",
"<span class='notice'>You remove \the [src]'s inner shielding.</span>")
security_level = AIRLOCK_SECURITY_NONE
modify_max_integrity(normal_integrity)
modify_max_integrity(max_integrity / AIRLOCK_INTEGRITY_MULTIPLIER)
damage_deflection = AIRLOCK_DAMAGE_DEFLECTION_N
spawn_atom_to_turf(/obj/item/stack/sheet/plasteel, user.loc, 1)
update_icon()
Expand Down Expand Up @@ -922,6 +939,33 @@
cable.plugin(src, user)
else if(istype(C, /obj/item/airlock_painter))
change_paintjob(C, user)
else if(istype(C, /obj/item/door_seal)) //adding the seal
var/obj/item/door_seal/airlockseal = C
if(!density)
to_chat(user, "<span class='warning'>[src] must be closed before you can seal it!</span>")
return
if(seal)
to_chat(user, "<span class='warning'>[src] has already been sealed!</span>")
return
user.visible_message("<span class='notice'>[user] begins sealing [src].</span>", "<span class='notice'>You begin sealing [src].</span>")
playsound(src, 'sound/items/jaws_pry.ogg', 30, TRUE)
if(!do_after(user, airlockseal.seal_time, target = src))
return
if(!density)
to_chat(user, "<span class='warning'>[src] must be closed before you can seal it!</span>")
return
if(seal)
to_chat(user, "<span class='warning'>[src] has already been sealed!</span>")
return
if(!user.transferItemToLoc(airlockseal, src))
to_chat(user, "<span class='warning'>For some reason, you can't attach [airlockseal]!</span>")
return
playsound(src, 'sound/machines/airlockforced.ogg', 30, TRUE)
user.visible_message("<span class='notice'>[user] finishes sealing [src].</span>", "<span class='notice'>You finish sealing [src].</span>")
seal = airlockseal
modify_max_integrity(max_integrity * AIRLOCK_SEAL_MULTIPLIER)
update_icon()

else if(istype(C, /obj/item/paper) || istype(C, /obj/item/photo))
if(note)
to_chat(user, "<span class='warning'>There's already something pinned to this airlock! Use wirecutters to remove it.</span>")
Expand All @@ -938,6 +982,9 @@

/obj/machinery/door/airlock/try_to_weld(obj/item/weldingtool/W, mob/user)
if(!operating && density)
if(seal)
to_chat(user, "<span class='warning'>[src] is blocked by a seal!</span>")
return
if(user.a_intent != INTENT_HELP)
if(!W.tool_start_check(user, amount=0))
return
Expand Down Expand Up @@ -968,6 +1015,36 @@
/obj/machinery/door/airlock/proc/weld_checks(obj/item/weldingtool/W, mob/user)
return !operating && density

/**
* Used when attempting to remove a seal from an airlock
*
* Called when attacking an airlock with an empty hand, returns TRUE (there was a seal and we removed it, or failed to remove it)
* or FALSE (there was no seal)
* Arguments:
* * user - Whoever is attempting to remove the seal
*/
/obj/machinery/door/airlock/try_remove_seal(mob/living/user)
if(!seal)
return FALSE
var/obj/item/door_seal/airlockseal = seal
if(!ishuman(user))
to_chat(user, text("<span class='warning'>You don't have the dexterity to remove the seal!</span>"))
return TRUE
user.visible_message("<span class='notice'>[user] begins removing the seal from [src].</span>", "<span class='notice'>You begin removing [src]'s pneumatic seal.</span>")
playsound(src, 'sound/machines/airlockforced.ogg', 30, TRUE)
if(!do_after(user, airlockseal.unseal_time, target = src))
return TRUE
if(!seal)
return TRUE
playsound(src, 'sound/items/jaws_pry.ogg', 30, TRUE)
airlockseal.forceMove(get_turf(user))
user.visible_message("<span class='notice'>[user] finishes removing the seal from [src].</span>", "<span class='notice'>You finish removing [src]'s pneumatic seal.</span>")
seal = null
modify_max_integrity(max_integrity / AIRLOCK_SEAL_MULTIPLIER)
update_icon()
return TRUE


/obj/machinery/door/airlock/try_to_crowbar(obj/item/I, mob/living/user, forced = FALSE)
if(I)
var/beingcrowbarred = (I.tool_behaviour == TOOL_CROWBAR)
Expand All @@ -977,6 +1054,9 @@
if(I.use_tool(src, user, 40, volume=100))
deconstruct(TRUE, user)
return
if(seal)
to_chat(user, "<span class='warning'>Remove the seal first!</span>")
return
if(locked)
to_chat(user, "<span class='warning'>The airlock's bolts prevent it from being forced!</span>")
return
Expand Down Expand Up @@ -1018,7 +1098,7 @@


/obj/machinery/door/airlock/open(forced=0)
if( operating || welded || locked )
if( operating || welded || locked || seal )
return FALSE
if(!forced)
if(!hasPower() || wires.is_cut(WIRE_OPEN))
Expand Down Expand Up @@ -1060,7 +1140,7 @@


/obj/machinery/door/airlock/close(forced=0)
if(operating || welded || locked)
if(operating || welded || locked || seal)
return
if(density)
return TRUE
Expand Down Expand Up @@ -1175,7 +1255,7 @@
return
if(!density) //Already open
return ..()
if(locked || welded) //Extremely generic, as aliens only understand the basics of how airlocks work.
if(locked || welded || seal) //Extremely generic, as aliens only understand the basics of how airlocks work.
if(user.a_intent == INTENT_HARM)
return ..()
to_chat(user, "<span class='warning'>[src] refuses to budge!</span>")
Expand Down Expand Up @@ -1294,6 +1374,9 @@
/obj/machinery/door/airlock/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
switch(the_rcd.mode)
if(RCD_DECONSTRUCT)
if(seal)
to_chat(user, "<span class='notice'>[src]'s seal needs to be removed first.</span>")
return FALSE
if(security_level != AIRLOCK_SECURITY_NONE)
to_chat(user, "<span class='notice'>[src]'s reinforcement needs to be removed first.</span>")
return FALSE
Expand Down Expand Up @@ -1499,6 +1582,7 @@

#undef AIRLOCK_INTEGRITY_N
#undef AIRLOCK_INTEGRITY_MULTIPLIER
#undef AIRLOCK_SEAL_MULTIPLIER
#undef AIRLOCK_DAMAGE_DEFLECTION_N
#undef AIRLOCK_DAMAGE_DEFLECTION_R

Expand Down
14 changes: 14 additions & 0 deletions code/game/machinery/doors/door.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
var/safety_mode = FALSE ///Whether or not the airlock can be opened with bare hands while unpowered
var/can_crush = TRUE /// Whether or not the door can crush mobs.


/obj/machinery/door/examine(mob/user)
. = ..()
if(red_alert_access)
Expand Down Expand Up @@ -97,6 +98,17 @@
return TRUE
return FALSE

/**
* Called when attempting to remove the seal from an airlock
*
* Here because we need to call it and return if there was a seal so we don't try to open the door
* or try its safety lock while it's sealed
* Arguments:
* * user - the mob attempting to remove the seal
*/
/obj/machinery/door/proc/try_remove_seal(mob/user)
return

/obj/machinery/door/Bumped(atom/movable/AM)
. = ..()
if(operating || (obj_flags & EMAGGED))
Expand Down Expand Up @@ -159,6 +171,8 @@
. = ..()
if(.)
return
if(try_remove_seal(user))
return
if(try_safety_unlock(user))
return
return try_to_activate_door(user)
Expand Down
25 changes: 25 additions & 0 deletions code/game/objects/items/door_seal.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/obj/item/door_seal
name = "pneumatic seal"
desc = "A brace used to seal and reinforce an airlock. Useful for making areas inaccessible to those without opposable thumbs."
icon = 'icons/obj/items_and_weapons.dmi'
icon_state = "pneumatic_seal"
lefthand_file = 'icons/mob/inhands/items_lefthand.dmi'
righthand_file = 'icons/mob/inhands/items_righthand.dmi'
flags_1 = CONDUCT_1
resistance_flags = FIRE_PROOF | ACID_PROOF
force = 5
throwforce = 5
throw_speed = 2
throw_range = 1
w_class = WEIGHT_CLASS_BULKY
custom_materials = list(/datum/material/iron=5000,/datum/material/plasma=500)
/// how long the seal takes to place on the door
var/seal_time = 3 SECONDS
/// how long it takes to remove the seal from a door
var/unseal_time = 2 SECONDS

/obj/item/door_seal/suicide_act(mob/user)
user.visible_message("<span class='suicide'>[user] is sealing [user.p_them()]self off from the world with [src]! It looks like [user.p_theyre()] trying to commit suicide!</span>")
playsound(src, 'sound/items/jaws_pry.ogg', 30, TRUE)
return(BRUTELOSS)

9 changes: 9 additions & 0 deletions code/modules/research/designs/misc_designs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,15 @@
build_path = /obj/item/bikehorn/rubberducky/plasticducky
category = list("Equipment")

/datum/design/pneumatic_seal
name = "Pneumatic Seal"
desc = "A heavy brace used to seal doors. Useful for keeping out people without the dexterity to remove it."
id = "pneumatic_seal"
build_type = PROTOLATHE
materials = list(/datum/material/iron = 20000, /datum/material/plasma = 10000)
build_path = /obj/item/door_seal
category = list("Equipment")
departmental_flags = DEPARTMENTAL_FLAG_ENGINEERING | DEPARTMENTAL_FLAG_SECURITY

/////////////////////////////////////////
////////////Janitor Designs//////////////
Expand Down
2 changes: 1 addition & 1 deletion code/modules/research/techweb/all_nodes.dm
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@
design_ids = list("solarcontrol", "recharger", "powermonitor", "rped", "pacman", "adv_capacitor", "adv_scanning", "w-recycler" , "emitter", "high_cell", "adv_matter_bin", "scanner_gate",
"atmosalerts", "atmos_control", "recycler", "autolathe", "high_micro_laser", "nano_mani", "mesons", "welding_goggles", "thermomachine", "rad_collector", "tesla_coil", "grounding_rod",
"apc_control", "cell_charger", "power control", "airlock_board", "firelock_board", "airalarm_electronics", "firealarm_electronics", "cell_charger", "stack_console", "stack_machine",
"oxygen_tank", "plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt", "electrolyzer", "adv_electrolite")
"oxygen_tank", "plasma_tank", "emergency_oxygen", "emergency_oxygen_engi", "plasmaman_tank_belt", "electrolyzer", "adv_electrolite", "pneumatic_seal")
research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 7500)

/datum/techweb_node/adv_engi
Expand Down
Binary file modified icons/mob/inhands/items_lefthand.dmi
Binary file not shown.
Binary file modified icons/mob/inhands/items_righthand.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/abductor/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/centcom/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/clockwork/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/cult/runed/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/cult/unruned/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/external/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/glass_large/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/hatch/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/highsec/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/shuttle/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/station/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/station2/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/survival/survival_overlays.dmi
Binary file not shown.
Binary file modified icons/obj/doors/airlocks/vault/overlays.dmi
Binary file not shown.
Binary file modified icons/obj/items_and_weapons.dmi
Binary file not shown.
1 change: 1 addition & 0 deletions tgstation.dme
Original file line number Diff line number Diff line change
Expand Up @@ -983,6 +983,7 @@
#include "code\game\objects\items\dice.dm"
#include "code\game\objects\items\dna_injector.dm"
#include "code\game\objects\items\documents.dm"
#include "code\game\objects\items\door_seal.dm"
#include "code\game\objects\items\dualsaber.dm"
#include "code\game\objects\items\eightball.dm"
#include "code\game\objects\items\emags.dm"
Expand Down

0 comments on commit a9c538f

Please sign in to comment.