Lavaland weather types: Dying is Fun edition (#28600)

* ddsadsa

ddsadsa

* beginning

* more progress

* oops saved

* radar workin now

* bugfixing and tweaks

* working on volcano

* tweaking

* ill figure this out later

* testing still

* MORE testing

* gunna cry

* PROGRESS!!!

* volcano DONE

* starting the acid rain

* acid rain code complete

* starting windstorm

* more bugfixing...

* its finished! need to bugtest

* bugfixing

* bugfixing

* forgot prob values

* spacing fix for linter

* linter fix

* undefining things

* Update code/datums/weather/weather_types/lavaland_weather.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/datums/weather/weather_types/lavaland_weather.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/datums/weather/weather_types/lavaland_weather.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* misc fixes/changes

* updated the doppler tower

* small tweaks

* still trying to get pods to work

* better support for sound transition to newly placed shelters

* minor fixes

* this didnt take oops

* nudged the probabilities

* deconflicting

* Update code/datums/weather/weather_types/lavaland_weather.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* Update code/game/machinery/radar.dm

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* applied requested fixes

* master update

* updates

* this should be here

* Apply suggestions from code review

Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>

* requested fixes

* sound tweaks

* remove debug message

* turned down ash storm sound

* fix gulag weather and attempt to fix sound overlap

* blackbox weather and title-case ash storms

* change up probabilities and bump acid rain melt chance

* another title case

* starting on issues

* revert some changes

* tiny tweak

* reworked acid rain a bit

* small tweaks to sleepers

* moderate again

* revert

* ups the rocks

* bug fixes

---------

Signed-off-by: Kyani <65205627+EmeraldCandy@users.noreply.github.com>
Co-authored-by: warriorstar-orion <orion@snowfrost.garden>
This commit is contained in:
Kyani
2025-04-18 20:18:38 +00:00
committed by GitHub
co-authored by warriorstar-orion
parent 21b6dcbe64
commit d2c761821a
38 changed files with 1171 additions and 344 deletions
+42 -1
View File
@@ -4,7 +4,7 @@
'sound/weather/ashstorm/outside/active_mid1.ogg' = 1,
'sound/weather/ashstorm/outside/active_mid1.ogg' = 1
)
mid_length = 80
mid_length = 65
start_sound = 'sound/weather/ashstorm/outside/active_start.ogg'
start_length = 130
end_sound = 'sound/weather/ashstorm/outside/active_end.ogg'
@@ -53,3 +53,44 @@
volume = 30
area_sound = TRUE
channel = CHANNEL_ASH_STORM
/datum/looping_sound/active_outside_acid
mid_sounds = 'sound/weather/acid/outside/active_mid1.ogg'
mid_length = 105
start_sound = list('sound/weather/acid/outside/active_start.ogg' = 1)
start_length = 130
end_sound = 'sound/weather/acid/outside/active_end.ogg'
volume = 65
area_sound = TRUE
channel = CHANNEL_ASH_STORM
/datum/looping_sound/weak_outside_acid
mid_sounds ='sound/weather/acid/outside/weak_mid1.ogg'
mid_length = 120
start_sound = list('sound/weather/acid/outside/weak_start.ogg' = 1)
start_length = 130
end_sound = 'sound/weather/acid/outside/weak_end.ogg'
volume = 60
area_sound = TRUE
channel = CHANNEL_ASH_STORM
/datum/looping_sound/active_inside_acid
mid_sounds = 'sound/weather/acid/inside/active_mid1.ogg'
mid_length = 105
start_sound = list('sound/weather/acid/inside/active_start.ogg' = 1)
start_length = 130
end_sound = 'sound/weather/acid/inside/active_end.ogg'
volume = 50
area_sound = TRUE
channel = CHANNEL_ASH_STORM
/datum/looping_sound/weak_inside_acid
mid_sounds = 'sound/weather/acid/inside/weak_mid1.ogg'
mid_length = 105
start_sound = list('sound/weather/acid/inside/weak_start.ogg' = 1)
start_length = 130
end_sound = 'sound/weather/acid/inside/weak_end.ogg'
volume = 50
area_sound = TRUE
channel = CHANNEL_ASH_STORM
+69 -4
View File
@@ -1,5 +1,7 @@
//The effects of weather occur across an entire z-level. For instance, lavaland has periodic ash storms that scorch most unprotected creatures.
GLOBAL_LIST_EMPTY(all_shelter_pods)
/datum/weather
var/name = "space wind"
var/desc = "Heavy gusts of wind blanket the area, periodically knocking down anyone caught in the open."
@@ -22,13 +24,15 @@
var/end_sound
var/end_overlay
var/area_type = /area/space //Types of area to affect
var/area_types = list(/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/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 = 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/overlay_plane = AREA_PLANE
var/custom_overlay // Do we want to give it a non-standard weather effect
var/overlay_dir = NORTH
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
@@ -41,14 +45,27 @@
var/barometer_predictable = FALSE
var/next_hit_time = 0 //For barometers to know when the next storm will hit
var/area_act = FALSE // Does this affect more than just mobs, or the landscape?
var/list/inside_areas = list() // Any areas not in the outside terf
var/list/outside_areas = list() // Any areas listed as "outside"
var/list/eligible_areas = list() // For variable playing or not playing sounds for shuttles
/datum/weather/New(z_levels)
..()
impacted_z_levels = z_levels
RegisterSignal(SSdcs, COMSIG_GLOB_SHELTER_PLACED, PROC_REF(on_shelter_placed))
/datum/weather/proc/on_shelter_placed(datum/source, turf/center)
SIGNAL_HANDLER // COMSIG_GLOB_SHELTER_PLACED
GLOB.all_shelter_pods += center
return
/datum/weather/proc/generate_area_list()
var/list/affectareas = list()
for(var/V in get_areas(area_type))
affectareas += V
for(var/area_type in area_types)
for(var/V in get_areas(area_type))
affectareas += V
for(var/V in protected_areas)
affectareas -= get_areas(V)
for(var/V in affectareas)
@@ -64,6 +81,8 @@
weather_duration = rand(weather_duration_lower, weather_duration_upper)
START_PROCESSING(SSweather, src)
update_areas()
update_eligible_areas()
update_audio()
for(var/M in GLOB.player_list)
var/turf/mob_turf = get_turf(M)
if(mob_turf && (mob_turf.z in impacted_z_levels))
@@ -71,6 +90,7 @@
to_chat(M, telegraph_message)
if(telegraph_sound)
SEND_SOUND(M, sound(telegraph_sound))
addtimer(CALLBACK(src, PROC_REF(start)), telegraph_duration)
/datum/weather/proc/start()
@@ -78,6 +98,7 @@
return
stage = WEATHER_MAIN_STAGE
update_areas()
update_audio()
for(var/M in GLOB.player_list)
var/turf/mob_turf = get_turf(M)
if(mob_turf && (mob_turf.z in impacted_z_levels))
@@ -92,6 +113,7 @@
return
stage = WEATHER_WIND_DOWN_STAGE
update_areas()
update_audio()
for(var/M in GLOB.player_list)
var/turf/mob_turf = get_turf(M)
if(mob_turf && (mob_turf.z in impacted_z_levels))
@@ -107,6 +129,7 @@
stage = WEATHER_END_STAGE
STOP_PROCESSING(SSweather, src)
update_areas()
update_audio()
/datum/weather/proc/can_weather_act(mob/living/L) //Can this weather impact a mob?
var/turf/mob_turf = get_turf(L)
@@ -128,7 +151,12 @@
var/area/N = V
N.layer = overlay_layer
N.plane = overlay_plane
N.icon = 'icons/effects/weather_effects.dmi'
if(!custom_overlay)
N.icon = 'icons/effects/weather_effects.dmi'
else
N.icon = custom_overlay
if(overlay_dir)
N.dir = overlay_dir
N.invisibility = 0
N.color = weather_color
switch(stage)
@@ -142,6 +170,43 @@
N.color = null
N.icon_state = ""
N.icon = 'icons/turf/areas.dmi'
N.dir = NORTH
N.layer = initial(N.layer)
N.plane = initial(N.plane)
N.set_opacity(FALSE)
/datum/weather/proc/update_eligible_areas()
for(var/z in impacted_z_levels)
for(var/area/A in GLOB.space_manager.areas_in_z["[z]"])
eligible_areas |= A
// Don't play storm audio to shuttles that are not at lavaland
var/miningShuttleDocked = is_shuttle_docked("mining", "mining_away")
if(!miningShuttleDocked)
eligible_areas -= get_areas(/area/shuttle/mining)
var/laborShuttleDocked = is_shuttle_docked("laborcamp", "laborcamp_away")
if(!laborShuttleDocked)
eligible_areas -= get_areas(/area/shuttle/siberia)
var/golemShuttleOnPlanet = is_shuttle_docked("freegolem", "freegolem_lavaland")
if(!golemShuttleOnPlanet)
eligible_areas -= get_areas(/area/shuttle/freegolem)
for(var/i in 1 to length(eligible_areas))
var/area/place = eligible_areas[i]
if(place.outdoors)
outside_areas |= place
else
inside_areas |= place
/datum/weather/proc/is_shuttle_docked(shuttleId, dockId)
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
return M && M.getDockedId() == dockId
/datum/weather/proc/area_act()
return
/datum/weather/proc/update_audio()
return
@@ -1,148 +0,0 @@
//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='boldannounceic'>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/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/proc/is_shuttle_docked(shuttleId, dockId)
var/obj/docking_port/mobile/M = SSshuttle.getShuttle(shuttleId)
return M && M.getDockedId() == dockId
/datum/weather/ash_storm/proc/update_eligible_areas()
var/list/inside_areas = list()
var/list/outside_areas = list()
var/list/eligible_areas = list()
for(var/z in impacted_z_levels)
if("[z]" in GLOB.space_manager.areas_in_z)
eligible_areas += GLOB.space_manager.areas_in_z["[z]"]
// Don't play storm audio to shuttles that are not at lavaland
var/miningShuttleDocked = is_shuttle_docked("mining", "mining_away")
if(!miningShuttleDocked)
eligible_areas -= get_areas(/area/shuttle/mining)
var/laborShuttleDocked = is_shuttle_docked("laborcamp", "laborcamp_away")
if(!laborShuttleDocked)
eligible_areas -= get_areas(/area/shuttle/siberia)
var/golemShuttleOnPlanet = is_shuttle_docked("freegolem", "freegolem_lavaland")
if(!golemShuttleOnPlanet)
eligible_areas -= get_areas(/area/shuttle/freegolem)
while(length(eligible_areas))
var/area/place = eligible_areas[length(eligible_areas)]
if(place.outdoors)
outside_areas += place
else
inside_areas += place
eligible_areas.len--
sound_ao.output_atoms = outside_areas
sound_ai.output_atoms = inside_areas
sound_wo.output_atoms = outside_areas
sound_wi.output_atoms = inside_areas
/datum/weather/ash_storm/proc/update_audio()
switch(stage)
if(WEATHER_STARTUP_STAGE)
sound_wo.start()
sound_wi.start()
if(WEATHER_MAIN_STAGE)
sound_wo.stop()
sound_wi.stop()
sound_ao.start()
sound_ai.start()
if(WEATHER_WIND_DOWN_STAGE)
sound_ao.stop()
sound_ai.stop()
sound_wo.start()
sound_wi.start()
if(WEATHER_END_STAGE)
sound_wo.stop()
sound_wi.stop()
/datum/weather/ash_storm/generate_area_list()
. = ..()
// I'm a lazy fuck and it's either this or refactor procgen again
impacted_areas |= get_areas(/area/lavaland/surface/gulag_rock)
/datum/weather/ash_storm/telegraph()
. = ..()
update_eligible_areas()
update_audio()
/datum/weather/ash_storm/start()
. = ..()
update_audio()
/datum/weather/ash_storm/wind_down()
. = ..()
update_audio()
/datum/weather/ash_storm/end()
. = ..()
update_audio()
/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_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
@@ -14,7 +14,7 @@
end_message = "<span class='danger'>The ground cools and returns to its usual form.</span>"
end_duration = 0
area_type = /area
area_types = list(/area)
protected_areas = list(/area/space)
target_trait = STATION_LEVEL
@@ -0,0 +1,470 @@
#define ROCKFALL_DELAY 10 // For how long until the boulders hit the ground
/// MARK: Ash Storm
//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='boldannounceic'>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_types = list(/area/lavaland/surface/outdoors, /area/lavaland/surface/gulag_rock)
target_trait = ORE_LEVEL
immunity_type = "ash"
probability = 25
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/update_eligible_areas()
. = ..()
sound_ao.output_atoms = outside_areas
sound_ai.output_atoms = inside_areas
sound_wo.output_atoms = outside_areas
sound_wi.output_atoms = inside_areas
/datum/weather/ash_storm/update_audio()
switch(stage)
if(WEATHER_STARTUP_STAGE)
sound_wo.start()
sound_wi.start()
if(WEATHER_MAIN_STAGE)
sound_wo.stop()
sound_wi.stop()
sound_ao.start()
sound_ai.start()
if(WEATHER_WIND_DOWN_STAGE)
sound_ao.stop()
sound_ai.stop()
sound_wo.start()
sound_wi.start()
if(WEATHER_END_STAGE)
sound_wo.stop()
sound_wi.stop()
/datum/weather/ash_storm/on_shelter_placed(datum/source, turf/center)
. = ..()
if(center.z in impacted_z_levels)
var/area/A = get_area(center)
inside_areas |= A
sound_ai.output_atoms |= A
sound_wi.output_atoms |= A
/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?
if(is_human_ash_immune(L))
return TRUE
L = L.loc //Matryoshka check
return FALSE //RIP you
/datum/weather/ash_storm/proc/is_human_ash_immune(mob/living/carbon/human/H)
var/thermal_protection = H.get_thermal_protection()
if(thermal_protection >= (FIRE_IMMUNITY_MAX_TEMP_PROTECT - 15))
return TRUE
/datum/weather/ash_storm/weather_act(mob/living/L)
if(is_ash_immune(L))
return
L.adjustFireLoss(4)
/// MARK: Heavy Ash Storm
// Radar needed to detect the difference, but shouldnt matter much
/datum/weather/ash_storm/heavy
name = "Heavy ash storm"
desc = "An even more 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."
//lasts longer
weather_duration_lower = 800
weather_duration_upper = 1600
probability = 10
/datum/weather/ash_storm/heavy/is_human_ash_immune(mob/living/carbon/human/H)
var/thermal_protection = H.get_thermal_protection()
if(thermal_protection >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
return TRUE
/datum/weather/ash_storm/heavy/weather_act(mob/living/L)
if(is_ash_immune(L))
return
L.adjustFireLoss(6) // does more damage
/// MARK: Emberfall
//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 = 25
/// MARK: Volcano
/datum/weather/volcano
name = "Volcanic activity"
desc = "The shifting tectonic forces on the unstable planet have caused volcanic activity in the area. New rivers/chasms will form and chunks of rock will rain from the sky."
telegraph_message = "<span class='boldwarning'><i>The ground rumbles with an ominous strength, threatening to shift below you. Seek shelter.</i></span>"
telegraph_duration = 600
telegraph_sound = 'sound/weather/volcano/lavaland_volcano_warning.ogg'
weather_message = "<span class='userdanger'><i>A massive plume of smoke and magma can be seen billowing in the distance. The ground quakes and threatens to split. Find shelter now!.</i></span>"
weather_duration_lower = 600
weather_duration_upper = 1200
weather_sound = 'sound/weather/volcano/lavaland_volcano_eruption.ogg'
// No end message. Radar will give you the safety message on this one, or your instincts
end_duration = 300
end_message = ""
area_types = list(/area/lavaland/surface/outdoors, /area/lavaland/surface/gulag_rock)
target_trait = ORE_LEVEL
probability = 5
barometer_predictable = TRUE
area_act = TRUE
// The time until the next rock falls from the sky
var/next_rubble
// Has a river already been generated this storm?
var/generated_river = FALSE
// What tiles can we hit with a rock?
var/list/valid_targets = list()
/datum/weather/volcano/New()
next_rubble = world.time + 10 SECONDS // Short delay
. = ..()
/datum/weather/volcano/area_act()
if(prob(1) && !generated_river)
generated_river = TRUE
var/datum/river_spawner/new_river = new /datum/river_spawner(pick(levels_by_trait(ORE_LEVEL)))
new_river.generate(nodes = 4, ignore_bridges = TRUE, warning = TRUE)
if(world.time >= next_rubble)
next_rubble = world.time + rand(3 DECISECONDS, 2 SECONDS)
var/hits = 0
var/target
for(var/turf/T in get_area_turfs(/area/lavaland/surface/outdoors))
if(istype(T, /turf/simulated/floor/)) // dont waste our time hitting walls
valid_targets += T
while(hits <= 150) //sling a bunch of rocks around the map
if(!valid_targets) // god forbid we run out of spots to sling rocks
break
target = pick(valid_targets)
new /obj/effect/temp_visual/rock_target(target)
hits++
valid_targets -= target
//just play the play from the last hit in the bundle, it reaches across the map anyways
INVOKE_ASYNC(src, PROC_REF(generate_boom), target)
//lets just fake some booms
/datum/weather/volcano/proc/generate_boom(turf/target)
sleep(ROCKFALL_DELAY)
for(var/mob/M in GLOB.player_list)
var/turf/M_turf = get_turf(M)
if(M_turf.z == target.z)
M.playsound_local(target, 'sound/effects/explosionfar.ogg', 50, 1, get_rand_frequency(), distance_multiplier = 0)
shake_camera(M, 2, 4)
/obj/effect/temp_visual/rockfall
icon = 'icons/obj/meteor.dmi'
icon_state = "clownish" // we shouldnt be seeing this
name = "Ejected boulder"
desc = "Get out of the way!"
layer = FLY_LAYER
randomdir = FALSE
duration = ROCKFALL_DELAY
pixel_z = 270
/obj/effect/temp_visual/rockfall/Initialize(mapload)
. = ..()
icon_state = pick("small","large", "sharp", "dust", "small1", "large1")
animate(src, pixel_z = 0, time = duration)
SpinAnimation()
/obj/effect/temp_visual/rock_target
icon = 'icons/mob/actions/actions.dmi'
icon_state = "sniper_zoom"
layer = BELOW_MOB_LAYER
light_range = 2
duration = ROCKFALL_DELAY
/obj/effect/temp_visual/rock_target/ex_act()
return
/obj/effect/temp_visual/rock_target/Initialize(mapload)
. = ..()
SpinAnimation()
INVOKE_ASYNC(src, PROC_REF(fall))
/obj/effect/temp_visual/rock_target/proc/fall()
var/turf/T = get_turf(src)
playsound(T,'sound/magic/fleshtostone.ogg', 100, TRUE)
new /obj/effect/temp_visual/rockfall(T)
sleep(duration)
T = get_turf(src)
var/turf_area = get_area(T)
if(ispath(turf_area, /area/shuttle)) //prevent hitting the shuttle when it moves
log_debug("we hit a shuttle area. breaking rock")
qdel(src)
return
playsound(T, 'sound/effects/break_stone.ogg', 80, TRUE)
playsound(T, get_sfx("explosion"), 80, TRUE)
for(var/mob/living/carbon/human/H in range(10, T))
shake_camera(H, 3, 8)
if(T.contents)
for(var/mob/living/L in T.contents) // dont want to be crushing the hazards
if(ismegafauna(L))
L.visible_message("[L.name] easily withstands the hit of the massive rock!")
return
else
L.visible_message("<span class='danger'>[L.name] is crushed under the massive impact of the boulder!</span>", "<span class='userdanger'>You are crushed as a massive weight suddenly descends upon you!</span>", "<span class='danger'>You hear wet splatters as something is hit with a massive object!</span>")
L.gib()
if(!islava(T) && !istype(T, /turf/simulated/floor/chasm)) // Splash harmlessly into the lava pools
for(var/obj/structure/thing in T.contents) // dont cover the tendrils
if(thing.name == "necropolis tendril")
return
T.ChangeTurf(/turf/simulated/mineral/random/high_chance/volcanic)
/// MARK: Acid Rain
/datum/weather/acid
name = "Acidic rain"
desc = "Emissions of sulfur and carbon into the atmosphere results in the formation of acid particulate in the ashen clouds. Eventually, enough collects that it will fall back down as sulfuric acid rain. NT brand shelter pods capsules are not rated for this level of acid."
telegraph_message = "<span class='boldwarning'><i>The sound of tiny drops begins to splatter against the ground, sizzling against the ash and stone. Seek shelter.</i></span>"
telegraph_duration = 600
telegraph_overlay = "light_ash"
weather_message = "<span class='userdanger'><i>Acidic rain begins to pour down in thick sheets, melting rock and flesh alike. Get inside now!</i></span>"
weather_duration_lower = 600
weather_duration_upper = 1200
weather_overlay = "acid_rain"
end_message = "<span class='boldannounceic'>The pitter of acidic dropples slows to silence. It should be safe to go outside now.</span>"
end_duration = 300
end_overlay = "light_ash"
area_types = list(/area/lavaland/surface/outdoors, /area/lavaland/surface/gulag_rock)
target_trait = ORE_LEVEL
probability = 10
barometer_predictable = TRUE
area_act = TRUE
// how long do you get before it melts a hole?
var/melt_delay = 5 SECONDS
var/datum/looping_sound/active_outside_acid/sound_ao = new(list(), FALSE, TRUE)
var/datum/looping_sound/active_inside_acid/sound_ai = new(list(), FALSE, TRUE)
var/datum/looping_sound/weak_outside_acid/sound_wo = new(list(), FALSE, TRUE)
var/datum/looping_sound/weak_inside_acid/sound_wi = new(list(), FALSE, TRUE)
/datum/weather/acid/update_eligible_areas()
. = ..()
sound_ao.output_atoms = outside_areas
sound_ai.output_atoms = inside_areas
sound_wo.output_atoms = outside_areas
sound_wi.output_atoms = inside_areas
/datum/weather/acid/update_audio()
switch(stage)
if(WEATHER_STARTUP_STAGE)
sound_wo.start()
sound_wi.start()
if(WEATHER_MAIN_STAGE)
sound_wo.stop()
sound_wi.stop()
sound_ao.start()
sound_ai.start()
if(WEATHER_WIND_DOWN_STAGE)
sound_ao.stop()
sound_ai.stop()
sound_wo.start()
sound_wi.start()
if(WEATHER_END_STAGE)
sound_wo.stop()
sound_wi.stop()
/datum/weather/acid/area_act()
if(!length(GLOB.all_shelter_pods)) // don't need to act if there's nothing in the list so we don't runtime
return
for(var/turf/current_turf in GLOB.all_shelter_pods)
if(!is_mining_level(current_turf.z)) // dont want to melt pods on other Z levels
continue
if(istype(get_area(current_turf), /area/survivalpod/luxurypod)) // luxury pods are immune to the storm
continue
if(prob(2))
current_turf.visible_message("<span class = 'danger'>The ceiling begins to drip as acid starts eating holes in the roof!</span>", "<span class = 'danger'>You hear droplets hitting the floor as acid leaks in through the roof.</span>")
addtimer(CALLBACK(src, PROC_REF(melt_pod), current_turf), melt_delay)
/datum/weather/acid/on_shelter_placed(datum/source, turf/center)
. = ..()
if(center.z in impacted_z_levels)
var/area/A = get_area(center)
inside_areas |= A
sound_ai.output_atoms |= A
sound_wi.output_atoms |= A
// lets make some holes!
/datum/weather/acid/proc/melt_pod(turf/melt_this)
var/area/new_area = GLOB.all_unique_areas[/area/lavaland/surface/outdoors] || new /area/lavaland/surface/outdoors
for(var/turf/simulated/nearby_turf in RANGE_TURFS(3, melt_this)) // danger, but probably wont make the whole pod unusable unless you're VERY unlucky
var/area/turf_area = get_area(nearby_turf)
if(prob(70) && turf_area.type == /area/survivalpod)
new_area.contents.Add(nearby_turf)
if(isfloorturf(nearby_turf))
nearby_turf.break_tile()
if(iswallturf(nearby_turf))
nearby_turf.dismantle_wall()
for(var/obj/machinery/sleeper/survival_pod/pod in nearby_turf.contents)
pod.visible_message("<span class = 'danger'>The sleeper melts away into a useless heap of junk!</span>", "<span class = 'danger'>You hear something nearby collapse from the acidic rain!</span>")
pod.Destroy()
impacted_areas.Cut()
generate_area_list()
update_areas()
update_eligible_areas()
/datum/weather/acid/weather_act(atom/L)
while(L && !isturf(L))
if(ismecha(L)) //Mechs are immune
return
if(!ishuman(L) || isgrey(L)) // greys and natural fauna shouldnt be affected by acid rain
return
var/mob/living/carbon/human/H = L
if(!H.wear_suit || !H.head) // No need to check further if they dont have clothing on
H.adjustFireLoss(2)
H.adjustBruteLoss(2)
return
if(!(H.head.resistance_flags & ACID_PROOF) && !(H.wear_suit.resistance_flags & ACID_PROOF))
H.adjustFireLoss(2)
H.adjustBruteLoss(2)
L = L.loc //Matryoshka check
/// MARK: Wind Storm
/datum/weather/wind
name = "High-velocity wind"
desc = "High-pressure barometrics in the area have caused a radical change in air pressure, resulting in high-speed winds in the immediate vicinity."
telegraph_message = "<span class='boldwarning'><i>The wind begins to pick up, whipping against your body with an ominous intensity. Seek shelter.</i></span>"
telegraph_duration = 600
telegraph_overlay = "light_ash"
weather_message = "<span class='userdanger'><i>The wind rises into a furious rage, kicking up dirt and ash in its wake. Get inside now!</i></span>"
weather_duration_lower = 600
weather_duration_upper = 1200
weather_overlay = "wind"
end_message = "<span class='boldannounceic'>The wind calms into its normal rhythms, dust settling back to the ashen surface. It should be safe to go outside now.</span>"
end_duration = 300
end_overlay = "light_ash"
area_types = list(/area/lavaland/surface/outdoors, /area/lavaland/surface/gulag_rock)
target_trait = ORE_LEVEL
probability = 25
barometer_predictable = TRUE
var/wind_dir
var/next_dir_change
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/wind/update_eligible_areas()
. = ..()
sound_ao.output_atoms = outside_areas
sound_ai.output_atoms = inside_areas
sound_wo.output_atoms = outside_areas
sound_wi.output_atoms = inside_areas
/datum/weather/wind/update_audio()
switch(stage)
if(WEATHER_STARTUP_STAGE)
sound_wo.start()
sound_wi.start()
if(WEATHER_MAIN_STAGE)
sound_wo.stop()
sound_wi.stop()
sound_ao.start()
sound_ai.start()
if(WEATHER_WIND_DOWN_STAGE)
sound_ao.stop()
sound_ai.stop()
sound_wo.start()
sound_wi.start()
if(WEATHER_END_STAGE)
sound_wo.stop()
sound_wi.stop()
/datum/weather/wind/on_shelter_placed(datum/source, turf/center)
. = ..()
if(center.z in impacted_z_levels)
var/area/A = get_area(center)
inside_areas |= A
sound_ai.output_atoms |= A
sound_wi.output_atoms |= A
/datum/weather/wind/start() //give it our custom overlay
custom_overlay = 'icons/effects/tile_effects.dmi'
wind_dir = pick(GLOB.alldirs)
overlay_dir = wind_dir
next_dir_change = world.time + rand(10 SECONDS, 30 SECONDS)
. = ..()
/datum/weather/wind/wind_down() // back to normal overlay
custom_overlay = null
overlay_dir = null
. = ..()
/datum/weather/wind/weather_act(mob/living/L)
if(next_dir_change <= world.time)
next_dir_change = world.time + rand(10 SECONDS, 30 SECONDS)
wind_dir = pick(GLOB.alldirs)
overlay_dir = wind_dir
update_areas()
if(ismecha(L)) //Mechs are immune
return
if(ishuman(L)) // lets not push around lavaland mobs
L.air_push(wind_dir, MOVE_FORCE_NORMAL * 2)
#undef ROCKFALL_DELAY
@@ -16,7 +16,7 @@
end_duration = 100
end_message = "<span class='notice'>The air seems to be cooling off again.</span>"
var/pre_maint_all_access
area_type = /area
area_types = list(/area)
protected_areas = list(
/area/station/maintenance,
/area/station/turret_protected/ai_upload,
@@ -14,7 +14,7 @@
end_duration = 10 // wind_down() does not do anything for this event, so we just trigger end() semi-immediately
end_message = null
area_type = /area // read generate_area_list() as well below
area_types = list(/area) // read generate_area_list() as well below
protected_areas = list(/area/shuttle/arrival/station)
target_trait = REACHABLE_SPACE_ONLY
immunity_type = "burn"