Skip to content

Commit

Permalink
Fix dropship door stuck and door refactoring (#7712)
Browse files Browse the repository at this point in the history
# About the pull request

This PR fixes a multitude of oversights with doors and makes it so
dropship doors closing now also throws objects. There's a lot of code
touched by this so there's very likely further changes that need to be
made (e.g. ~~how do vehicles behave with it, how do resin constructions
behave with it~~, are there weird prying issues now, etc).

# Explain why it's good for the game

Fixes #7709 

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>

Airlock spamming:
https://youtu.be/U9icC16jJcA

Objects in airlock:

![throw](https://github.com/user-attachments/assets/893c33f8-08ac-4ca9-ac74-6ffc758b7362)

Vehicle in airlock:

![arc](https://github.com/user-attachments/assets/00bfab6b-e5fc-4d14-b7e8-0cda6ec9bcec)

Resin in airlock:

![resin](https://github.com/user-attachments/assets/fa75c3b2-3dfe-45dc-aa71-edf39f2e0015)

</details>


# Changelog
:cl: Drathek
add: Dropship airlocks that force close now also throw objects (and
vehicles) out of their way
add: Airlocks can crush more xeno structures if they somehow got placed
there
fix: Fix doors sometimes ignoring force call (namely dropship airlocks)
fix: Fix doors not checking their turfs correctly (for example it
wouldn't throw mobs in its own turf)
refactor: Refactor some door code
fix: Fix vehicles in airlocks not being handled correctly (never
autoclosing again)
/:cl:
  • Loading branch information
Drulikar authored Dec 2, 2024
1 parent 0539608 commit fad71e1
Show file tree
Hide file tree
Showing 24 changed files with 441 additions and 259 deletions.
6 changes: 6 additions & 0 deletions code/__DEFINES/machinery.dm
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@
#define USE_POWER_IDLE 1
#define USE_POWER_ACTIVE 2

// door defines

#define DOOR_OPERATING_IDLE 0
#define DOOR_OPERATING_OPENING 1
#define DOOR_OPERATING_CLOSING 2

// used by the simulator to select mob type

#define HUMAN_MODE "Unarmoured Humans"
Expand Down
2 changes: 1 addition & 1 deletion code/datums/diseases/black_goo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@
if(do_after(user, 3 SECONDS, INTERRUPT_ALL, BUSY_ICON_HOSTILE) && D.density)
user.visible_message(SPAN_DANGER("[user] forces [D] open with their [name]."),
SPAN_DANGER("You force [D] open with your [name]."))
D.Open()
D.open()

/obj/item/reagent_container/food/drinks/bottle/black_goo
name = "strange bottle"
Expand Down
3 changes: 2 additions & 1 deletion code/game/machinery/door_display/door_display.dm
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@
if(!D.density)
continue
D.unlock(force)
D.open(force)
if(D.operating != DOOR_OPERATING_OPENING)
D.open(force)
open = TRUE

return TRUE
Expand Down
122 changes: 81 additions & 41 deletions code/game/machinery/doors/airlock.dm
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,8 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
var/assembly_type = /obj/structure/airlock_assembly
var/mineral = null
var/justzap = 0
var/safe = 1
/// Whether to delay closing when a mob is present
var/safe = TRUE
normalspeed = 1
var/obj/item/circuitboard/airlock/electronics = null
var/hasShocked = 0 //Prevents multiple shocks from happening
Expand All @@ -62,16 +63,22 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
var/announce_hacked = TRUE

//Resin constructions that will be SMUSHED by closing doors
var/static/list/resin_door_shmushereds = list(
var/static/list/resin_smushables = list(
/obj/effect/resin_construct/door,
/obj/structure/mineral_door/resin,
/obj/structure/bed/nest,
/obj/effect/alien/resin/spike,
/obj/effect/alien/resin/acid_pillar,
/obj/effect/alien/resin/shield_pillar,
/obj/effect/alien/resin/resin_pillar,
/obj/item/explosive/grenade/alien/acid,
/obj/structure/alien/movable_wall,
/turf/closed/wall/resin,
/obj/effect/alien/egg,
/obj/effect/alien/resin/fruit,
/obj/effect/alien/resin/special,
/obj/effect/alien/resin/construction,
/obj/item/reagent_container/food/snacks/resin_fruit,
)

/obj/structure/machinery/door/airlock/Destroy()
Expand All @@ -88,7 +95,7 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
spawn (openspeed)
justzap = 0
return
else if(user.hallucination > 50 && prob(10) && operating == 0)
else if(user.hallucination > 50 && prob(10) && !operating)
to_chat(user, SPAN_DANGER("<B>You feel a powerful shock course through your body!</B>"))
user.halloss += 10
user.apply_effect(10, STUN)
Expand Down Expand Up @@ -689,7 +696,7 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
if(operating == -1)
airlock_electronics.fried = TRUE
airlock_electronics.update_icon()
operating = 0
operating = DOOR_OPERATING_IDLE

msg_admin_niche("[key_name(user)] deconstructed [src] in [get_area(user)] ([user.loc.x],[user.loc.y],[user.loc.z])")
SEND_SIGNAL(user, COMSIG_MOB_DISASSEMBLE_AIRLOCK, src)
Expand Down Expand Up @@ -722,51 +729,74 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
else
return ..()


/obj/structure/machinery/door/airlock/open(forced=0)
if( operating || welded || locked || !loc)
/// Tries to open the door. If forced, operating checks and operable checks are skipped (so you need to prevent spamming yourself)
/obj/structure/machinery/door/airlock/open(forced = FALSE)
if(operating && !forced)
return FALSE
if(welded)
return FALSE
if(locked)
return FALSE
if(!density)
return TRUE
if(!loc)
return FALSE

if(!forced)
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR) )
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_OPEN_DOOR))
return FALSE

use_power(360) //360 W seems much more appropriate for an actuator moving an industrial door capable of crushing people
if(istype(src, /obj/structure/machinery/door/airlock/glass))
playsound(loc, 'sound/machines/windowdoor.ogg', 25, 1)
else
playsound(loc, 'sound/machines/airlock.ogg', 25, 0)
if(closeOther != null && istype(closeOther, /obj/structure/machinery/door/airlock/) && !closeOther.density)
closeOther.close()
return ..(forced)

. = ..()

if(!forced)
send_status()
return .

/// Tries to close the door. If forced, operating checks and operable checks are skipped (so you need to prevent spamming yourself)
/obj/structure/machinery/door/airlock/close(forced = FALSE)
if(operating || welded || locked || !loc)
return
if(operating && !forced)
return FALSE
if(welded)
return FALSE
if(locked)
return FALSE
if(!loc)
return FALSE

if(!forced)
if( !arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS) )
return
if(!arePowerSystemsOn() || isWireCut(AIRLOCK_WIRE_DOOR_BOLTS))
return FALSE

if(safe)
for(var/turf/turf in locs)
if(locate(/mob/living) in turf)
// playsound(loc, 'sound/machines/buzz-two.ogg', 25, 0) //THE BUZZING IT NEVER STOPS -Pete
spawn (60 + openspeed)
close()
return
// playsound(loc, 'sound/machines/buzz-two.ogg', 25, 0) //THE BUZZING IT NEVER STOPS -Pete
addtimer(CALLBACK(src, PROC_REF(close), forced), 6 SECONDS + openspeed, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)
return FALSE

for(var/turf/turf in locs)
for(var/mob/living/M in turf)
if(HAS_TRAIT(M, TRAIT_SUPER_STRONG))
M.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE)
for(var/mob/living/crushed in turf)
if(HAS_TRAIT(crushed, TRAIT_SUPER_STRONG))
crushed.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE)
else
M.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE)
M.set_effect(5, STUN)
M.set_effect(5, WEAKEN)
if(ishuman(M))
var/mob/living/carbon/human/H = M
if(H.pain.feels_pain)
M.emote("pain")
crushed.apply_damage(DOOR_CRUSH_DAMAGE, BRUTE)
crushed.set_effect(5, STUN)
crushed.set_effect(5, WEAKEN)
if(ishuman(crushed))
var/mob/living/carbon/human/crushed_human = crushed
if(crushed_human.pain.feels_pain)
crushed.emote("pain")
var/turf/location = loc
if(istype(location, /turf))
location.add_mob_blood(M)
location.add_mob_blood(crushed)

