Make multitile airlocks/poddoors directional (#28928)

* Update multitile airlocks

* Update shuttle_rotate.dm

* updatepaths

* code review changes + linters

* i failed my own linters

* updatepaths
This commit is contained in:
kyunkyunkyun
2025-05-04 02:35:33 +00:00
committed by GitHub
parent 37a4e6efe6
commit ec6a23eec5
43 changed files with 412 additions and 227 deletions
+15
View File
@@ -33,3 +33,18 @@
dir = WEST; \
pixel_x = offset_west; \
}
#define MAPPING_DIRECTIONAL_HELPERS_MULTITILE(path, offset) ##path/directional/north {\
dir = NORTH; \
} \
##path/directional/south {\
dir = SOUTH; \
pixel_y = -offset; \
} \
##path/directional/east {\
dir = EAST; \
} \
##path/directional/west {\
dir = WEST; \
pixel_x = -offset; \
}
+1 -1
View File
@@ -1330,7 +1330,7 @@ GLOBAL_LIST_EMPTY(airlock_emissive_underlays)
operating = NONE
recalculate_atmos_connectivity()
if(safe)
CheckForMobs()
check_for_mobs()
return TRUE
/obj/machinery/door/airlock/lock(forced=0)
+42 -5
View File
@@ -654,7 +654,6 @@
//Terribly sorry for the code doubling, but things go derpy otherwise.
/obj/machinery/door/airlock/multi_tile
name = "large airlock"
dir = EAST
width = 2
icon = 'icons/obj/doors/airlocks/glass_large/glass_large.dmi'
overlays_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
@@ -662,9 +661,13 @@
assemblytype = /obj/structure/door_assembly/multi_tile
paintable = FALSE
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/airlock/multi_tile, 32)
/obj/machinery/door/airlock/multi_tile/narsie_act()
return
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/airlock/multi_tile/glass, 32)
/obj/machinery/door/airlock/multi_tile/glass
opacity = FALSE
glass = TRUE
@@ -678,17 +681,38 @@
opacity = TRUE
anchored = TRUE
invisibility = INVISIBILITY_MAXIMUM
obj_integrity = INFINITY // our parent airlock/assembly will handle that
//atmos_canpass = CANPASS_DENSITY
/// The door/airlock this fluff panel is attached to
var/obj/machinery/door/filled_airlock
/// The assembly this fluff panel is attached to
var/obj/structure/door_assembly/filled_assembly
/obj/airlock_filler_object/Bumped(atom/A)
if(isnull(filled_airlock))
stack_trace("Someone bumped into an airlock filler with no parent airlock specified!")
return filled_airlock.Bumped(A)
if(filled_airlock)
return filled_airlock.Bumped(A)
if(filled_assembly)
return filled_assembly.Bumped(A)
else
stack_trace("Someone bumped into an airlock filler with no parent airlock/assembly specified!")
/obj/airlock_filler_object/Destroy()
filled_airlock = null
filled_assembly = null
return ..()
/obj/airlock_filler_object/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = TRUE, attack_dir, armour_penetration_flat = 0, armour_penetration_percentage = 0)
if(filled_airlock)
filled_airlock.take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir)
else if(filled_assembly)
filled_assembly.take_damage(damage_amount, damage_type, damage_flag, sound_effect, attack_dir)
return ..()
/obj/airlock_filler_object/ex_act(severity)
if(filled_airlock)
filled_airlock.ex_act(severity)
else if(filled_assembly)
filled_assembly.ex_act(severity)
return ..()
/// Multi-tile airlocks pair with a filler panel, if one goes so does the other.
@@ -699,18 +723,31 @@
filled_airlock = parent_airlock
RegisterSignal(filled_airlock, COMSIG_PARENT_QDELETING, PROC_REF(no_airlock))
/obj/airlock_filler_object/proc/pair_assembly(obj/structure/door_assembly/parent_assembly)
if(isnull(parent_assembly))
stack_trace("Attempted to pair an airlock filler with no parent assembly specified!")
filled_assembly = parent_assembly
RegisterSignal(filled_assembly, COMSIG_PARENT_QDELETING, PROC_REF(no_assembly))
/obj/airlock_filler_object/proc/no_airlock()
UnregisterSignal(filled_airlock)
qdel(src)
/obj/airlock_filler_object/proc/no_assembly()
UnregisterSignal(filled_assembly)
qdel(src)
/// Multi-tile airlocks (using a filler panel) have special handling for movables with PASS_FLAG_GLASS
/obj/airlock_filler_object/CanPass(atom/movable/mover, border_dir)
if(mover == filled_assembly)
return TRUE
. = ..()
if(.)
return
if(istype(mover))
return !opacity
return !density
/obj/airlock_filler_object/singularity_act()
return
+59 -30
View File
@@ -53,6 +53,8 @@
/// How much this door reduces superconductivity to when closed.
var/superconductivity = DOOR_HEAT_TRANSFER_COEFFICIENT
/// So explosion doesn't deal extra damage for multitile airlocks
COOLDOWN_DECLARE(explosion_cooldown)
/obj/machinery/door/Initialize(mapload)
@@ -88,6 +90,13 @@
return
update_icon()
/obj/machinery/door/ex_act()
if(width > 1 && fillers)
if(!COOLDOWN_FINISHED(src, explosion_cooldown))
return
COOLDOWN_START(src, explosion_cooldown, 1 SECONDS)
return ..()
/obj/machinery/door/Destroy()
density = FALSE
recalculate_atmos_connectivity()
@@ -425,33 +434,42 @@
recalculate_atmos_connectivity()
update_freelook_sight()
if(safe)
CheckForMobs()
check_for_mobs()
else
crush()
return TRUE
/obj/machinery/door/proc/CheckForMobs()
if(locate(/mob/living) in get_turf(src))
sleep(1)
open()
/obj/machinery/door/proc/get_airlock_turfs()
var/list/airlock_turfs = list(get_turf(src))
if(width > 1 && fillers)
for(var/obj/F in fillers)
airlock_turfs |= get_turf(F)
return airlock_turfs
/obj/machinery/door/proc/check_for_mobs()
for(var/turf/T in get_airlock_turfs())
if(locate(/mob/living) in T)
sleep(1)
open()
break
/obj/machinery/door/proc/crush()
for(var/mob/living/L in get_turf(src))
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
if(isalien(L)) //For xenos
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
L.emote("roar")
else if(ishuman(L)) //For humans
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
if(L.stat == CONSCIOUS)
L.emote("scream")
L.Weaken(10 SECONDS)
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
var/turf/location = get_turf(src)
L.add_splatter_floor(location)
for(var/obj/mecha/M in get_turf(src))
M.take_damage(DOOR_CRUSH_DAMAGE)
for(var/turf/T in get_airlock_turfs())
for(var/mob/living/L in T)
L.visible_message("<span class='warning'>[src] closes on [L], crushing [L.p_them()]!</span>", "<span class='userdanger'>[src] closes on you and crushes you!</span>")
if(isalien(L)) //For xenos
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE * 1.5) //Xenos go into crit after aproximately the same amount of crushes as humans.
L.emote("roar")
else if(ishuman(L)) //For humans
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
if(L.stat == CONSCIOUS)
L.emote("scream")
L.Weaken(10 SECONDS)
else //for simple_animals & borgs
L.adjustBruteLoss(DOOR_CRUSH_DAMAGE)
L.add_splatter_floor(T)
for(var/obj/mecha/M in T)
M.take_damage(DOOR_CRUSH_DAMAGE)
/obj/machinery/door/proc/requiresID()
return 1
@@ -529,11 +547,6 @@
* Checks which way the airlock is facing and adjusts the direction accordingly.
* For use with multi-tile airlocks.
*/
/obj/machinery/door/proc/get_adjusted_dir(dir)
if(dir in list(EAST, WEST))
return EAST
else
return NORTH
/**
* Sets the bounds of the airlock. For use with multi-tile airlocks.
@@ -550,25 +563,41 @@
if(dir in list(EAST, WEST))
bound_width = width * world.icon_size
bound_height = world.icon_size
bound_y = 0
pixel_y = 0
if(dir == WEST)
bound_x = -(width - 1) * world.icon_size
pixel_x = -(width - 1) * world.icon_size
else
bound_x = 0
pixel_x = 0
else
bound_width = world.icon_size
bound_height = width * world.icon_size
bound_x = 0
pixel_x = 0
if(dir == SOUTH)
bound_y = -(width - 1) * world.icon_size
pixel_y = -(width - 1) * world.icon_size
else
bound_y = 0
pixel_y = 0
LAZYINITLIST(fillers)
var/adjusted_dir = get_adjusted_dir(dir)
var/obj/last_filler = src
for(var/i = 1, i < width, i++)
for(var/i in 1 to width)
var/obj/airlock_filler_object/filler
if(length(fillers) < i)
filler = new
filler = new(src)
filler.pair_airlock(src)
fillers.Add(filler)
else
filler = fillers[i]
filler.loc = get_step(last_filler, adjusted_dir)
filler.loc = get_step(last_filler, dir)
filler.density = density
filler.set_opacity(opacity)
+27 -47
View File
@@ -92,41 +92,33 @@
layer = CLOSED_BLASTDOOR_LAYER
closingLayer = CLOSED_BLASTDOOR_LAYER
/obj/machinery/door/poddoor/multi_tile/four_tile_ver
icon = 'icons/obj/doors/1x4blast_vert.dmi'
width = 4
dir = NORTH
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/poddoor/multi_tile, 0, 0)
/obj/machinery/door/poddoor/multi_tile/three_tile_ver
icon = 'icons/obj/doors/1x3blast_vert.dmi'
width = 3
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/two_tile_ver
icon = 'icons/obj/doors/1x2blast_vert.dmi'
/obj/machinery/door/poddoor/multi_tile/double
icon = 'icons/obj/doors/blastdoor_1x2.dmi'
width = 2
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/four_tile_hor
icon = 'icons/obj/doors/1x4blast_hor.dmi'
width = 4
dir = EAST
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/double, 32)
/obj/machinery/door/poddoor/multi_tile/three_tile_hor
icon = 'icons/obj/doors/1x3blast_hor.dmi'
/obj/machinery/door/poddoor/multi_tile/triple
icon = 'icons/obj/doors/blastdoor_1x3.dmi'
width = 3
dir = EAST
/obj/machinery/door/poddoor/multi_tile/two_tile_hor
icon = 'icons/obj/doors/1x2blast_hor.dmi'
width = 2
dir = EAST
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/triple, 64)
/obj/machinery/door/poddoor/multi_tile/quad
icon = 'icons/obj/doors/blastdoor_1x4.dmi'
width = 4
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/quad, 96)
/obj/machinery/door/poddoor/multi_tile/impassable
desc = "A heavy duty blast door that opens mechanically. Looks even tougher than usual."
resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF
move_resist = INFINITY
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/door/poddoor/multi_tile/impassable, 0, 0)
/obj/machinery/door/poddoor/multi_tile/impassable/hostile_lockdown()
return
@@ -137,32 +129,20 @@
to_chat(user, "<span class='notice'>The electronic systems in this door are far too advanced for your primitive hacking peripherals.</span>")
return
/obj/machinery/door/poddoor/multi_tile/impassable/four_tile_ver
icon = 'icons/obj/doors/1x4blast_vert.dmi'
width = 4
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/impassable/three_tile_ver
icon = 'icons/obj/doors/1x3blast_vert.dmi'
width = 3
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/impassable/two_tile_ver
icon = 'icons/obj/doors/1x2blast_vert.dmi'
/obj/machinery/door/poddoor/multi_tile/impassable/double
icon = 'icons/obj/doors/blastdoor_1x2.dmi'
width = 2
dir = NORTH
/obj/machinery/door/poddoor/multi_tile/impassable/four_tile_hor
icon = 'icons/obj/doors/1x4blast_hor.dmi'
width = 4
dir = EAST
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/impassable/double, 32)
/obj/machinery/door/poddoor/multi_tile/impassable/three_tile_hor
icon = 'icons/obj/doors/1x3blast_hor.dmi'
/obj/machinery/door/poddoor/multi_tile/impassable/triple
icon = 'icons/obj/doors/blastdoor_1x3.dmi'
width = 3
dir = EAST
/obj/machinery/door/poddoor/multi_tile/impassable/two_tile_hor
icon = 'icons/obj/doors/1x2blast_hor.dmi'
width = 2
dir = EAST
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/impassable/triple, 64)
/obj/machinery/door/poddoor/multi_tile/impassable/quad
icon = 'icons/obj/doors/blastdoor_1x4.dmi'
width = 4
MAPPING_DIRECTIONAL_HELPERS_MULTITILE(/obj/machinery/door/poddoor/multi_tile/impassable/quad, 96)
@@ -136,29 +136,80 @@
icon = 'icons/obj/doors/airlocks/glass_large/glass_large.dmi'
base_name = "large airlock"
overlays_file = 'icons/obj/doors/airlocks/glass_large/overlays.dmi'
dir = EAST
var/width = 2
var/list/fillers
airlock_type = /obj/machinery/door/airlock/multi_tile
glass_type = /obj/machinery/door/airlock/multi_tile/glass
material_amt = 8
/obj/structure/door_assembly/multi_tile/Initialize(mapload)
. = ..()
if(dir in list(EAST, WEST))
bound_width = width * world.icon_size
bound_height = world.icon_size
else
bound_width = world.icon_size
bound_height = width * world.icon_size
update_bounds()
/obj/structure/door_assembly/multi_tile/Move()
/obj/structure/door_assembly/multi_tile/Move(new_loc, new_dir)
. = ..()
update_bounds()
/obj/structure/door_assembly/multi_tile/start_pulling(atom/movable/AM, state, force, show_message)
. = ..()
if(fillers)
for(var/i in 1 to width)
var/obj/airlock_filler_object/filler = fillers[i]
filler.density = FALSE
/obj/structure/door_assembly/multi_tile/stop_pulling()
. = ..()
if(fillers)
for(var/i in 1 to width)
var/obj/airlock_filler_object/filler = fillers[i]
filler.density = TRUE
/obj/structure/door_assembly/multi_tile/proc/update_bounds()
if(width <= 1)
return
if(dir in list(EAST, WEST))
bound_width = width * world.icon_size
bound_height = world.icon_size
bound_y = 0
pixel_y = 0
if(dir == WEST)
bound_x = -(width - 1) * world.icon_size
pixel_x = -(width - 1) * world.icon_size
else
bound_x = 0
pixel_x = 0
else
bound_width = world.icon_size
bound_height = width * world.icon_size
bound_x = 0
pixel_x = 0
if(dir == SOUTH)
bound_y = -(width - 1) * world.icon_size
pixel_y = -(width - 1) * world.icon_size
else
bound_y = 0
pixel_y = 0
QDEL_LIST_CONTENTS(fillers)
LAZYINITLIST(fillers)
var/obj/last_filler = src
for(var/i in 1 to width)
var/obj/airlock_filler_object/filler
if(length(fillers) < i)
filler = new(src)
filler.pair_assembly(src)
fillers += filler
else
filler = fillers[i]
filler.loc = get_step(last_filler, dir)
filler.set_opacity(opacity)
last_filler = filler
/obj/structure/door_assembly/door_assembly_cult
name = "cult airlock assembly"
+9
View File
@@ -97,3 +97,12 @@ If ever any of these procs are useful for non-shuttles, rename it to proc/rotate
/obj/machinery/gravity_generator/shuttleRotate(rotation, params)
params = NONE
return ..()
// Updates airlocks' icon
/obj/machinery/door/shuttleRotate(rotation, params)
..()
update_bounds()
/obj/structure/door_assembly/multi_tile/shuttleRotate(rotation, params)
..()
update_bounds()