mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-18 18:44:48 +01:00
Merge pull request #9050 from Fox-McCloud/weather-subsystem
Converts and Updates Weather Subsystem
This commit is contained in:
@@ -7,23 +7,35 @@
|
||||
#define PLANE_SPACE_PARALLAX -90
|
||||
|
||||
#define GAME_PLANE 0
|
||||
|
||||
#define SPACE_LAYER 1.8
|
||||
//#define TURF_LAYER 2 //For easy recordkeeping; this is a byond define
|
||||
#define MID_TURF_LAYER 2.02
|
||||
#define HIGH_TURF_LAYER 2.03
|
||||
#define TURF_PLATING_DECAL_LAYER 2.031
|
||||
#define TURF_DECAL_LAYER 2.039 //Makes turf decals appear in DM how they will look inworld.
|
||||
#define ABOVE_OPEN_TURF_LAYER 2.04
|
||||
#define CLOSED_TURF_LAYER 2.05
|
||||
#define BULLET_HOLE_LAYER 2.06
|
||||
#define ABOVE_NORMAL_TURF_LAYER 2.08
|
||||
#define LATTICE_LAYER 2.2
|
||||
#define DISPOSAL_PIPE_LAYER 2.3
|
||||
#define GAS_PIPE_LAYER 2.35
|
||||
#define GAS_PIPE_HIDDEN_LAYER 2.35
|
||||
#define WIRE_LAYER 2.4
|
||||
#define WIRE_TERMINAL_LAYER 2.45
|
||||
#define GAS_SCRUBBER_LAYER 2.46
|
||||
#define GAS_PIPE_VISIBLE_LAYER 2.47
|
||||
#define GAS_FILTER_LAYER 2.48
|
||||
#define GAS_PUMP_LAYER 2.49
|
||||
#define LOW_OBJ_LAYER 2.5
|
||||
#define LOW_SIGIL_LAYER 2.52
|
||||
#define SIGIL_LAYER 2.54
|
||||
#define HIGH_SIGIL_LAYER 2.56
|
||||
|
||||
#define BELOW_OPEN_DOOR_LAYER 2.6
|
||||
#define BLASTDOOR_LAYER 2.65
|
||||
#define OPEN_DOOR_LAYER 2.7
|
||||
#define DOOR_HELPER_LAYER 2.71 //keep this above OPEN_DOOR_LAYER
|
||||
#define PROJECTILE_HIT_THRESHHOLD_LAYER 2.75 //projectiles won't hit objects at or below this layer if possible
|
||||
#define TABLE_LAYER 2.8
|
||||
#define BELOW_OBJ_LAYER 2.9
|
||||
@@ -52,9 +64,13 @@
|
||||
#define SPACEVINE_LAYER 4.8
|
||||
#define SPACEVINE_MOB_LAYER 4.9
|
||||
//#define FLY_LAYER 5 //For easy recordkeeping; this is a byond define
|
||||
#define GASFIRE_LAYER 5.05
|
||||
#define RIPPLE_LAYER 5.1
|
||||
|
||||
#define GHOST_LAYER 6
|
||||
#define LOW_LANDMARK_LAYER 9
|
||||
#define MID_LANDMARK_LAYER 9.1
|
||||
#define HIGH_LANDMARK_LAYER 9.2
|
||||
#define AREA_LAYER 10
|
||||
#define MASSIVE_OBJ_LAYER 11
|
||||
#define POINT_LAYER 12
|
||||
@@ -62,6 +78,26 @@
|
||||
#define LIGHTING_PLANE 15
|
||||
#define LIGHTING_LAYER 15
|
||||
|
||||
#define ABOVE_LIGHTING_PLANE 16
|
||||
#define ABOVE_LIGHTING_LAYER 16
|
||||
|
||||
#define BYOND_LIGHTING_PLANE 17
|
||||
#define BYOND_LIGHTING_LAYER 17
|
||||
|
||||
//HUD layer defines
|
||||
|
||||
#define FULLSCREEN_PLANE 18
|
||||
#define FLASH_LAYER 18
|
||||
#define FULLSCREEN_LAYER 18.1
|
||||
#define UI_DAMAGE_LAYER 18.2
|
||||
#define BLIND_LAYER 18.3
|
||||
#define CRIT_LAYER 18.4
|
||||
#define CURSE_LAYER 18.5
|
||||
|
||||
#define HUD_PLANE 19
|
||||
#define HUD_LAYER 19
|
||||
#define HUD_PLANE 90
|
||||
#define ABOVE_HUD_PLANE 20
|
||||
#define ABOVE_HUD_LAYER 20
|
||||
|
||||
#define SPLASHSCREEN_LAYER 21
|
||||
#define SPLASHSCREEN_PLANE 21
|
||||
@@ -1,19 +0,0 @@
|
||||
/datum/controller/process/nanoui/setup()
|
||||
name = "nanoui"
|
||||
schedule_interval = 20 // every 2 seconds
|
||||
|
||||
/datum/controller/process/nanoui/statProcess()
|
||||
..()
|
||||
stat(null, "[nanomanager.processing_uis.len] UIs")
|
||||
|
||||
/datum/controller/process/nanoui/doWork()
|
||||
for(last_object in nanomanager.processing_uis)
|
||||
var/datum/nanoui/NUI = last_object
|
||||
if(istype(NUI) && isnull(NUI.gcDestroyed))
|
||||
try
|
||||
NUI.process()
|
||||
catch(var/exception/e)
|
||||
catchException(e, NUI)
|
||||
else
|
||||
catchBadType(NUI)
|
||||
nanomanager.processing_uis -= NUI
|
||||
@@ -1,54 +0,0 @@
|
||||
//Used for all kinds of weather, ex. lavaland ash storms.
|
||||
// TODO: This could probably be better-integrated with the space manager
|
||||
var/global/datum/controller/process/weather/weather_master
|
||||
|
||||
/datum/controller/process/weather
|
||||
var/list/processing_weather = list()
|
||||
var/list/existing_weather = list()
|
||||
var/list/eligible_zlevels = list()
|
||||
|
||||
/datum/controller/process/weather/setup()
|
||||
name = "weather"
|
||||
schedule_interval = 10
|
||||
|
||||
for(var/V in subtypesof(/datum/weather))
|
||||
var/datum/weather/W = V
|
||||
existing_weather |= new W
|
||||
|
||||
/datum/controller/process/weather/statProcess()
|
||||
..()
|
||||
stat(null, "[processing_weather.len] weather")
|
||||
|
||||
/datum/controller/process/weather/doWork()
|
||||
for(var/V in processing_weather)
|
||||
var/datum/weather/W = V
|
||||
if(W.aesthetic)
|
||||
continue
|
||||
for(var/mob/living/L in mob_list)
|
||||
if(W.can_impact(L))
|
||||
W.impact(L)
|
||||
SCHECK
|
||||
for(var/Z in eligible_zlevels)
|
||||
var/list/possible_weather_for_this_z = list()
|
||||
for(var/V in existing_weather)
|
||||
var/datum/weather/WE = V
|
||||
if(WE.target_z == Z && WE.probability) //Another check so that it doesn't run extra weather
|
||||
possible_weather_for_this_z[WE] = WE.probability
|
||||
var/datum/weather/W = pickweight(possible_weather_for_this_z)
|
||||
run_weather(W.name)
|
||||
eligible_zlevels -= Z
|
||||
addtimer(CALLBACK(src, .proc/make_z_eligible, Z), rand(3000, 6000) + W.weather_duration_upper, TIMER_UNIQUE) //Around 5-10 minutes between weathers
|
||||
|
||||
DECLARE_GLOBAL_CONTROLLER(weather, weather_master)
|
||||
|
||||
/datum/controller/process/weather/proc/run_weather(weather_name)
|
||||
if(!weather_name)
|
||||
return
|
||||
for(var/V in existing_weather)
|
||||
var/datum/weather/W = V
|
||||
if(W.name == weather_name)
|
||||
W.telegraph()
|
||||
SCHECK
|
||||
|
||||
/datum/controller/process/weather/proc/make_z_eligible(zlevel)
|
||||
eligible_zlevels |= zlevel
|
||||
@@ -0,0 +1,83 @@
|
||||
#define STARTUP_STAGE 1
|
||||
#define MAIN_STAGE 2
|
||||
#define WIND_DOWN_STAGE 3
|
||||
#define END_STAGE 4
|
||||
|
||||
//Used for all kinds of weather, ex. lavaland ash storms.
|
||||
SUBSYSTEM_DEF(weather)
|
||||
name = "Weather"
|
||||
flags = SS_BACKGROUND
|
||||
wait = 10
|
||||
runlevels = RUNLEVEL_GAME
|
||||
var/list/processing = list()
|
||||
var/list/eligible_zlevels = list()
|
||||
var/list/next_hit_by_zlevel = list() //Used by barometers to know when the next storm is coming
|
||||
|
||||
/datum/controller/subsystem/weather/fire()
|
||||
// process active weather
|
||||
for(var/V in processing)
|
||||
var/datum/weather/W = V
|
||||
if(W.aesthetic || W.stage != MAIN_STAGE)
|
||||
continue
|
||||
for(var/i in living_mob_list)
|
||||
var/mob/living/L = i
|
||||
if(W.can_weather_act(L))
|
||||
W.weather_act(L)
|
||||
|
||||
// start random weather on relevant levels
|
||||
for(var/z in eligible_zlevels)
|
||||
var/possible_weather = eligible_zlevels[z]
|
||||
var/datum/weather/W = pickweight(possible_weather)
|
||||
run_weather(W, list(text2num(z)))
|
||||
eligible_zlevels -= z
|
||||
var/randTime = rand(3000, 6000)
|
||||
addtimer(CALLBACK(src, .proc/make_eligible, z, possible_weather), randTime + initial(W.weather_duration_upper), TIMER_UNIQUE) //Around 5-10 minutes between weathers
|
||||
next_hit_by_zlevel["[z]"] = world.time + randTime + initial(W.telegraph_duration)
|
||||
|
||||
/datum/controller/subsystem/weather/Initialize(start_timeofday)
|
||||
for(var/V in subtypesof(/datum/weather))
|
||||
var/datum/weather/W = V
|
||||
var/probability = initial(W.probability)
|
||||
var/target_trait = initial(W.target_trait)
|
||||
|
||||
// any weather with a probability set may occur at random
|
||||
if(probability)
|
||||
for(var/z in levels_by_trait(target_trait))
|
||||
LAZYINITLIST(eligible_zlevels["[z]"])
|
||||
eligible_zlevels["[z]"][W] = probability
|
||||
..()
|
||||
|
||||
/datum/controller/subsystem/weather/proc/run_weather(datum/weather/weather_datum_type, z_levels)
|
||||
if(istext(weather_datum_type))
|
||||
for(var/V in subtypesof(/datum/weather))
|
||||
var/datum/weather/W = V
|
||||
if(initial(W.name) == weather_datum_type)
|
||||
weather_datum_type = V
|
||||
break
|
||||
if(!ispath(weather_datum_type, /datum/weather))
|
||||
CRASH("run_weather called with invalid weather_datum_type: [weather_datum_type || "null"]")
|
||||
return
|
||||
|
||||
if(isnull(z_levels))
|
||||
z_levels = levels_by_trait(initial(weather_datum_type.target_trait))
|
||||
else if(isnum(z_levels))
|
||||
z_levels = list(z_levels)
|
||||
else if(!islist(z_levels))
|
||||
CRASH("run_weather called with invalid z_levels: [z_levels || "null"]")
|
||||
return
|
||||
|
||||
var/datum/weather/W = new weather_datum_type(z_levels)
|
||||
W.telegraph()
|
||||
|
||||
/datum/controller/subsystem/weather/proc/make_eligible(z, possible_weather)
|
||||
eligible_zlevels[z] = possible_weather
|
||||
next_hit_by_zlevel["[z]"] = null
|
||||
|
||||
/datum/controller/subsystem/weather/proc/get_weather(z, area/active_area)
|
||||
var/datum/weather/A
|
||||
for(var/V in processing)
|
||||
var/datum/weather/W = V
|
||||
if((z in W.impacted_z_levels) && W.area_type == active_area.type)
|
||||
A = W
|
||||
break
|
||||
return A
|
||||
@@ -94,7 +94,7 @@
|
||||
debug_variables(SStimer)
|
||||
feedback_add_details("admin_verb","DTimer")
|
||||
if("Weather")
|
||||
debug_variables(weather_master)
|
||||
debug_variables(SSweather)
|
||||
feedback_add_details("admin_verb","DWeather")
|
||||
if("Space")
|
||||
debug_variables(space_manager)
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/datum/looping_sound/active_outside_ashstorm
|
||||
mid_sounds = list(
|
||||
'sound/weather/ashstorm/outside/active_mid1.ogg' = 1,
|
||||
'sound/weather/ashstorm/outside/active_mid1.ogg' = 1,
|
||||
'sound/weather/ashstorm/outside/active_mid1.ogg' = 1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/ashstorm/outside/active_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/outside/active_end.ogg'
|
||||
volume = 80
|
||||
|
||||
/datum/looping_sound/active_inside_ashstorm
|
||||
mid_sounds = list(
|
||||
'sound/weather/ashstorm/inside/active_mid1.ogg' = 1,
|
||||
'sound/weather/ashstorm/inside/active_mid2.ogg' = 1,
|
||||
'sound/weather/ashstorm/inside/active_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/ashstorm/inside/active_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/inside/active_end.ogg'
|
||||
volume = 60
|
||||
|
||||
/datum/looping_sound/weak_outside_ashstorm
|
||||
mid_sounds = list(
|
||||
'sound/weather/ashstorm/outside/weak_mid1.ogg' = 1,
|
||||
'sound/weather/ashstorm/outside/weak_mid2.ogg' = 1,
|
||||
'sound/weather/ashstorm/outside/weak_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/ashstorm/outside/weak_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/outside/weak_end.ogg'
|
||||
volume = 50
|
||||
|
||||
/datum/looping_sound/weak_inside_ashstorm
|
||||
mid_sounds = list(
|
||||
'sound/weather/ashstorm/inside/weak_mid1.ogg' = 1,
|
||||
'sound/weather/ashstorm/inside/weak_mid2.ogg' = 1,
|
||||
'sound/weather/ashstorm/inside/weak_mid3.ogg' = 1
|
||||
)
|
||||
mid_length = 80
|
||||
start_sound = 'sound/weather/ashstorm/inside/weak_start.ogg'
|
||||
start_length = 130
|
||||
end_sound = 'sound/weather/ashstorm/inside/weak_end.ogg'
|
||||
volume = 30
|
||||
@@ -1,10 +1,5 @@
|
||||
//The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures.
|
||||
|
||||
#define STARTUP_STAGE 1
|
||||
#define MAIN_STAGE 2
|
||||
#define WIND_DOWN_STAGE 3
|
||||
#define END_STAGE 4
|
||||
|
||||
/datum/weather
|
||||
var/name = "space wind"
|
||||
var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open."
|
||||
@@ -29,24 +24,25 @@
|
||||
|
||||
var/area_type = /area/space //Types of area to affect
|
||||
var/list/impacted_areas = list() //Areas to be affected by the weather, calculated when the weather begins
|
||||
var/target_z = MAIN_STATION //The z-level to affect
|
||||
var/list/protected_areas = list()//Areas that are protected and excluded from the affected areas.
|
||||
var/impacted_z_levels // The list of z-levels that this weather is actively affecting
|
||||
|
||||
var/overlay_layer = 10 //Since it's above everything else, this is the layer used by default. 2 is below mobs and walls if you need to use that.
|
||||
var/overlay_layer = AREA_LAYER //Since it's above everything else, this is the layer used by default. TURF_LAYER is below mobs and walls if you need to use that.
|
||||
var/aesthetic = FALSE //If the weather has no purpose other than looks
|
||||
var/immunity_type = "storm" //Used by mobs to prevent them from being affected by the weather
|
||||
|
||||
var/stage = END_STAGE //The stage of the weather, from 1-4
|
||||
|
||||
var/probability = FALSE //Percent chance to happen if there are other possible weathers on the z-level
|
||||
// These are read by the weather subsystem and used to determine when and where to run the weather.
|
||||
var/probability = 0 // Weight amongst other eligible weather. If zero, will never happen randomly.
|
||||
var/target_trait = STATION_LEVEL // The z-level trait to affect when run randomly or when not overridden.
|
||||
|
||||
/datum/weather/New()
|
||||
var/barometer_predictable = FALSE
|
||||
var/next_hit_time = 0 //For barometers to know when the next storm will hit
|
||||
|
||||
/datum/weather/New(z_levels)
|
||||
..()
|
||||
weather_master.existing_weather |= src
|
||||
|
||||
/datum/weather/Destroy()
|
||||
weather_master.existing_weather -= src
|
||||
return ..()
|
||||
impacted_z_levels = z_levels
|
||||
|
||||
/datum/weather/proc/telegraph()
|
||||
if(stage == STARTUP_STAGE)
|
||||
@@ -59,17 +55,18 @@
|
||||
affectareas -= get_areas(V)
|
||||
for(var/V in affectareas)
|
||||
var/area/A = V
|
||||
if(is_on_level_name(A,target_z))
|
||||
if(A.z in impacted_z_levels)
|
||||
impacted_areas |= A
|
||||
weather_duration = rand(weather_duration_lower, weather_duration_upper)
|
||||
START_PROCESSING(SSweather, src)
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_z))
|
||||
for(var/M in player_list)
|
||||
var/turf/mob_turf = get_turf(M)
|
||||
if(mob_turf && (mob_turf.z in impacted_z_levels))
|
||||
if(telegraph_message)
|
||||
to_chat(M, telegraph_message)
|
||||
if(telegraph_sound)
|
||||
M << sound(telegraph_sound)
|
||||
SEND_SOUND(M, sound(telegraph_sound))
|
||||
addtimer(CALLBACK(src, .proc/start), telegraph_duration)
|
||||
|
||||
/datum/weather/proc/start()
|
||||
@@ -77,14 +74,13 @@
|
||||
return
|
||||
stage = MAIN_STAGE
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_z))
|
||||
for(var/M in player_list)
|
||||
var/turf/mob_turf = get_turf(M)
|
||||
if(mob_turf && (mob_turf.z in impacted_z_levels))
|
||||
if(weather_message)
|
||||
to_chat(M, weather_message)
|
||||
if(weather_sound)
|
||||
M << sound(weather_sound)
|
||||
weather_master.processing_weather |= src
|
||||
SEND_SOUND(M, sound(weather_sound))
|
||||
addtimer(CALLBACK(src, .proc/wind_down), weather_duration)
|
||||
|
||||
/datum/weather/proc/wind_down()
|
||||
@@ -92,24 +88,25 @@
|
||||
return
|
||||
stage = WIND_DOWN_STAGE
|
||||
update_areas()
|
||||
for(var/V in player_list)
|
||||
var/mob/M = V
|
||||
if(is_on_level_name(M,target_z))
|
||||
for(var/M in player_list)
|
||||
var/turf/mob_turf = get_turf(M)
|
||||
if(mob_turf && (mob_turf.z in impacted_z_levels))
|
||||
if(end_message)
|
||||
to_chat(M, end_message)
|
||||
if(end_sound)
|
||||
M << sound(end_sound)
|
||||
weather_master.processing_weather -= src
|
||||
SEND_SOUND(M, sound(end_sound))
|
||||
addtimer(CALLBACK(src, .proc/end), end_duration)
|
||||
|
||||
/datum/weather/proc/end()
|
||||
if(stage == END_STAGE)
|
||||
return
|
||||
return 1
|
||||
stage = END_STAGE
|
||||
STOP_PROCESSING(SSweather, src)
|
||||
update_areas()
|
||||
|
||||
/datum/weather/proc/can_impact(mob/living/L) //Can this weather impact a mob?
|
||||
if(!is_on_level_name(L,target_z))
|
||||
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
|
||||
var/turf/mob_turf = get_turf(L)
|
||||
if(mob_turf && !(mob_turf.z in impacted_z_levels))
|
||||
return
|
||||
if(immunity_type in L.weather_immunities)
|
||||
return
|
||||
@@ -117,7 +114,7 @@
|
||||
return
|
||||
return 1
|
||||
|
||||
/datum/weather/proc/impact(mob/living/L) //What effect does this weather have on the hapless mob?
|
||||
/datum/weather/proc/weather_act(mob/living/L) //What effect does this weather have on the hapless mob?
|
||||
return
|
||||
|
||||
/datum/weather/proc/update_areas()
|
||||
@@ -136,8 +133,8 @@
|
||||
N.icon_state = end_overlay
|
||||
if(END_STAGE)
|
||||
N.color = null
|
||||
N.icon_state = initial(N.icon_state)
|
||||
N.icon_state = ""
|
||||
N.icon = 'icons/turf/areas.dmi'
|
||||
N.layer = 10 //Just default back to normal area stuff since I assume setting a var is faster than initial
|
||||
N.layer = AREA_LAYER //Just default back to normal area stuff since I assume setting a var is faster than initial
|
||||
N.invisibility = INVISIBILITY_MAXIMUM
|
||||
N.opacity = 0
|
||||
N.set_opacity(FALSE)
|
||||
|
||||
@@ -1,118 +0,0 @@
|
||||
//Different types of weather.
|
||||
|
||||
/datum/weather/floor_is_lava //The Floor is Lava: Makes all turfs damage anyone on them unless they're standing on a solid object.
|
||||
name = "the floor is lava"
|
||||
desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
|
||||
|
||||
telegraph_message = "<span class='warning'>Waves of heat emanate from the ground...</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>The floor is lava! Get on top of something!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 600
|
||||
weather_overlay = "lava"
|
||||
|
||||
end_message = "<span class='danger'>The ground cools and returns to its usual form.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_z = MAIN_STATION
|
||||
|
||||
overlay_layer = 2 //Covers floors only
|
||||
immunity_type = "lava"
|
||||
|
||||
/datum/weather/floor_is_lava/impact(mob/living/L)
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density)
|
||||
return
|
||||
if(L.loc.density)
|
||||
return
|
||||
if(!L.client) //Only sentient people are going along with it!
|
||||
return
|
||||
L.adjustFireLoss(3)
|
||||
|
||||
/datum/weather/floor_is_lava/fake
|
||||
name = "fake lava"
|
||||
aesthetic = TRUE
|
||||
|
||||
/datum/weather/advanced_darkness //Advanced Darkness: Restricts the vision of all affected mobs to a single tile in the cardinal directions.
|
||||
name = "advanced darkness"
|
||||
desc = "Everything in the area is effectively blinded, unable to see more than a foot or so around itself."
|
||||
|
||||
telegraph_message = "<span class='warning'>The lights begin to dim... is the power going out?</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>This isn't your everyday darkness... this is <i>advanced</i> darkness!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 300
|
||||
|
||||
end_message = "<span class='danger'>At last, the darkness recedes.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
target_z = MAIN_STATION
|
||||
|
||||
/datum/weather/advanced_darkness/update_areas()
|
||||
for(var/V in impacted_areas)
|
||||
var/area/A = V
|
||||
if(stage == MAIN_STAGE)
|
||||
A.invisibility = 0
|
||||
A.opacity = 1
|
||||
A.layer = overlay_layer
|
||||
A.icon = 'icons/effects/weather_effects.dmi'
|
||||
A.icon_state = "darkness"
|
||||
else
|
||||
A.invisibility = INVISIBILITY_MAXIMUM
|
||||
A.opacity = 0
|
||||
|
||||
|
||||
/datum/weather/ash_storm //Ash Storms: Common happenings on lavaland. Heavily obscures vision and deals heavy fire damage to anyone caught outside.
|
||||
name = "ash storm"
|
||||
desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected."
|
||||
|
||||
telegraph_message = "<span class='boldwarning'>An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter.</span>"
|
||||
telegraph_duration = 300
|
||||
telegraph_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
telegraph_overlay = "light_ash"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Smoldering clouds of scorching ash billow down around you! Get inside!</i></span>"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_sound = 'sound/lavaland/ash_storm_start.ogg'
|
||||
weather_overlay = "ash_storm"
|
||||
|
||||
end_message = "<span class='boldannounce'>The shrieking wind whips away the last of the ash falls to its usual murmur. It should be safe to go outside now.</span>"
|
||||
end_duration = 300
|
||||
end_sound = 'sound/lavaland/ash_storm_end.ogg'
|
||||
end_overlay = "light_ash"
|
||||
|
||||
area_type = /area/mine/dangerous
|
||||
target_z = MINING
|
||||
|
||||
immunity_type = "ash"
|
||||
|
||||
probability = 90
|
||||
|
||||
/datum/weather/ash_storm/impact(mob/living/L)
|
||||
if(istype(L.loc, /obj/mecha))
|
||||
return
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/thermal_protection = H.get_thermal_protection()
|
||||
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
|
||||
return
|
||||
L.adjustFireLoss(4)
|
||||
|
||||
/datum/weather/ash_storm/emberfall //Emberfall: An ash storm passes by, resulting in harmless embers falling like snow. 10% to happen in place of an ash storm.
|
||||
name = "emberfall"
|
||||
desc = "A passing ash storm blankets the area in harmless embers."
|
||||
|
||||
weather_message = "<span class='notice'>Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by...</span>"
|
||||
weather_sound = 'sound/lavaland/ash_storm_windup.ogg'
|
||||
weather_overlay = "light_ash"
|
||||
|
||||
end_message = "<span class='notice'>The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet.</span>"
|
||||
|
||||
aesthetic = TRUE
|
||||
|
||||
probability = 10
|
||||
@@ -0,0 +1,108 @@
|
||||
//Ash storms happen frequently on lavaland. They heavily obscure vision, and cause high fire damage to anyone caught outside.
|
||||
/datum/weather/ash_storm
|
||||
name = "ash storm"
|
||||
desc = "An intense atmospheric storm lifts ash off of the planet's surface and billows it down across the area, dealing intense fire damage to the unprotected."
|
||||
|
||||
telegraph_message = "<span class='boldwarning'>An eerie moan rises on the wind. Sheets of burning ash blacken the horizon. Seek shelter.</span>"
|
||||
telegraph_duration = 300
|
||||
telegraph_overlay = "light_ash"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Smoldering clouds of scorching ash billow down around you! Get inside!</i></span>"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1200
|
||||
weather_overlay = "ash_storm"
|
||||
|
||||
end_message = "<span class='boldannounce'>The shrieking wind whips away the last of the ash and falls to its usual murmur. It should be safe to go outside now.</span>"
|
||||
end_duration = 300
|
||||
end_overlay = "light_ash"
|
||||
|
||||
area_type = /area/mine/dangerous // /area/lavaland/surface/outdoors
|
||||
target_trait = ORE_LEVEL
|
||||
|
||||
immunity_type = "ash"
|
||||
|
||||
// probability = 90
|
||||
|
||||
barometer_predictable = TRUE
|
||||
|
||||
var/datum/looping_sound/active_outside_ashstorm/sound_ao = new(list(), FALSE, TRUE)
|
||||
var/datum/looping_sound/active_inside_ashstorm/sound_ai = new(list(), FALSE, TRUE)
|
||||
var/datum/looping_sound/weak_outside_ashstorm/sound_wo = new(list(), FALSE, TRUE)
|
||||
var/datum/looping_sound/weak_inside_ashstorm/sound_wi = new(list(), FALSE, TRUE)
|
||||
|
||||
/datum/weather/ash_storm/telegraph()
|
||||
. = ..()
|
||||
var/list/inside_areas = list()
|
||||
var/list/outside_areas = list()
|
||||
var/list/eligible_areas = list()
|
||||
for(var/z in impacted_z_levels)
|
||||
eligible_areas += space_manager.areas_in_z["[z]"]
|
||||
for(var/i in 1 to eligible_areas.len)
|
||||
var/area/place = eligible_areas[i]
|
||||
if(place.outdoors)
|
||||
outside_areas += place
|
||||
else
|
||||
inside_areas += place
|
||||
CHECK_TICK
|
||||
|
||||
sound_ao.output_atoms = outside_areas
|
||||
sound_ai.output_atoms = inside_areas
|
||||
sound_wo.output_atoms = outside_areas
|
||||
sound_wi.output_atoms = inside_areas
|
||||
|
||||
sound_wo.start()
|
||||
sound_wi.start()
|
||||
|
||||
/datum/weather/ash_storm/start()
|
||||
. = ..()
|
||||
sound_wo.stop()
|
||||
sound_wi.stop()
|
||||
|
||||
sound_ao.start()
|
||||
sound_ai.start()
|
||||
|
||||
/datum/weather/ash_storm/wind_down()
|
||||
. = ..()
|
||||
sound_ao.stop()
|
||||
sound_ai.stop()
|
||||
|
||||
sound_wo.start()
|
||||
sound_wi.start()
|
||||
|
||||
/datum/weather/ash_storm/end()
|
||||
. = ..()
|
||||
sound_wo.stop()
|
||||
sound_wi.stop()
|
||||
|
||||
/datum/weather/ash_storm/proc/is_ash_immune(atom/L)
|
||||
while(L && !isturf(L))
|
||||
if(ismecha(L)) //Mechs are immune
|
||||
return TRUE
|
||||
if(ishuman(L)) //Are you immune?
|
||||
var/mob/living/carbon/human/H = L
|
||||
var/thermal_protection = H.get_thermal_protection()
|
||||
if(thermal_protection >= FIRE_IMMUNITY_SUIT_MAX_TEMP_PROTECT)
|
||||
return TRUE
|
||||
L = L.loc //Matryoshka check
|
||||
return FALSE //RIP you
|
||||
|
||||
/datum/weather/ash_storm/weather_act(mob/living/L)
|
||||
if(is_ash_immune(L))
|
||||
return
|
||||
L.adjustFireLoss(4)
|
||||
|
||||
|
||||
//Emberfalls are the result of an ash storm passing by close to the playable area of lavaland. They have a 10% chance to trigger in place of an ash storm.
|
||||
/datum/weather/ash_storm/emberfall
|
||||
name = "emberfall"
|
||||
desc = "A passing ash storm blankets the area in harmless embers."
|
||||
|
||||
weather_message = "<span class='notice'>Gentle embers waft down around you like grotesque snow. The storm seems to have passed you by...</span>"
|
||||
weather_overlay = "light_ash"
|
||||
|
||||
end_message = "<span class='notice'>The emberfall slows, stops. Another layer of hardened soot to the basalt beneath your feet.</span>"
|
||||
end_sound = null
|
||||
|
||||
aesthetic = TRUE
|
||||
|
||||
// probability = 10
|
||||
@@ -0,0 +1,39 @@
|
||||
//Causes fire damage to anyone not standing on a dense object.
|
||||
/datum/weather/floor_is_lava
|
||||
name = "the floor is lava"
|
||||
desc = "The ground turns into surprisingly cool lava, lightly damaging anything on the floor."
|
||||
|
||||
telegraph_message = "<span class='warning'>You feel the ground beneath you getting hot. Waves of heat distort the air.</span>"
|
||||
telegraph_duration = 150
|
||||
|
||||
weather_message = "<span class='userdanger'>The floor is lava! Get on top of something!</span>"
|
||||
weather_duration_lower = 300
|
||||
weather_duration_upper = 600
|
||||
weather_overlay = "lava"
|
||||
|
||||
end_message = "<span class='danger'>The ground cools and returns to its usual form.</span>"
|
||||
end_duration = 0
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/space)
|
||||
target_trait = STATION_LEVEL
|
||||
|
||||
overlay_layer = ABOVE_OPEN_TURF_LAYER //Covers floors only
|
||||
immunity_type = "lava"
|
||||
|
||||
|
||||
/datum/weather/floor_is_lava/weather_act(mob/living/L)
|
||||
if(issilicon(L))
|
||||
return
|
||||
for(var/obj/structure/O in L.loc)
|
||||
if(O.density || O.buckled_mob && istype(O, /obj/structure/stool/bed))
|
||||
return
|
||||
if(L.loc.density)
|
||||
return
|
||||
if(!L.client) //Only sentient people are going along with it!
|
||||
return
|
||||
L.adjustFireLoss(3)
|
||||
|
||||
/datum/weather/floor_is_lava/fake
|
||||
name = "the floor is lava (fake)"
|
||||
aesthetic = TRUE
|
||||
@@ -0,0 +1,61 @@
|
||||
//Radiation storms occur when the station passes through an irradiated area, and irradiate anyone not standing in protected areas (maintenance, emergency storage, etc.)
|
||||
/datum/weather/rad_storm
|
||||
name = "radiation storm"
|
||||
desc = "A cloud of intense radiation passes through the area dealing rad damage to those who are unprotected."
|
||||
|
||||
telegraph_duration = 400
|
||||
telegraph_message = "<span class='danger'>The air begins to grow warm.</span>"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>You feel waves of heat wash over you! Find shelter!</i></span>"
|
||||
weather_overlay = "ash_storm"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
weather_color = "green"
|
||||
weather_sound = 'sound/misc/bloblarm.ogg'
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='notice'>The air seems to be cooling off again.</span>"
|
||||
|
||||
area_type = /area
|
||||
protected_areas = list(/area/maintenance, /area/turret_protected/ai_upload, /area/turret_protected/ai_upload_foyer,
|
||||
/area/turret_protected/ai, /area/storage/emergency, /area/storage/emergency2, /area/crew_quarters/sleep, /area/security/brig, /area/shuttle)
|
||||
target_trait = STATION_LEVEL
|
||||
|
||||
immunity_type = "rad"
|
||||
|
||||
/datum/weather/rad_storm/telegraph()
|
||||
..()
|
||||
status_alarm(TRUE)
|
||||
make_maint_all_access()
|
||||
|
||||
|
||||
/datum/weather/rad_storm/weather_act(mob/living/L)
|
||||
var/resist = L.getarmor(null, "rad")
|
||||
if(prob(40))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
if(!(RADIMMUNE in H.species.species_traits))
|
||||
if(prob(max(0, 100 - resist)))
|
||||
randmuti(H) // Applies bad mutation
|
||||
if(prob(50))
|
||||
if(prob(90))
|
||||
randmutb(H)
|
||||
else
|
||||
randmutg(H)
|
||||
domutcheck(H, null, 1)
|
||||
|
||||
L.apply_effect(20, IRRADIATE, resist)
|
||||
|
||||
/datum/weather/rad_storm/end()
|
||||
if(..())
|
||||
return
|
||||
priority_announcement.Announce("The radiation threat has passed. Please return to your workplaces.", "Anomaly Alert")
|
||||
status_alarm(FALSE)
|
||||
revoke_maint_all_access()
|
||||
|
||||
/datum/weather/rad_storm/proc/status_alarm(active) //Makes the status displays show the radiation warning for those who missed the announcement.
|
||||
if(active)
|
||||
post_status("alert", "radiation")
|
||||
else
|
||||
post_status("blank")
|
||||
post_status("shuttle")
|
||||
@@ -0,0 +1,28 @@
|
||||
/datum/weather/snow_storm
|
||||
name = "snow storm"
|
||||
desc = "Harsh snowstorms roam the topside of this arctic planet, burying any area unfortunate enough to be in its path."
|
||||
probability = 90
|
||||
|
||||
telegraph_message = "<span class='warning'>Drifting particles of snow begin to dust the surrounding area..</span>"
|
||||
telegraph_duration = 300
|
||||
telegraph_overlay = "light_snow"
|
||||
|
||||
weather_message = "<span class='userdanger'><i>Harsh winds pick up as dense snow begins to fall from the sky! Seek shelter!</i></span>"
|
||||
weather_overlay = "snow_storm"
|
||||
weather_duration_lower = 600
|
||||
weather_duration_upper = 1500
|
||||
|
||||
end_duration = 100
|
||||
end_message = "<span class='boldannounce'>The snowfall dies down, it should be safe to go outside again.</span>"
|
||||
|
||||
// area_type = /area/awaymission/snowdin/outside
|
||||
target_trait = AWAY_LEVEL
|
||||
|
||||
immunity_type = "snow"
|
||||
|
||||
barometer_predictable = TRUE
|
||||
|
||||
|
||||
/datum/weather/snow_storm/weather_act(mob/living/L)
|
||||
L.adjust_bodytemperature(-rand(5, 15))
|
||||
|
||||
@@ -20,13 +20,12 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
var/atmosalm = ATMOS_ALARM_NONE
|
||||
var/poweralm = 1
|
||||
var/party = null
|
||||
var/radalert = 0
|
||||
var/report_alerts = 1 // Should atmos alerts notify the AI/computers
|
||||
level = null
|
||||
name = "Space"
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "unknown"
|
||||
layer = 10
|
||||
layer = AREA_LAYER
|
||||
luminosity = 0
|
||||
mouse_opacity = 0
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
@@ -141,9 +140,6 @@ var/list/ghostteleportlocs = list()
|
||||
/area/space/readyalert()
|
||||
return
|
||||
|
||||
/area/space/radiation_alert()
|
||||
return
|
||||
|
||||
/area/space/partyalert()
|
||||
return
|
||||
|
||||
|
||||
+31
-21
@@ -22,7 +22,7 @@
|
||||
|
||||
..()
|
||||
icon_state = ""
|
||||
layer = 10
|
||||
layer = AREA_LAYER
|
||||
uid = ++global_uid
|
||||
all_areas += src
|
||||
map_name = name // Save the initial (the name set in the map) name of the area.
|
||||
@@ -45,7 +45,24 @@
|
||||
blend_mode = BLEND_MULTIPLY // Putting this in the constructor so that it stops the icons being screwed up in the map editor.
|
||||
|
||||
/area/Initialize()
|
||||
..()
|
||||
. = ..()
|
||||
|
||||
if(contents.len)
|
||||
var/list/areas_in_z = space_manager.areas_in_z
|
||||
var/z
|
||||
for(var/i in 1 to contents.len)
|
||||
var/atom/thing = contents[i]
|
||||
if(!thing)
|
||||
continue
|
||||
z = thing.z
|
||||
break
|
||||
if(!z)
|
||||
WARNING("No z found for [src]")
|
||||
return
|
||||
if(!areas_in_z["[z]"])
|
||||
areas_in_z["[z]"] = list()
|
||||
areas_in_z["[z]"] += src
|
||||
|
||||
return INITIALIZE_HINT_LATELOAD
|
||||
|
||||
/area/LateInitialize()
|
||||
@@ -160,16 +177,6 @@
|
||||
eject = 0
|
||||
updateicon()
|
||||
|
||||
/area/proc/radiation_alert()
|
||||
if(!radalert)
|
||||
radalert = 1
|
||||
updateicon()
|
||||
|
||||
/area/proc/reset_radiation_alert()
|
||||
if(radalert)
|
||||
radalert = 0
|
||||
updateicon()
|
||||
|
||||
/area/proc/partyalert()
|
||||
if(!party)
|
||||
party = 1
|
||||
@@ -183,11 +190,8 @@
|
||||
updateicon()
|
||||
|
||||
/area/proc/updateicon()
|
||||
if(radalert) // always show the radiation alert, regardless of power
|
||||
icon_state = "radiation"
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
else if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc.
|
||||
if(fire && !radalert && !eject && !party)
|
||||
if((fire || eject || party) && (!requires_power||power_environ))//If it doesn't require power, can still activate this proc.
|
||||
if(fire && !eject && !party)
|
||||
icon_state = "red"
|
||||
else if(!fire && eject && !party)
|
||||
icon_state = "red"
|
||||
@@ -197,9 +201,15 @@
|
||||
icon_state = "blue-red"
|
||||
invisibility = INVISIBILITY_LIGHTING
|
||||
else
|
||||
// new lighting behaviour with obj lights
|
||||
icon_state = null
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
var/weather_icon
|
||||
for(var/V in SSweather.processing)
|
||||
var/datum/weather/W = V
|
||||
if(W.stage != END_STAGE && (src in W.impacted_areas))
|
||||
W.update_areas()
|
||||
weather_icon = TRUE
|
||||
if(!weather_icon)
|
||||
icon_state = null
|
||||
invisibility = INVISIBILITY_MAXIMUM
|
||||
|
||||
/area/space/updateicon()
|
||||
icon_state = null
|
||||
@@ -384,4 +394,4 @@
|
||||
for(var/obj/machinery/door/airlock/temp_airlock in src)
|
||||
temp_airlock.prison_open()
|
||||
for(var/obj/machinery/door/window/temp_windoor in src)
|
||||
temp_windoor.open()
|
||||
temp_windoor.open()
|
||||
@@ -528,7 +528,8 @@
|
||||
if("alert")
|
||||
status_signal.data["picture_state"] = data1
|
||||
|
||||
frequency.post_signal(src, status_signal)
|
||||
spawn(0)
|
||||
frequency.post_signal(src, status_signal)
|
||||
|
||||
|
||||
/obj/machinery/computer/communications/Destroy()
|
||||
|
||||
@@ -205,8 +205,8 @@
|
||||
if(href_list["dstele"])
|
||||
var/choices = list(0)
|
||||
var/list/reachable_levels = levels_by_trait(REACHABLE)
|
||||
for(var/datum/space_level/S in reachable_levels)
|
||||
choices += S.zpos
|
||||
for(var/z in reachable_levels)
|
||||
choices += z
|
||||
var/obj/machinery/computer/pod/deathsquad/D = src
|
||||
var/input = input("Enter the destination Z-Level. The mechs will arrive from the East. Leave 0 if you don't want to set a specific ZLevel", "Mass Driver Controls", 0) in choices
|
||||
D.teleporter_dest = input
|
||||
|
||||
@@ -313,6 +313,9 @@ REAGENT SCANNER
|
||||
throw_range = 7
|
||||
materials = list(MAT_METAL=30, MAT_GLASS=20)
|
||||
origin_tech = "magnets=1;engineering=1"
|
||||
var/cooldown = FALSE
|
||||
var/cooldown_time = 250
|
||||
var/accuracy // 0 is the best accuracy.
|
||||
|
||||
/obj/item/analyzer/attack_self(mob/user as mob)
|
||||
|
||||
@@ -366,6 +369,69 @@ REAGENT SCANNER
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
/obj/item/analyzer/AltClick(mob/user) //Barometer output for measuring when the next storm happens
|
||||
..()
|
||||
|
||||
if(!user.incapacitated() && Adjacent(user))
|
||||
|
||||
if(cooldown)
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function is prepraring itself.</span>")
|
||||
return
|
||||
|
||||
var/turf/T = get_turf(user)
|
||||
if(!T)
|
||||
return
|
||||
|
||||
playsound(src, 'sound/effects/pop.ogg', 100)
|
||||
var/area/user_area = T.loc
|
||||
var/datum/weather/ongoing_weather = null
|
||||
|
||||
if(!user_area.outdoors)
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function won't work indoors!</span>")
|
||||
return
|
||||
|
||||
for(var/V in SSweather.processing)
|
||||
var/datum/weather/W = V
|
||||
if(W.barometer_predictable && (T.z in W.impacted_z_levels) && W.area_type == user_area.type && !(W.stage == END_STAGE))
|
||||
ongoing_weather = W
|
||||
break
|
||||
|
||||
if(ongoing_weather)
|
||||
if((ongoing_weather.stage == MAIN_STAGE) || (ongoing_weather.stage == WIND_DOWN_STAGE))
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function can't trace anything while the storm is [ongoing_weather.stage == MAIN_STAGE ? "already here!" : "winding down."]</span>")
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>The next [ongoing_weather] will hit in [butchertime(ongoing_weather.next_hit_time - world.time)].</span>")
|
||||
if(ongoing_weather.aesthetic)
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function says that the next storm will breeze on by.</span>")
|
||||
else
|
||||
var/next_hit = SSweather.next_hit_by_zlevel["[T.z]"]
|
||||
var/fixed = next_hit ? next_hit - world.time : -1
|
||||
if(fixed < 0)
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function was unable to trace any weather patterns.</span>")
|
||||
else
|
||||
to_chat(user, "<span class='warning'>[src]'s barometer function says a storm will land in approximately [butchertime(fixed)].</span>")
|
||||
cooldown = TRUE
|
||||
addtimer(CALLBACK(src,/obj/item/analyzer/proc/ping), cooldown_time)
|
||||
|
||||
/obj/item/analyzer/proc/ping()
|
||||
if(isliving(loc))
|
||||
var/mob/living/L = loc
|
||||
to_chat(L, "<span class='notice'>[src]'s barometer function is ready!</span>")
|
||||
playsound(src, 'sound/machines/click.ogg', 100)
|
||||
cooldown = FALSE
|
||||
|
||||
/obj/item/analyzer/proc/butchertime(amount)
|
||||
if(!amount)
|
||||
return
|
||||
if(accuracy)
|
||||
var/inaccurate = round(accuracy * (1 / 3))
|
||||
if(prob(50))
|
||||
amount -= inaccurate
|
||||
if(prob(50))
|
||||
amount += inaccurate
|
||||
return DisplayTimeText(max(1, amount))
|
||||
|
||||
/obj/item/mass_spectrometer
|
||||
desc = "A hand-held mass spectrometer which identifies trace chemicals in a blood sample. Inject sample with syringe."
|
||||
name = "mass-spectrometer"
|
||||
|
||||
@@ -94,8 +94,7 @@
|
||||
var/max = world.maxx-TRANSITIONEDGE
|
||||
var/min = 1+TRANSITIONEDGE
|
||||
|
||||
var/datum/space_level/dest = pick(levels_by_trait(REACHABLE))
|
||||
var/_z = dest.zpos //select a random space zlevel
|
||||
var/_z = pick(levels_by_trait(REACHABLE)) //select a random space zlevel
|
||||
|
||||
//now select coordinates for a border turf
|
||||
var/_x
|
||||
|
||||
@@ -80,7 +80,6 @@
|
||||
<A href='?src=[UID()];secretsfun=securitylevel5'>Security Level - Delta</A><BR>
|
||||
<b>Create Weather</b><BR>
|
||||
<A href='?src=[UID()];secretsfun=weatherashstorm'>Weather - Ash Storm</A>
|
||||
<A href='?src=[UID()];secretsfun=weatherdarkness'>Weather - Advanced Darkness</A>
|
||||
<BR>
|
||||
</center>"}
|
||||
|
||||
|
||||
@@ -2727,48 +2727,6 @@
|
||||
for(var/mob/M in player_list)
|
||||
if(M.stat != 2)
|
||||
M.show_message(text("<span class='notice'>The chilling wind suddenly stops...</span>"), 1)
|
||||
/* if("shockwave")
|
||||
ok = 1
|
||||
to_chat(world, "<span class='danger'><big>ALERT: STATION STRESS CRITICAL</big></span>")
|
||||
sleep(60)
|
||||
to_chat(world, "<span class='danger'><big>ALERT: STATION STRESS CRITICAL. TOLERABLE LEVELS EXCEEDED!</big></span>")
|
||||
sleep(80)
|
||||
to_chat(world, "<span class='danger'><big>ALERT: STATION STRUCTURAL STRESS CRITICAL. SAFETY MECHANISMS FAILED!</big></span>")
|
||||
sleep(40)
|
||||
for(var/mob/M in world)
|
||||
shake_camera(M, 400, 1)
|
||||
for(var/obj/structure/window/W in world)
|
||||
spawn(0)
|
||||
sleep(rand(10,400))
|
||||
W.ex_act(rand(2,1))
|
||||
for(var/obj/structure/grille/G in world)
|
||||
spawn(0)
|
||||
sleep(rand(20,400))
|
||||
G.ex_act(rand(2,1))
|
||||
for(var/obj/machinery/door/D in world)
|
||||
spawn(0)
|
||||
sleep(rand(20,400))
|
||||
D.ex_act(rand(2,1))
|
||||
for(var/turf/station/floor/Floor in world)
|
||||
spawn(0)
|
||||
sleep(rand(30,400))
|
||||
Floor.ex_act(rand(2,1))
|
||||
for(var/obj/structure/cable/Cable in world)
|
||||
spawn(0)
|
||||
sleep(rand(30,400))
|
||||
Cable.ex_act(rand(2,1))
|
||||
for(var/obj/structure/closet/Closet in world)
|
||||
spawn(0)
|
||||
sleep(rand(30,400))
|
||||
Closet.ex_act(rand(2,1))
|
||||
for(var/obj/machinery/Machinery in world)
|
||||
spawn(0)
|
||||
sleep(rand(30,400))
|
||||
Machinery.ex_act(rand(1,3))
|
||||
for(var/turf/station/wall/Wall in world)
|
||||
spawn(0)
|
||||
sleep(rand(30,400))
|
||||
Wall.ex_act(rand(2,1)) */
|
||||
if("lightout")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","LO")
|
||||
@@ -2793,7 +2751,7 @@
|
||||
var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No")
|
||||
if(sure == "No")
|
||||
return
|
||||
weather_master.run_weather("the floor is lava")
|
||||
SSweather.run_weather(/datum/weather/floor_is_lava)
|
||||
message_admins("[key_name_admin(usr)] made the floor lava")
|
||||
if("fakelava")
|
||||
feedback_inc("admin_secrets_fun_used", 1)
|
||||
@@ -2801,7 +2759,7 @@
|
||||
var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No")
|
||||
if(sure == "No")
|
||||
return
|
||||
weather_master.run_weather("fake lava")
|
||||
SSweather.run_weather(/datum/weather/floor_is_lava/fake)
|
||||
message_admins("[key_name_admin(usr)] made aesthetic lava on the floor")
|
||||
if("weatherashstorm")
|
||||
feedback_inc("admin_secrets_fun_used", 1)
|
||||
@@ -2809,16 +2767,8 @@
|
||||
var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No")
|
||||
if(sure == "No")
|
||||
return
|
||||
weather_master.run_weather("ash storm")
|
||||
SSweather.run_weather(/datum/weather/ash_storm)
|
||||
message_admins("[key_name_admin(usr)] spawned an ash storm on the mining asteroid")
|
||||
if("weatherdarkness")
|
||||
feedback_inc("admin_secrets_fun_used", 1)
|
||||
feedback_add_details("admin_secrets_fun_used", "WD")
|
||||
var/sure = alert(usr, "Are you sure you want to do this?", "Confirmation", "Yes", "No")
|
||||
if(sure == "No")
|
||||
return
|
||||
weather_master.run_weather("advanced darkness")
|
||||
message_admins("[key_name_admin(usr)] made the station go through advanced darkness")
|
||||
if("retardify")
|
||||
feedback_inc("admin_secrets_fun_used",1)
|
||||
feedback_add_details("admin_secrets_fun_used","RET")
|
||||
|
||||
@@ -1,70 +1,11 @@
|
||||
/datum/event/radiation_storm
|
||||
announceWhen = 1
|
||||
var/safe_zones = list(
|
||||
/area/maintenance,
|
||||
/area/crew_quarters/sleep,
|
||||
/area/security/brig,
|
||||
/area/shuttle,
|
||||
/area/vox_station,
|
||||
/area/syndicate_station
|
||||
)
|
||||
|
||||
/datum/event/radiation_storm/setup()
|
||||
startWhen = 3
|
||||
endWhen = startWhen + 1
|
||||
announceWhen = 1
|
||||
|
||||
/datum/event/radiation_storm/announce()
|
||||
// Don't do anything, we want to pack the announcement with the actual event
|
||||
|
||||
/datum/event/radiation_storm/proc/is_safe_zone(var/area/A)
|
||||
for(var/szt in safe_zones)
|
||||
if(istype(A, szt))
|
||||
return 1
|
||||
return 0
|
||||
priority_announcement.Announce("High levels of radiation detected near the station. Maintenance is best shielded from radiation.", "Anomaly Alert", 'sound/ai/radiation.ogg')
|
||||
//sound not longer matches the text, but an audible warning is probably good
|
||||
|
||||
/datum/event/radiation_storm/start()
|
||||
spawn()
|
||||
event_announcement.Announce("High levels of radiation detected near the station. Please evacuate into one of the shielded maintenance tunnels.", "Anomaly Alert", new_sound = 'sound/AI/radiation.ogg')
|
||||
|
||||
for(var/area/A in world)
|
||||
if(!is_station_level(A.z) || is_safe_zone(A))
|
||||
continue
|
||||
A.radiation_alert()
|
||||
|
||||
make_maint_all_access()
|
||||
|
||||
sleep(600)
|
||||
|
||||
event_announcement.Announce("The station has entered the radiation belt. Please remain in a sheltered area until we have passed the radiation belt.", "Anomaly Alert")
|
||||
|
||||
for(var/i = 0, i < 10, i++)
|
||||
for(var/mob/living/carbon/human/H in living_mob_list)
|
||||
var/armor = H.getarmor(type = "rad")
|
||||
if((RADIMMUNE in H.species.species_traits) || armor >= 100) // Leave radiation-immune species/fully rad armored players completely unaffected
|
||||
continue
|
||||
var/turf/T = get_turf(H)
|
||||
if(!T)
|
||||
continue
|
||||
if(!is_station_level(T.z) || is_safe_zone(T.loc))
|
||||
continue
|
||||
|
||||
if(istype(H,/mob/living/carbon/human))
|
||||
H.apply_effect((rand(15,35)),IRRADIATE,0)
|
||||
if(prob(5))
|
||||
H.apply_effect((rand(40,70)),IRRADIATE,0)
|
||||
if(prob(75))
|
||||
randmutb(H) // Applies bad mutation
|
||||
domutcheck(H,null,1)
|
||||
else
|
||||
randmutg(H) // Applies good mutation
|
||||
domutcheck(H,null,1)
|
||||
|
||||
sleep(100)
|
||||
|
||||
event_announcement.Announce("The station has passed the radiation belt. Please report to medbay if you experience any unusual symptoms. Maintenance will lose all access again shortly.", "Anomaly Alert")
|
||||
|
||||
for(var/area/A in world)
|
||||
if(!is_station_level(A.z) || is_safe_zone(A))
|
||||
continue
|
||||
A.reset_radiation_alert()
|
||||
|
||||
sleep(600) // Want to give them time to get out of maintenance.
|
||||
|
||||
revoke_maint_all_access()
|
||||
SSweather.run_weather(/datum/weather/rad_storm)
|
||||
@@ -5,7 +5,6 @@
|
||||
item_state = "staffofstorms"
|
||||
icon = 'icons/obj/guns/magic.dmi'
|
||||
slot_flags = SLOT_BACK
|
||||
item_state = "staffofstorms"
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 25
|
||||
damtype = BURN
|
||||
@@ -19,34 +18,36 @@
|
||||
return
|
||||
|
||||
var/area/user_area = get_area(user)
|
||||
var/turf/user_turf = get_turf(user)
|
||||
if(!user_area || !user_turf)
|
||||
to_chat(user, "<span class='warning'>Something is preventing you from using the staff here.</span>")
|
||||
return
|
||||
var/datum/weather/A
|
||||
var/z_level_name = space_manager.levels_by_name[user.z]
|
||||
for(var/V in weather_master.existing_weather)
|
||||
for(var/V in SSweather.processing)
|
||||
var/datum/weather/W = V
|
||||
if(W.target_z == z_level_name && W.area_type == user_area.type)
|
||||
if((user_turf.z in W.impacted_z_levels) && W.area_type == user_area.type)
|
||||
A = W
|
||||
break
|
||||
if(A)
|
||||
|
||||
if(A)
|
||||
if(A.stage != END_STAGE)
|
||||
if(A.stage == WIND_DOWN_STAGE)
|
||||
to_chat(user, "<span class='warning'>The storm is already ending! It would be a waste to use the staff now.</span>")
|
||||
return
|
||||
user.visible_message("<span class='warning'>[user] holds [src] skywards as an orange beam travels into the sky!</span>", \
|
||||
"<span class='notice'>You hold [src] skyward, dispelling the storm!</span>")
|
||||
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
|
||||
playsound(user, 'sound/magic/staff_change.ogg', 200, 0)
|
||||
A.wind_down()
|
||||
return
|
||||
else
|
||||
A = new storm_type
|
||||
A = new storm_type(list(user_turf.z))
|
||||
A.name = "staff storm"
|
||||
A.area_type = user_area.type
|
||||
A.target_z = z_level_name
|
||||
A.telegraph_duration = 100
|
||||
A.end_duration = 100
|
||||
|
||||
user.visible_message("<span class='warning'>[user] holds [src] skywards as red lightning crackles into the sky!</span>", \
|
||||
"<span class='notice'>You hold [src] skyward, calling down a terrible storm!</span>")
|
||||
playsound(user, 'sound/magic/Staff_Change.ogg', 200, 0)
|
||||
playsound(user, 'sound/magic/staff_change.ogg', 200, 0)
|
||||
A.telegraph()
|
||||
storm_cooldown = world.time + 200
|
||||
|
||||
@@ -208,3 +208,7 @@
|
||||
|
||||
/mob/proc/AdjustWeakened()
|
||||
return
|
||||
|
||||
/mob/proc/adjust_bodytemperature(amount, min_temp = 0, max_temp = INFINITY)
|
||||
if(bodytemperature > min_temp && bodytemperature < max_temp)
|
||||
bodytemperature = Clamp(bodytemperature + amount, min_temp, max_temp)
|
||||
@@ -1,62 +1,63 @@
|
||||
/proc/is_level_reachable(z)
|
||||
return check_level_trait(z, REACHABLE)
|
||||
return check_level_trait(z, REACHABLE)
|
||||
|
||||
/proc/is_station_level(z)
|
||||
return check_level_trait(z, STATION_LEVEL)
|
||||
return check_level_trait(z, STATION_LEVEL)
|
||||
|
||||
/proc/is_station_contact(z)
|
||||
return check_level_trait(z, STATION_CONTACT)
|
||||
return check_level_trait(z, STATION_CONTACT)
|
||||
|
||||
/proc/is_teleport_allowed(z)
|
||||
return !check_level_trait(z, BLOCK_TELEPORT)
|
||||
return !check_level_trait(z, BLOCK_TELEPORT)
|
||||
|
||||
/proc/is_admin_level(z)
|
||||
return check_level_trait(z, ADMIN_LEVEL)
|
||||
return check_level_trait(z, ADMIN_LEVEL)
|
||||
|
||||
/proc/is_away_level(z)
|
||||
return check_level_trait(z, AWAY_LEVEL)
|
||||
return check_level_trait(z, AWAY_LEVEL)
|
||||
|
||||
/proc/is_mining_level(z)
|
||||
return check_level_trait(z, ORE_LEVEL)
|
||||
return check_level_trait(z, ORE_LEVEL)
|
||||
|
||||
/proc/is_ai_allowed(z)
|
||||
return check_level_trait(z, AI_OK)
|
||||
return check_level_trait(z, AI_OK)
|
||||
|
||||
/proc/level_blocks_magic(z)
|
||||
return check_level_trait(z, IMPEDES_MAGIC)
|
||||
return check_level_trait(z, IMPEDES_MAGIC)
|
||||
|
||||
/proc/level_boosts_signal(z)
|
||||
return check_level_trait(z, BOOSTS_SIGNAL)
|
||||
return check_level_trait(z, BOOSTS_SIGNAL)
|
||||
|
||||
// Used for the nuke disk, or for checking if players survived through xenos
|
||||
/proc/is_secure_level(z)
|
||||
var/secure = check_level_trait(z, STATION_LEVEL)
|
||||
if(!secure)
|
||||
// This is to allow further admin levels later, other than centcomm
|
||||
secure = (z == level_name_to_num(CENTCOMM))
|
||||
return secure
|
||||
var/secure = check_level_trait(z, STATION_LEVEL)
|
||||
if(!secure)
|
||||
// This is to allow further admin levels later, other than centcomm
|
||||
secure = (z == level_name_to_num(CENTCOMM))
|
||||
return secure
|
||||
|
||||
var/list/default_map_traits = MAP_TRANSITION_CONFIG
|
||||
|
||||
/proc/check_level_trait(z, trait)
|
||||
if(!z)
|
||||
return 0 // If you're nowhere, you have no traits
|
||||
var/list/trait_list
|
||||
if(space_manager.initialized)
|
||||
var/datum/space_level/S = space_manager.get_zlev(z)
|
||||
trait_list = S.flags
|
||||
else
|
||||
trait_list = default_map_traits[z]
|
||||
trait_list = trait_list["attributes"]
|
||||
return (trait in trait_list)
|
||||
if(!z)
|
||||
return 0 // If you're nowhere, you have no traits
|
||||
var/list/trait_list
|
||||
if(space_manager.initialized)
|
||||
var/datum/space_level/S = space_manager.get_zlev(z)
|
||||
trait_list = S.flags
|
||||
else
|
||||
trait_list = default_map_traits[z]
|
||||
trait_list = trait_list["attributes"]
|
||||
return (trait in trait_list)
|
||||
|
||||
/proc/levels_by_trait(trait)
|
||||
var/list/result = list()
|
||||
for(var/A in space_manager.z_list)
|
||||
var/datum/space_level/S = space_manager.z_list[A]
|
||||
if(trait in S.flags)
|
||||
result |= S
|
||||
return result
|
||||
var/list/result = list()
|
||||
for(var/A in space_manager.z_list)
|
||||
var/datum/space_level/S = space_manager.z_list[A]
|
||||
if(trait in S.flags)
|
||||
result |= S.zpos
|
||||
return result
|
||||
|
||||
/proc/level_name_to_num(name)
|
||||
var/datum/space_level/S = space_manager.get_zlev_by_name(name)
|
||||
return S.zpos
|
||||
var/datum/space_level/S = space_manager.get_zlev_by_name(name)
|
||||
return S.zpos
|
||||
@@ -12,6 +12,8 @@ var/global/datum/zlev_manager/space_manager = new
|
||||
var/datum/spacewalk_grid/linkage_map
|
||||
var/initialized = 0
|
||||
|
||||
var/list/areas_in_z = list()
|
||||
|
||||
// Populate our space level list
|
||||
// and prepare space transitions
|
||||
/datum/zlev_manager/proc/initialize()
|
||||
@@ -166,4 +168,4 @@ var/global/datum/zlev_manager/space_manager = new
|
||||
var/datum/space_level/heap/heap = z_list["[C.zpos]"]
|
||||
if(!istype(heap))
|
||||
throw EXCEPTION("Attempted to free chunk at invalid z-level ([C.x],[C.y],[C.zpos]) [C.width]x[C.height]")
|
||||
heap.free(C)
|
||||
heap.free(C)
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 18 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 122 KiB After Width: | Height: | Size: 122 KiB |
+6
-2
@@ -198,7 +198,6 @@
|
||||
#include "code\controllers\Processes\obj.dm"
|
||||
#include "code\controllers\Processes\shuttles.dm"
|
||||
#include "code\controllers\Processes\ticker.dm"
|
||||
#include "code\controllers\Processes\weather.dm"
|
||||
#include "code\controllers\ProcessScheduler\core\process.dm"
|
||||
#include "code\controllers\ProcessScheduler\core\processScheduler.dm"
|
||||
#include "code\controllers\subsystem\air.dm"
|
||||
@@ -213,6 +212,7 @@
|
||||
#include "code\controllers\subsystem\sun.dm"
|
||||
#include "code\controllers\subsystem\throwing.dm"
|
||||
#include "code\controllers\subsystem\timer.dm"
|
||||
#include "code\controllers\subsystem\weather.dm"
|
||||
#include "code\controllers\subsystem\processing\processing.dm"
|
||||
#include "code\datums\action.dm"
|
||||
#include "code\datums\ai_law_sets.dm"
|
||||
@@ -313,6 +313,7 @@
|
||||
#include "code\datums\helper_datums\topic_input.dm"
|
||||
#include "code\datums\looping_sounds\looping_sound.dm"
|
||||
#include "code\datums\looping_sounds\machinery_sounds.dm"
|
||||
#include "code\datums\looping_sounds\weather.dm"
|
||||
#include "code\datums\outfits\outfit.dm"
|
||||
#include "code\datums\outfits\outfit_admin.dm"
|
||||
#include "code\datums\ruins\space.dm"
|
||||
@@ -352,7 +353,10 @@
|
||||
#include "code\datums\status_effects\status_effect.dm"
|
||||
#include "code\datums\vr\level.dm"
|
||||
#include "code\datums\weather\weather.dm"
|
||||
#include "code\datums\weather\weather_types.dm"
|
||||
#include "code\datums\weather\weather_types\ash_storm.dm"
|
||||
#include "code\datums\weather\weather_types\floor_is_lava.dm"
|
||||
#include "code\datums\weather\weather_types\radiation_storm.dm"
|
||||
#include "code\datums\weather\weather_types\snow_storm.dm"
|
||||
#include "code\datums\wires\airlock.dm"
|
||||
#include "code\datums\wires\alarm.dm"
|
||||
#include "code\datums\wires\apc.dm"
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user