break_resin_objects()

Expand All @@ -779,28 +809,38 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
var/obj/structure/window/killthis = (locate(/obj/structure/window) in turf)
if(killthis)
killthis.ex_act(EXPLOSION_THRESHOLD_LOW)//Smashin windows
..()
return

. = ..()

if(!forced)
send_status()
return .

/obj/structure/machinery/door/airlock/proc/lock(forced = FALSE)
if((operating && !forced) || locked)
return
if(operating && !forced)
return FALSE
if(locked)
return FALSE

playsound(loc, 'sound/machines/hydraulics_1.ogg', 25)
locked = TRUE
visible_message(SPAN_NOTICE("\The [src] airlock emits a loud thunk, then a click."))
visible_message(SPAN_NOTICE("[src] airlock emits a loud thunk, then a click."))
update_icon()
return TRUE

/obj/structure/machinery/door/airlock/proc/unlock(forced=0)
if(operating || !locked) return
/obj/structure/machinery/door/airlock/proc/unlock(forced = FALSE)
if(operating && !forced)
return FALSE
if(!locked)
return FALSE

if(forced || (arePowerSystemsOn())) //only can raise bolts if power's on
if(forced || arePowerSystemsOn()) //only can raise bolts if power's on
locked = FALSE

playsound(loc, 'sound/machines/hydraulics_2.ogg', 25)
visible_message(SPAN_NOTICE("\The [src] airlock emits a click, then hums slightly."))
visible_message(SPAN_NOTICE("[src] airlock emits a click, then hums slightly."))
update_icon()
return TRUE

