Merge pull request #9050 from Fox-McCloud/weather-subsystem

Converts and Updates Weather Subsystem
This commit is contained in:
tigercat2000
2018-06-13 16:08:02 -07:00
committed by GitHub
51 changed files with 608 additions and 426 deletions
+47
View File
@@ -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
+33 -36
View File
@@ -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)
-118
View File
@@ -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))