mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-01-01 05:02:33 +00:00
* Fire Alarms eventually stop making sounds * Change testing time * Fixups * Apply suggestions from code review Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: ExusA <67055922+ExusA@users.noreply.github.com> --------- Signed-off-by: ExusA <67055922+ExusA@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
587 lines
19 KiB
Plaintext
587 lines
19 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
|
|
|
|
/// Timer to stop ongoing fire alarm sounds
|
|
var/firealarm_sound_stop_timer = null
|
|
/// The air alarms present in this area.
|
|
var/list/air_alarms = list()
|
|
/// 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.
|
|
// Firedoors do not close automatically by default, and setting it to false when the alarm is off prevents unnecessary timers from being created. Emagged doors are permanently disabled from automatically closing, or being operated by alarms altogether apart from the lights.
|
|
if(!D.emagged)
|
|
if(opening)
|
|
D.autoclose = FALSE
|
|
else
|
|
D.autoclose = TRUE
|
|
|
|
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 || D.emagged)
|
|
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)
|
|
if(!firealarm_sound_stop_timer)
|
|
firealarm_sound_stop_timer = addtimer(CALLBACK(src, PROC_REF(stop_alarm_sounds)), 4 MINUTES, TIMER_STOPPABLE | TIMER_UNIQUE)
|
|
|
|
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)
|
|
|
|
/area/proc/stop_alarm_sounds()
|
|
for(var/obj/machinery/firealarm/F in firealarms)
|
|
F.update_icon()
|
|
GLOB.firealarm_soundloop.stop(F)
|
|
/**
|
|
* 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)
|
|
if(firealarm_sound_stop_timer)
|
|
deltimer(firealarm_sound_stop_timer)
|
|
firealarm_sound_stop_timer = null
|
|
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
|