mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-11 15:14:27 +01:00
26a884e70a
* Gravity generator, Atmos Control Computers, and Station Alert Computers now work by area rather than Z_level
* Cameras get added to network depending on ancestor area
* Station Alert console work by area
* Adds a check so we don't get_area on a null variable
* Gravgen also checks for z level. Area check now includes some types of ruins that weren't checked
* Keeps everything on the Z level. Atmos alert computer now iterates over alarm, but still presesents area names
* Engineering monitor gets networks from the area it is placed in
* Adds missing area prototype to the prototype list
* moves the area check to a function
* reject legs, return to snek.
* Revert "reject legs, return to snek."
This reverts commit 1dfc2c4454.
* I don't know what happened with paradise.dme, but it seems ok now
* Requested style changes and remove redundant nulls
* oops
* Another empty line removed
569 lines
18 KiB
Plaintext
569 lines
18 KiB
Plaintext
/area
|
|
var/fire = null
|
|
var/area_emergency_mode = FALSE // When true, fire alarms cannot unset emergency lighting. Not to be confused with emergency_mode var on light objects.
|
|
var/atmosalm = ATMOS_ALARM_NONE
|
|
var/poweralm = TRUE
|
|
var/report_alerts = TRUE // Should atmos alerts notify the AI/computers
|
|
level = null
|
|
name = "Space"
|
|
icon = 'icons/turf/areas.dmi'
|
|
icon_state = "unknown"
|
|
layer = AREA_LAYER
|
|
plane = AREA_PLANE //Keeping this on the default plane, GAME_PLANE, will make area overlays fail to render on FLOOR_PLANE.
|
|
luminosity = 0
|
|
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
invisibility = INVISIBILITY_LIGHTING
|
|
|
|
/// used for cult summoning areas on station zlevel
|
|
var/valid_territory = TRUE
|
|
/// Set in New(); preserves the name set by the map maker, even if renamed by the Blueprints.
|
|
var/map_name
|
|
/// Is the lightswitch in this area on? Controls whether or not lights are on and off
|
|
var/lightswitch = TRUE
|
|
/// Is the window tint control in this area on? Controls whether electrochromic windows and doors are tinted or not
|
|
var/window_tint = FALSE
|
|
/// If TRUE, the local powernet in this area will have all its power channels switched off
|
|
var/apc_starts_off = FALSE
|
|
/// If TRUE, this area's local powernet will require power to properly operate machines
|
|
var/requires_power = TRUE
|
|
/// If TRUE, machines that require power in this area will never be powered
|
|
var/always_unpowered = FALSE
|
|
/// The local powernet of this area, this is where all machine/apc/object power related operations are handled
|
|
var/datum/local_powernet/powernet = null
|
|
/// All APCs currently constructed in this area
|
|
var/list/apc = list()
|
|
|
|
var/has_gravity = TRUE
|
|
|
|
var/air_doors_activated = FALSE
|
|
|
|
var/tele_proof = FALSE
|
|
var/no_teleportlocs = FALSE
|
|
|
|
var/outdoors = FALSE //For space, the asteroid, lavaland, etc. Used with blueprints to determine if we are adding a new area (vs editing a station room)
|
|
var/xenobiology_compatible = FALSE //Can the Xenobio management console transverse this area by default?
|
|
var/nad_allowed = FALSE //is the station NAD allowed on this area?
|
|
|
|
// This var is used with the maploader (modules/awaymissions/maploader/reader.dm)
|
|
// if this is 1, when used in a map snippet, this will instantiate a unique
|
|
// area from any other instances already present (meaning you can have
|
|
// separate APCs, and so on)
|
|
var/there_can_be_many = FALSE
|
|
|
|
/// Static var that is incremented when the UID of a area is being assigned.
|
|
var/global/global_uid = 0
|
|
var/uid
|
|
|
|
var/list/ambientsounds = GENERIC_SOUNDS
|
|
|
|
var/list/firedoors
|
|
var/list/cameras
|
|
var/list/firealarms
|
|
var/firedoors_last_closed_on = 0
|
|
|
|
/// The air alarm to use for atmos_alert consoles
|
|
var/obj/machinery/alarm/master_air_alarm
|
|
/// The list of vents in our area.
|
|
var/list/obj/machinery/atmospherics/unary/vent_pump/vents = list()
|
|
/// The list of scrubbers in our area.
|
|
var/list/obj/machinery/atmospherics/unary/vent_scrubber/scrubbers = list()
|
|
|
|
/// Do we quickly despawn the person in this area? Pretty much just used in permabrig
|
|
var/fast_despawn = FALSE
|
|
/// Do we despawn the person in this area? Pretty much just used in security areas that aren't permabrig
|
|
var/can_get_auto_cryod = TRUE
|
|
/// For areas such as thunderdome which generate a lot of spammy attacklogs. Reduces log priority.
|
|
var/hide_attacklogs = FALSE
|
|
/// Handles the direction parallax will be moved in. References
|
|
var/parallax_move_direction = 0
|
|
/// Is a shuttle moving to our area?
|
|
var/moving = FALSE
|
|
/// "Haunted" areas such as the morgue and chapel are easier to boo. Because flavor.
|
|
var/is_haunted = FALSE
|
|
///Used to decide what kind of reverb the area makes sound have
|
|
var/sound_environment = SOUND_ENVIRONMENT_NONE
|
|
|
|
/// Used to decide what the minimum time between ambience is
|
|
var/min_ambience_cooldown = 30 SECONDS
|
|
/// Used to decide what the maximum time between ambience is
|
|
var/max_ambience_cooldown = 90 SECONDS
|
|
|
|
/// Turrets use this list to see if individual power/lethal settings are allowed. Contains the /obj/machinery/turretid for this area
|
|
var/list/turret_controls = list()
|
|
|
|
/// The flags applied to request consoles spawned in this area.
|
|
/// See [RC_ASSIST], [RC_SUPPLY], [RC_INFO].
|
|
var/request_console_flags = 0
|
|
/// The name for any spawned request consoles. Defaults to the area name.
|
|
var/request_console_name
|
|
/// Whether request consoles in this area can send announcements.
|
|
var/request_console_announces = FALSE
|
|
/// Fire alarm camera network
|
|
var/fire_cam_network = "Fire Alarms Debug"
|
|
/// Power alarm camera network
|
|
var/power_cam_network = "Power Alarms Debug"
|
|
/// Atmosphere alarm camera network
|
|
var/atmos_cam_network = "Atmosphere Alarms Debug"
|
|
/*
|
|
Lighting Vars
|
|
*/
|
|
luminosity = TRUE
|
|
var/dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
|
|
|
|
/area/New(loc, ...)
|
|
if(!there_can_be_many) // Has to be done in New else the maploader will fuck up and find subtypes for the parent
|
|
GLOB.all_unique_areas[type] = src
|
|
GLOB.all_areas += src
|
|
return ..()
|
|
|
|
/area/Initialize(mapload)
|
|
if(is_station_level(z))
|
|
RegisterSignal(SSsecurity_level, COMSIG_SECURITY_LEVEL_CHANGED, PROC_REF(on_security_level_update))
|
|
|
|
icon_state = ""
|
|
layer = AREA_LAYER
|
|
uid = ++global_uid
|
|
|
|
map_name = name // Save the initial (the name set in the map) name of the area.
|
|
|
|
if(!powernet) // we may already have a powernet due to machine init, better to be safe than sorry
|
|
create_powernet() // no powernet yet, create one
|
|
|
|
//setting lighting
|
|
if(!requires_power)
|
|
if(dynamic_lighting == DYNAMIC_LIGHTING_FORCED)
|
|
dynamic_lighting = DYNAMIC_LIGHTING_ENABLED
|
|
luminosity = 0
|
|
else if(dynamic_lighting != DYNAMIC_LIGHTING_IFSTARLIGHT)
|
|
dynamic_lighting = DYNAMIC_LIGHTING_DISABLED
|
|
if(dynamic_lighting == DYNAMIC_LIGHTING_IFSTARLIGHT)
|
|
dynamic_lighting = GLOB.configuration.general.starlight ? DYNAMIC_LIGHTING_ENABLED : DYNAMIC_LIGHTING_DISABLED
|
|
|
|
. = ..()
|
|
|
|
blend_mode = BLEND_MULTIPLY // Putting this in the constructor so that it stops the icons being screwed up in the map editor.
|
|
|
|
if(!IS_DYNAMIC_LIGHTING(src))
|
|
add_overlay(/obj/effect/fullbright)
|
|
|
|
reg_in_areas_in_z()
|
|
|
|
return INITIALIZE_HINT_LATELOAD
|
|
|
|
/area/proc/on_security_level_update(datum/source, previous_level_number, new_level_number)
|
|
SIGNAL_HANDLER
|
|
|
|
area_emergency_mode = (new_level_number >= SEC_LEVEL_EPSILON)
|
|
|
|
/area/proc/create_powernet()
|
|
powernet = new()
|
|
powernet.powernet_area = src
|
|
|
|
//setting power flags and channel breakers
|
|
if(always_unpowered) //area will never be powered, set all power channels to off
|
|
powernet.lighting_powered = FALSE
|
|
powernet.equipment_powered = FALSE
|
|
powernet.environment_powered = FALSE
|
|
powernet.power_flags |= PW_ALWAYS_UNPOWERED //ensures all power checks will return FALSE
|
|
else if(requires_power) //area does require power
|
|
luminosity = 0
|
|
if(apc_starts_off) //flip all the channels off if apc starts off
|
|
powernet.lighting_powered = FALSE
|
|
powernet.equipment_powered = FALSE
|
|
powernet.environment_powered = FALSE
|
|
else // area doesn't require power
|
|
powernet.power_flags |= PW_ALWAYS_POWERED //ensures all power checks will return TRUE
|
|
|
|
return powernet
|
|
|
|
/area/proc/reg_in_areas_in_z()
|
|
if(!length(contents)) // if its nullspaced or something, I guess
|
|
return
|
|
if(!z)
|
|
WARNING("No z found for [src]")
|
|
return
|
|
var/list/areas_in_z = GLOB.space_manager.areas_in_z
|
|
if(!areas_in_z["[z]"])
|
|
areas_in_z["[z]"] = list()
|
|
areas_in_z["[z]"] += src
|
|
|
|
/area/proc/get_cameras()
|
|
var/list/cameras = list()
|
|
for(var/obj/machinery/camera/C in src)
|
|
cameras += C
|
|
return cameras
|
|
|
|
/area/proc/air_doors_close()
|
|
if(air_doors_activated)
|
|
return
|
|
air_doors_activated = TRUE
|
|
for(var/obj/machinery/door/firedoor/D in src)
|
|
if(!D.is_operational())
|
|
continue
|
|
D.activate_alarm()
|
|
if(D.welded)
|
|
continue
|
|
if(D.operating && D.operating != DOOR_CLOSING)
|
|
D.nextstate = FD_CLOSED
|
|
else if(!D.density)
|
|
INVOKE_ASYNC(D, TYPE_PROC_REF(/obj/machinery/door/firedoor, close))
|
|
|
|
/area/proc/air_doors_open()
|
|
if(!air_doors_activated)
|
|
return
|
|
air_doors_activated = FALSE
|
|
for(var/obj/machinery/door/firedoor/D in src)
|
|
if(!D.is_operational())
|
|
continue
|
|
D.deactivate_alarm()
|
|
if(D.welded)
|
|
continue
|
|
if(D.operating && D.operating != DOOR_OPENING)
|
|
D.nextstate = FD_OPEN
|
|
else if(D.density)
|
|
INVOKE_ASYNC(D, TYPE_PROC_REF(/obj/machinery/door/firedoor, open))
|
|
|
|
/area/Destroy()
|
|
STOP_PROCESSING(SSobj, src)
|
|
return ..()
|
|
|
|
/**
|
|
* Generate a power alert for this area
|
|
*
|
|
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
|
|
*/
|
|
/area/proc/poweralert(state, obj/source)
|
|
if(state == poweralm)
|
|
return
|
|
poweralm = state
|
|
if(!istype(source)) //Only report power alarms on the z-level where the source is located.
|
|
return
|
|
for(var/thing in cameras)
|
|
var/obj/machinery/camera/C = locateUID(thing)
|
|
if(!QDELETED(C))
|
|
if(state)
|
|
C.network -= power_cam_network
|
|
else
|
|
C.network |= power_cam_network
|
|
|
|
if(state)
|
|
GLOB.alarm_manager.cancel_alarm("Power", src, source)
|
|
else
|
|
GLOB.alarm_manager.trigger_alarm("Power", src, cameras, source)
|
|
|
|
/**
|
|
* Generate an atmospheric alert for this area
|
|
*
|
|
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
|
|
*/
|
|
/area/proc/atmosalert(danger_level, obj/source)
|
|
if(danger_level != atmosalm)
|
|
if(danger_level == ATMOS_ALARM_DANGER)
|
|
|
|
for(var/thing in cameras)
|
|
var/obj/machinery/camera/C = locateUID(thing)
|
|
if(!QDELETED(C))
|
|
C.network |= atmos_cam_network
|
|
|
|
|
|
GLOB.alarm_manager.trigger_alarm("Atmosphere", src, cameras, source)
|
|
|
|
else if(atmosalm == ATMOS_ALARM_DANGER)
|
|
for(var/thing in cameras)
|
|
var/obj/machinery/camera/C = locateUID(thing)
|
|
if(!QDELETED(C))
|
|
C.network -= atmos_cam_network
|
|
|
|
GLOB.alarm_manager.cancel_alarm("Atmosphere", src, source)
|
|
|
|
atmosalm = danger_level
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/**
|
|
* Try to close all the firedoors in the area
|
|
*/
|
|
/area/proc/ModifyFiredoors(opening)
|
|
if(!firedoors)
|
|
return
|
|
firedoors_last_closed_on = world.time
|
|
for(var/obj/machinery/door/firedoor/D in firedoors)
|
|
if(!D.is_operational())
|
|
continue
|
|
var/valid = TRUE
|
|
if(opening) //don't open if adjacent area is on fire
|
|
for(var/I in D.affecting_areas)
|
|
var/area/A = I
|
|
if(A.fire)
|
|
valid = FALSE
|
|
break
|
|
if(!valid)
|
|
continue
|
|
|
|
// At this point, the area is safe and the door is technically functional.
|
|
|
|
INVOKE_ASYNC(D, (opening ? TYPE_PROC_REF(/obj/machinery/door/firedoor, deactivate_alarm) : TYPE_PROC_REF(/obj/machinery/door/firedoor, activate_alarm)))
|
|
if(D.welded)
|
|
continue // Alarm is toggled, but door stuck
|
|
if(D.operating)
|
|
if((D.operating == DOOR_OPENING && opening) || (D.operating == DOOR_CLOSING && !opening))
|
|
continue
|
|
else
|
|
D.nextstate = opening ? FD_OPEN : FD_CLOSED
|
|
else if(D.density == opening)
|
|
INVOKE_ASYNC(D, (opening ? TYPE_PROC_REF(/obj/machinery/door/firedoor, open) : TYPE_PROC_REF(/obj/machinery/door/firedoor, close)))
|
|
|
|
/**
|
|
* Generate a firealarm alert for this area
|
|
*
|
|
* Sends to all ai players, alert consoles, drones and alarm monitor programs in the world
|
|
*
|
|
* Also starts the area processing on SSobj
|
|
*/
|
|
/area/proc/firealert(obj/source)
|
|
if(always_unpowered) //no fire alarms in space/asteroid
|
|
return
|
|
|
|
if(!fire)
|
|
set_fire_alarm_effect()
|
|
ModifyFiredoors(FALSE)
|
|
for(var/item in firealarms)
|
|
var/obj/machinery/firealarm/F = item
|
|
F.update_icon()
|
|
GLOB.firealarm_soundloop.start(F)
|
|
|
|
for(var/thing in cameras)
|
|
var/obj/machinery/camera/C = locateUID(thing)
|
|
if(!QDELETED(C))
|
|
C.network |= fire_cam_network
|
|
|
|
GLOB.alarm_manager.trigger_alarm("Fire", src, cameras, source)
|
|
|
|
START_PROCESSING(SSobj, src)
|
|
|
|
/**
|
|
* Reset the firealarm alert for this area
|
|
*
|
|
* resets the alert sent to all ai players, alert consoles, drones and alarm monitor programs
|
|
* in the world
|
|
*
|
|
* Also cycles the icons of all firealarms and deregisters the area from processing on SSOBJ
|
|
*/
|
|
/area/proc/firereset(obj/source)
|
|
if(fire)
|
|
unset_fire_alarm_effects()
|
|
ModifyFiredoors(TRUE)
|
|
for(var/item in firealarms)
|
|
var/obj/machinery/firealarm/F = item
|
|
F.update_icon()
|
|
GLOB.firealarm_soundloop.stop(F, TRUE)
|
|
|
|
for(var/thing in cameras)
|
|
var/obj/machinery/camera/C = locateUID(thing)
|
|
if(!QDELETED(C))
|
|
C.network -= fire_cam_network
|
|
|
|
GLOB.alarm_manager.cancel_alarm("Fire", src, source)
|
|
|
|
STOP_PROCESSING(SSobj, src)
|
|
|
|
/**
|
|
* If 100 ticks has elapsed, toggle all the firedoors closed again
|
|
*/
|
|
/area/process()
|
|
if(firedoors_last_closed_on + 100 < world.time) //every 10 seconds
|
|
ModifyFiredoors(FALSE)
|
|
|
|
/**
|
|
* Close and lock a door passed into this proc
|
|
*
|
|
* Does this need to exist on area? probably not
|
|
*/
|
|
/area/proc/close_and_lock_door(obj/machinery/door/DOOR)
|
|
set waitfor = FALSE
|
|
DOOR.close()
|
|
if(DOOR.density)
|
|
DOOR.lock()
|
|
|
|
/**
|
|
* Raise a burglar alert for this area
|
|
*
|
|
* Close and locks all doors in the area and alerts silicon mobs of a break in
|
|
*
|
|
* Alarm auto resets after 600 ticks
|
|
*/
|
|
/area/proc/burglaralert(obj/trigger)
|
|
if(always_unpowered) //no burglar alarms in space/asteroid
|
|
return
|
|
|
|
//Trigger alarm effect
|
|
set_fire_alarm_effect()
|
|
//Lockdown airlocks
|
|
for(var/obj/machinery/door/DOOR in src)
|
|
close_and_lock_door(DOOR)
|
|
|
|
if(GLOB.alarm_manager.trigger_alarm("Burglar", src, cameras, trigger))
|
|
//Cancel silicon alert after 1 minute
|
|
addtimer(CALLBACK(GLOB.alarm_manager, TYPE_PROC_REF(/datum/alarm_manager, cancel_alarm), "Burglar", src, trigger), 1 MINUTES)
|
|
|
|
/**
|
|
* Trigger the fire alarm visual affects in an area
|
|
*
|
|
* Updates the fire light on fire alarms in the area and sets all lights to emergency mode
|
|
*/
|
|
/area/proc/set_fire_alarm_effect()
|
|
fire = TRUE
|
|
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
for(var/alarm in firealarms)
|
|
var/obj/machinery/firealarm/F = alarm
|
|
F.update_fire_light(fire)
|
|
if(area_emergency_mode) //Fires are not legally allowed if the power is off
|
|
return
|
|
for(var/obj/machinery/light/L in src)
|
|
L.fire_mode = TRUE
|
|
L.update(TRUE, TRUE, FALSE)
|
|
|
|
///unset the fire alarm visual affects in an area
|
|
/area/proc/unset_fire_alarm_effects()
|
|
fire = FALSE
|
|
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
for(var/alarm in firealarms)
|
|
var/obj/machinery/firealarm/F = alarm
|
|
F.update_fire_light(fire)
|
|
if(area_emergency_mode) //The lights stay red until the crisis is resolved
|
|
return
|
|
for(var/obj/machinery/light/L in src)
|
|
L.fire_mode = FALSE
|
|
L.update(TRUE, TRUE, FALSE)
|
|
|
|
/area/update_icon_state()
|
|
var/weather_icon
|
|
for(var/V in SSweather.processing)
|
|
var/datum/weather/W = V
|
|
if(W.stage != WEATHER_END_STAGE && (src in W.impacted_areas))
|
|
W.update_areas()
|
|
weather_icon = TRUE
|
|
if(!weather_icon)
|
|
icon_state = null
|
|
|
|
/area/space/update_icon_state()
|
|
icon_state = null
|
|
|
|
/area/Entered(A)
|
|
var/area/newarea
|
|
var/area/oldarea
|
|
|
|
if(ismob(A))
|
|
var/mob/M = A
|
|
|
|
if(!M.lastarea)
|
|
M.lastarea = get_area(M)
|
|
newarea = get_area(M)
|
|
oldarea = M.lastarea
|
|
|
|
if(newarea==oldarea) return
|
|
|
|
M.lastarea = src
|
|
|
|
if(!isliving(A)) return
|
|
|
|
var/mob/living/L = A
|
|
if(!L.ckey) return
|
|
SEND_SIGNAL(L, COMSIG_AREA_ENTERED, newarea)
|
|
if((oldarea.has_gravity == 0) && (newarea.has_gravity == 1) && (L.m_intent == MOVE_INTENT_RUN)) // Being ready when you change areas gives you a chance to avoid falling all together.
|
|
thunk(L)
|
|
|
|
if(GLOB.configuration.general.disable_ambient_noise)
|
|
return
|
|
|
|
//Ship ambience just loops if turned on.
|
|
if(L && L.client && !L.client.ambience_playing && (L.client.prefs.sound & SOUND_BUZZ))
|
|
L.client.ambience_playing = TRUE
|
|
SEND_SOUND(L, sound('sound/ambience/shipambience.ogg', repeat = TRUE, wait = FALSE, volume = 35 * L.client.prefs.get_channel_volume(CHANNEL_BUZZ), channel = CHANNEL_BUZZ))
|
|
else if(L && L.client && !(L.client.prefs.sound & SOUND_BUZZ))
|
|
L.client.ambience_playing = FALSE
|
|
|
|
/area/proc/gravitychange(gravitystate = 0, area/A)
|
|
A.has_gravity = gravitystate
|
|
|
|
if(gravitystate)
|
|
for(var/mob/living/carbon/human/M in A)
|
|
thunk(M)
|
|
for(var/obj/effect/decal/cleanable/blood/B in A)
|
|
B.splat(B)
|
|
for(var/obj/effect/decal/cleanable/vomit/V in A)
|
|
V.splat(V)
|
|
|
|
/area/proc/thunk(mob/living/carbon/human/M)
|
|
if(!istype(M)) // Rather not have non-humans get hit with a THUNK
|
|
return
|
|
|
|
if(HAS_TRAIT(M, TRAIT_MAGPULSE)) // Only humans can wear magboots, so we give them a chance to.
|
|
return
|
|
|
|
if(M.dna.species.spec_thunk(M)) //Species level thunk overrides
|
|
return
|
|
|
|
if(M.buckled) //Cam't fall down if you are buckled
|
|
return
|
|
|
|
if(isspaceturf(get_turf(M))) // Can't fall onto nothing.
|
|
return
|
|
|
|
if((ishuman(M)) && (M.m_intent == MOVE_INTENT_RUN))
|
|
M.Weaken(10 SECONDS)
|
|
|
|
else if(ishuman(M))
|
|
M.Weaken(4 SECONDS)
|
|
|
|
|
|
to_chat(M, "Gravity!")
|
|
|
|
/proc/has_gravity(atom/AT, turf/T)
|
|
if(!T)
|
|
T = get_turf(AT) // If we still don't have a turf, don't process the other stuff
|
|
if(!T)
|
|
return
|
|
var/area/A = get_area(T)
|
|
if(isspaceturf(T)) // Turf never has gravity
|
|
return 0
|
|
else if(A && A.has_gravity) // Areas which always has gravity
|
|
return 1
|
|
else
|
|
// There's a gravity generator on our z level
|
|
// This would do well when integrated with the z level manager
|
|
if(T && GLOB.gravity_generators["[T.z]"] && length(GLOB.gravity_generators["[T.z]"]))
|
|
return 1
|
|
return 0
|
|
|
|
/area/proc/prison_break()
|
|
for(var/obj/machinery/power/apc/temp_apc in src)
|
|
INVOKE_ASYNC(temp_apc, TYPE_PROC_REF(/obj/machinery/power/apc, overload_lighting), 70)
|
|
for(var/obj/machinery/door/airlock/temp_airlock in src)
|
|
INVOKE_ASYNC(temp_airlock, TYPE_PROC_REF(/obj/machinery/door/airlock, prison_open))
|
|
for(var/obj/machinery/door/window/temp_windoor in src)
|
|
INVOKE_ASYNC(temp_windoor, TYPE_PROC_REF(/obj/machinery/door, open))
|
|
for(var/obj/machinery/door/poddoor/temp_poddoor in src)
|
|
INVOKE_ASYNC(temp_poddoor, TYPE_PROC_REF(/obj/machinery/door, open))
|
|
|
|
/area/AllowDrop()
|
|
CRASH("Bad op: area/AllowDrop() called")
|
|
|
|
/area/drop_location()
|
|
CRASH("Bad op: area/drop_location() called")
|
|
|
|
/// Returns highest area type in the hirarchy of a given ruin or /area/station if it is given a station area.
|
|
/// For an example the top parent of area/ruin/space/bar/backroom is area/ruin/space/bar
|
|
/area/proc/get_top_parent_type()
|
|
var/top_parent_type = type
|
|
|
|
if(parent_type in subtypesof(/area/ruin))
|
|
// figure out which ruin we are on
|
|
while(!(type2parent(top_parent_type) in GLOB.ruin_prototypes))
|
|
top_parent_type = type2parent(top_parent_type)
|
|
else if(parent_type in subtypesof(/area/station))
|
|
top_parent_type = /area/station
|
|
else
|
|
top_parent_type = null
|
|
return top_parent_type
|