return FALSE

/obj/structure/machinery/door/airlock/Initialize()
Expand Down Expand Up @@ -840,10 +880,10 @@ GLOBAL_LIST_INIT(airlock_wire_descriptions, list(
for(var/turf/i in things_to_shmush)
things_to_shmush |= i.contents
for(var/x in things_to_shmush)
for(var/i in resin_door_shmushereds)
if(istype(x,i)) //I would like to just use a if(locate() in ) here but Im not gonna add every child to GLOB.resin_door_shmushereds so it works
for(var/i in resin_smushables)
if(istype(x,i)) //I would like to just use a if(locate() in ) here but Im not gonna add every child to GLOB.resin_smushables so it works
playsound(loc, "alien_resin_break", 25)
visible_message(SPAN_WARNING("The [src.name] closes on [x], shmushing it!"))
visible_message(SPAN_WARNING("The [src.name] closes on [x], smushing it!"))
if(isturf(x))
var/turf/closed/wall/resin_wall_to_destroy = x
resin_wall_to_destroy.dismantle_wall()
Expand Down
13 changes: 0 additions & 13 deletions code/game/machinery/doors/airlock_control.dm
Original file line number Diff line number Diff line change
Expand Up @@ -122,19 +122,6 @@

radio_connection.post_signal(src, signal, range = AIRLOCK_CONTROL_RANGE, filter = RADIO_AIRLOCK)


/obj/structure/machinery/door/airlock/open(forced)
. = ..()
if(!forced)
send_status()


/obj/structure/machinery/door/airlock/close(forced)
. = ..()
if(!forced)
send_status()


/obj/structure/machinery/door/airlock/proc/set_frequency(new_frequency)
SSradio.remove_object(src, frequency)
if(new_frequency)
Expand Down
8 changes: 4 additions & 4 deletions code/game/machinery/doors/airlock_types.dm
Original file line number Diff line number Diff line change
Expand Up @@ -860,10 +860,10 @@
/obj/structure/machinery/door/airlock/dropship_hatch/ex_act(severity)
return

/obj/structure/machinery/door/airlock/dropship_hatch/unlock()
if(is_reserved_level(z)) // in flight
return
..()
/obj/structure/machinery/door/airlock/dropship_hatch/unlock(forced = FALSE)
if(is_reserved_level(z) && !forced) // in flight
return FALSE
return ..()

/obj/structure/machinery/door/airlock/dropship_hatch/attack_alien(mob/living/carbon/xenomorph/xeno)

Expand Down
44 changes: 28 additions & 16 deletions code/game/machinery/doors/door.dm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
var/secondsElectrified = 0
var/visible = TRUE
var/panel_open = FALSE
var/operating = FALSE
var/operating = DOOR_OPERATING_IDLE
var/autoclose = FALSE
var/glass = FALSE
/// If FALSE it speeds up the autoclosing timing.
Expand Down Expand Up @@ -211,49 +211,61 @@
flick("door_deny", src)
return

/obj/structure/machinery/door/proc/open(forced)
/obj/structure/machinery/door/proc/open(forced = FALSE)
if(!density)
return TRUE
if(operating || !loc)
if(operating && !forced)
return FALSE
if(!loc)
return FALSE

operating = TRUE
operating = DOOR_OPERATING_OPENING
do_animate("opening")
set_opacity(FALSE)
if(length(filler_turfs))
change_filler_opacity(opacity)
addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed)
addtimer(CALLBACK(src, PROC_REF(finish_open)), openspeed, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)
return TRUE

/obj/structure/machinery/door/proc/finish_open()
if(operating != DOOR_OPERATING_OPENING)
return
if(QDELETED(src))
return // Specifically checked because of the possiible addtimer

layer = open_layer
density = FALSE
update_icon()

if(operating)
operating = FALSE
operating = DOOR_OPERATING_IDLE
if(autoclose)
addtimer(CALLBACK(src, PROC_REF(autoclose)), normalspeed ? 150 + openspeed : 5)
addtimer(CALLBACK(src, PROC_REF(autoclose)), normalspeed ? 15 SECONDS + openspeed : 5 DECISECONDS, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)

/obj/structure/machinery/door/proc/close()
if(density)
/obj/structure/machinery/door/proc/close(forced = FALSE)
if(density && !operating)
return TRUE
if(operating)
if(operating && !forced)
return FALSE
if(!loc)
return FALSE

operating = TRUE
src.density = TRUE
src.layer = closed_layer
operating = DOOR_OPERATING_CLOSING
density = TRUE
layer = closed_layer
do_animate("closing")
addtimer(CALLBACK(src, PROC_REF(finish_close)), openspeed)
addtimer(CALLBACK(src, PROC_REF(finish_close)), openspeed, TIMER_UNIQUE|TIMER_OVERRIDE|TIMER_NO_HASH_WAIT)
return TRUE

/obj/structure/machinery/door/proc/finish_close()
if(operating != DOOR_OPERATING_CLOSING)
return

update_icon()
if(visible && !glass)
set_opacity(TRUE)
if(length(filler_turfs))
change_filler_opacity(opacity)
operating = FALSE
operating = DOOR_OPERATING_IDLE

/obj/structure/machinery/door/proc/requiresID()
return TRUE
Expand Down
5 changes: 3 additions & 2 deletions code/game/machinery/doors/firedoor.dm
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
/obj/structure/machinery/door/firedoor/proc/latetoggle()
if(operating || !nextstate)
return

switch(nextstate)
if(OPEN)
nextstate = null
Expand All @@ -241,14 +242,14 @@
close()
return

/obj/structure/machinery/door/firedoor/close()
/obj/structure/machinery/door/firedoor/close(forced = FALSE)
latetoggle()
return ..()

/obj/structure/machinery/door/firedoor/open(forced = FALSE)
if(!forced)
if(inoperable())
return //needs power to open unless it was forced
return FALSE //needs power to open unless it was forced
else
use_power(360)
latetoggle()
Expand Down
Loading

0 comments on commit fad71e1

Please sign in to comment.