Adds the weather anomaly (#18960)

* Weather anomaly

* Rest of the stuff

* Stomach acids to normal acids

* Changes
This commit is contained in:
Guti
2026-01-01 14:39:44 -05:00
committed by GitHub
parent cbc248a39c
commit 3889dc69ab
12 changed files with 376 additions and 11 deletions
@@ -80,7 +80,7 @@
return FALSE
/obj/effect/anomaly/proc/anomalyNeutralize()
new /obj/effect/effect/smoke/bad(loc)
new /obj/effect/effect/smoke(loc)
if(!isnull(anomaly_core))
anomaly_core.forceMove(get_turf(src))
anomaly_core = null
@@ -101,21 +101,23 @@
return TRUE
return ..()
/proc/generate_anomaly(turf/anomalycenter, type = FLUX_ANOMALY, anomalyrange = 5, has_changed_lifespan = TRUE)
/proc/generate_anomaly(turf/anomalycenter, type = FLUX_ANOMALY, anomalyrange = 5, has_changed_lifespan = TRUE, drops_core = TRUE)
var/turf/local_turf = pick(RANGE_TURFS(anomalyrange, anomalycenter))
if(!local_turf)
return
switch(type)
if(FLUX_ANOMALY)
var/explosive = has_changed_lifespan ? FLUX_NO_EMP : FLUX_LIGHT_EMP
new /obj/effect/anomaly/flux(local_turf, has_changed_lifespan ? rand(25 SECONDS, 35 SECONDS) : null, FALSE, explosive)
new /obj/effect/anomaly/flux(local_turf, has_changed_lifespan ? rand(25 SECONDS, 35 SECONDS) : null, drops_core, explosive)
if(GRAVITATIONAL_ANOMALY)
new /obj/effect/anomaly/grav(local_turf, has_changed_lifespan ? rand(20 SECONDS, 30 SECONDS) : null, FALSE)
new /obj/effect/anomaly/grav(local_turf, has_changed_lifespan ? rand(20 SECONDS, 30 SECONDS) : null, drops_core)
if(PYRO_ANOMALY)
new /obj/effect/anomaly/pyro(local_turf, has_changed_lifespan ? rand(15 SECONDS, 25 SECONDS) : null, FALSE)
new /obj/effect/anomaly/pyro(local_turf, has_changed_lifespan ? rand(15 SECONDS, 25 SECONDS) : null, drops_core)
if(HALLUCINATION_ANOMALY)
new /obj/effect/anomaly/hallucination/supermatter(local_turf, has_changed_lifespan ? rand(15 SECONDS, 25 SECONDS) : null, FALSE)
new /obj/effect/anomaly/hallucination/supermatter(local_turf, has_changed_lifespan ? rand(15 SECONDS, 25 SECONDS) : null, drops_core)
if(BIOSCRAMBLER_ANOMALY)
new /obj/effect/anomaly/bioscrambler/docile(local_turf, null, FALSE)
new /obj/effect/anomaly/bioscrambler/docile(local_turf, null, drops_core)
if(DIMENSIONAL_ANOMALY)
new /obj/effect/anomaly/dimensional(local_turf, null, FALSE)
new /obj/effect/anomaly/dimensional(local_turf, null, drops_core)
if(WEATHER_ANOMALY)
new /obj/effect/anomaly/dimensional(local_turf, null, drops_core)
@@ -0,0 +1,121 @@
/obj/effect/anomaly/weather
name = "weather anomaly"
icon_state = "weather"
anomaly_core = /obj/item/assembly/signaler/anomaly/weather
lifespan = ANOMALY_COUNTDOWN_TIMER * 2.5
var/telegraph_percent = 7
var/list/area/affected_areas = list()
var/list/turf/affected_turfs = list()
var/datum/anomalous_weather/selected_weather
var/is_raining = FALSE
/obj/effect/anomaly/weather/Initialize(mapload, new_lifespan, drops_core)
. = ..()
affected_areas.Add(impact_area)
if(!selected_weather)
pick_weather()
var/telegraph = lifespan / telegraph_percent
for(var/spread_dir in GLOB.alldirs)
var/area/nearby = find_adjacent_impacted_area(spread_dir)
if(isnull(nearby) || nearby.flag_check(AREA_FORBID_EVENTS))
continue
if(istype(nearby, /area/space))
continue
affected_areas |= nearby
for(var/area/area in affected_areas)
for(var/mob/mob in area)
to_chat(mob, span_notice(selected_weather.telegraph_message))
for(var/turf/turf in area)
affected_turfs.Add(turf)
apply_wibbly_filters(src)
addtimer(CALLBACK(src, PROC_REF(start_weather)), telegraph, TIMER_DELETE_ME)
/obj/effect/anomaly/weather/proc/find_adjacent_impacted_area(check_dir)
var/limit = 10
var/turf/next_turf = get_step(src, check_dir)
while(next_turf.loc == impact_area && limit > 0)
next_turf = get_step(next_turf, check_dir)
if(isnull(next_turf))
return null
limit -= 1
return next_turf.loc
/obj/effect/anomaly/weather/anomalyNeutralize()
clear_weather()
return ..()
/obj/effect/anomaly/weather/detonate()
new /obj/effect/effect/smoke/bad/burntfood(loc) // OOoooOooh spooky cloud... Doesn't do ANYTHING
qdel(src)
/obj/effect/anomaly/weather/anomalyEffect(seconds_per_tick)
..()
if(!is_raining)
return
for(var/turf/turf in affected_turfs)
selected_weather.affect_turf(turf)
for(var/mob/mob as anything in GLOB.player_list)
if(get_area(mob) in affected_areas)
selected_weather.hear_sounds(mob, TRUE)
else
selected_weather.hear_sounds(mob, FALSE)
/obj/effect/anomaly/weather/proc/pick_weather(new_weather_path)
if(!new_weather_path)
new_weather_path = pick(subtypesof(/datum/anomalous_weather))
selected_weather = new new_weather_path
/obj/effect/anomaly/weather/proc/start_weather()
if(QDELETED(src))
return
is_raining = TRUE
if(selected_weather.loop_sounds)
selected_weather.loop_sounds.start()
for(var/turf/area_turf in affected_turfs)
apply_to_turf(area_turf)
/obj/effect/anomaly/weather/proc/clear_weather()
if(!is_raining)
return
if(selected_weather.sounds)
selected_weather.loop_sounds.stop()
for(var/area in affected_areas)
for(var/turf/area_turf in area)
remove_from_turf(area_turf)
for(var/mob/mob in area)
selected_weather.hear_sounds(mob, FALSE)
/obj/effect/anomaly/weather/proc/apply_to_turf(turf/T)
if(selected_weather.visuals in T.vis_contents)
WARNING("Was asked to add weather to [T.x], [T.y], [T.z] despite already having us in it's vis contents")
return
T.vis_contents += selected_weather.visuals
/obj/effect/anomaly/weather/proc/remove_from_turf(turf/T)
if(!(selected_weather.visuals in T.vis_contents))
WARNING("Was asked to remove weather from [T.x], [T.y], [T.z] despite it not having us in it's vis contents")
return
T.vis_contents -= selected_weather.visuals
/obj/effect/anomaly/weather/Destroy()
clear_weather()
. = ..()
@@ -0,0 +1,188 @@
/datum/anomalous_weather
var/name = "Unnamed Weather"
var/icon = 'icons/effects/weather.dmi'
var/icon_state = null
var/reagent_id
var/weather_colour
var/datum/reagents/reagent_holder
var/atom/movable/weather_visuals/visuals = null
var/telegraph_message = "The storm is coming..."
var/patter_message = "Something patters softly onto your umbrella. You're not quite sure of what it is, actually."
var/drench_message = "You're getting... Wet?"
var/sounds = null
var/datum/looping_sound/loop_sounds = null
/datum/anomalous_weather/New()
..()
visuals = new()
visuals.icon = icon
visuals.icon_state = icon_state
loop_sounds = new sounds(list(), FALSE, TRUE)
if(reagent_id)
reagent_holder = new(10000, null)
reagent_holder.add_reagent(reagent_id, 10000)
weather_colour = reagent_holder.get_color()
if(weather_colour)
visuals.color = weather_colour
/datum/anomalous_weather/proc/affect_turf(turf/to_affect)
if(iswall(to_affect))
return
for(var/atom/thing in to_affect)
if(isliving(thing))
affect_mob(thing)
continue
if(!reagent_id) // No reagent was given, so don't do anything past this.
continue
reagent_holder.touch_obj(thing, 2)
if(!istype(thing, /obj/item/reagent_containers))
continue
var/obj/item/reagent_containers/container = thing
if(!container.is_open_container() || container.reagents.total_volume >= container.reagents.maximum_volume)
continue
container.reagents.add_reagent(reagent_id, 2)
if(reagent_id == REAGENT_ID_WATER)
to_affect.wash(CLEAN_ALL)
do_special(to_affect)
return
/datum/anomalous_weather/proc/affect_mob(mob/living/affected_mob)
var/obj/item/melee/umbrella/U = affected_mob.get_active_hand()
if(!istype(U) || !U.open)
U = affected_mob.get_inactive_hand()
if(istype(U) && U.open)
if(prob(5))
to_chat(affected_mob, span_notice(patter_message))
return
if(prob(5))
to_chat(affected_mob, span_danger(drench_message))
if(!reagent_id) // No reagent was given, no need to continue.
return
reagent_holder.splash_mob(affected_mob, 2)
if(reagent_id == REAGENT_ID_WATER)
affected_mob.wash(CLEAN_ALL)
affected_mob.water_act(2)
/datum/anomalous_weather/proc/do_special(var/turf/simulated/T)
return
/datum/anomalous_weather/proc/hear_sounds(mob/M, adding)
if(!sounds)
return
if(adding)
loop_sounds.output_atoms |= M
return
loop_sounds.output_atoms -= M
/datum/anomalous_weather/rain
name = "Rain"
icon_state = "anom_rain"
reagent_id = REAGENT_ID_WATER
sounds = /datum/looping_sound/weather/rain
telegraph_message = "Clouds begin to cover the ceiling of the area..."
patter_message = "Rain patters softly onto your umbrella."
drench_message = "Rain falls on you, drenching you in water."
/datum/anomalous_weather/rain/do_special(turf/simulated/T)
if(prob(2))
T.wet_floor(1)
/datum/anomalous_weather/rain/blood
name = "Blood Rain" // From a lacerated sky
reagent_id = REAGENT_ID_BLOOD
telegraph_message = "Red clouds begin to cover the ceiling of the area..."
patter_message = "Blood splatters and falls past your umbrella." // Bleeding it's horrors
drench_message = "Blood splatters fall on you, covering you in it."
/datum/anomalous_weather/rain/blood/do_special(turf/simulated/T)
if(prob(0.5))
blood_splatter(T, null, TRUE)
/datum/anomalous_weather/rain/storm
name = "Storm"
icon_state = "anom_rain_fast"
loop_sounds = /datum/looping_sound/weather/outside_blizzard
telegraph_message = "Grey clouds begin to cover the ceiling of the area..."
patter_message = "Rain patters continuously onto your umbrella."
drench_message = "Rain falls on you, completely soaking you."
/datum/anomalous_weather/rain/storm/do_special(turf/simulated/T)
if(prob(3))
T.wet_floor(1)
if(prob(0.025))
lightning_strike(T)
/datum/anomalous_weather/rain/acid
name = "Acid Rain"
reagent_id = REAGENT_ID_SACID
telegraph_message = "Strange clouds begin to cover the ceiling, an acidid tinge on them..."
/datum/anomalous_weather/hail
name = "Hail"
icon_state = "snowfall_heavy_old"
reagent_id = REAGENT_ID_ICE
sounds = /datum/looping_sound/weather/outside_blizzard
telegraph_message = "Grey clouds begin to cover the ceiling of the area..."
patter_message = "Hail patters on your umbrella."
drench_message = "Hail pelts you"
/datum/anomalous_weather/hail/affect_mob(mob/living/affected_mob)
..()
var/target_zone = pick(BP_ALL)
var/amount_blocked = affected_mob.run_armor_check(target_zone, "melee")
var/damage = rand(1,3)
if(amount_blocked >= 30)
return
affected_mob.apply_damage(damage, BRUTE, target_zone, amount_blocked, used_weapon = "hail")
/datum/anomalous_weather/ash_storm
name = "Ash Storm"
icon_state = "ashfall_moderate-alt"
sounds = /datum/looping_sound/weather/outside_blizzard
telegraph_message = "Ash clouds begin to cover the ceiling of the area..."
/datum/anomalous_weather/ash_storm/affect_mob(mob/living/affected_mob)
affected_mob.inflict_heat_damage(rand(1, 3))
/datum/anomalous_weather/ash_storm/do_special(turf/simulated/T)
if(prob(5) && T.can_dirty)
T.dirt += 30
/* Activate this one for a lot of rain
/datum/anomalous_weather/rain/storm/cats_n_dogs
name = "Cats and dogs rain"
telegraph_message = "Strange, fuzzy clouds beging to cover the ceiling of the area..."
/datum/anomalous_weather/rain/storm/cats_n_dogs/do_special(turf/simulated/T)
..()
if(prob(0.01))
var/mob/living/cat_or_dog = pick(/mob/living/simple_mob/animal/passive/cat, /mob/living/simple_mob/animal/passive/dog)
new cat_or_dog(T.loc)
T.visible_message(span_danger("A [cat_or_dog.name] falls from within the strange clouds!"))
*/