[MIRROR] Airlock Seals 2: I'm dumb and a fool edition (#791)

* Airlock Seals 2: I'm dumb and a fool edition (#53114)

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.

* Airlock Seals 2: I'm dumb and a fool edition

Co-authored-by: Jimmius <huw4@btinternet.com>
This commit is contained in:
SkyratBot
2020-09-14 00:20:38 +02:00
committed by GitHub
parent a1cbb903f9
commit 0ffccf8554
23 changed files with 140 additions and 7 deletions
+90 -6
View File
@@ -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
@@ -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'
@@ -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 ..()
@@ -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))
@@ -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)
@@ -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))
@@ -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)
@@ -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)
@@ -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)
@@ -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)
@@ -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
@@ -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()
@@ -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>")
@@ -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
@@ -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)
@@ -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
@@ -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))
@@ -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
@@ -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>")
@@ -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
@@ -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
+14
View File
@@ -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)
@@ -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))
@@ -159,6 +171,8 @@
. = ..()
if(.)
return
if(try_remove_seal(user))
return
if(try_safety_unlock(user))
return
return try_to_activate_door(user)
+25
View File
@@ -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)
@@ -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//////////////
+1 -1
View File
@@ -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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.5 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 105 KiB

+1
View File
@@ -984,6 +984,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"