From 67360a9bea38e9367234e8d40396dc58dc2c057e Mon Sep 17 00:00:00 2001 From: Geeves Date: Tue, 24 Dec 2024 18:04:51 +0200 Subject: [PATCH] Weather Warnings (#19934) * Atmospheric probes will now relay changes in weather when deployed. Analog radios can be tuned into the weather broadcast and receive it, provided they're in the same sector / connected z-levels. * Fixed weather transitions to rainy / icy weather not working. * Changed rainy / icy weather to have a blue color, reducing eye strain. ![image](https://github.com/user-attachments/assets/b8439595-25ff-4df0-8f5d-b2d27d147b70) ![image-1](https://github.com/user-attachments/assets/cf0018c2-c6c7-4cf6-8069-543ad98cd597) ![image](https://github.com/user-attachments/assets/5e4d87e2-33c8-494a-9b8f-8a62f12c496a) --- aurorastation.dme | 1 + code/__DEFINES/dcs/signals/signals_weather.dm | 12 ++++ code/controllers/subsystems/weather.dm | 6 +- code/datums/state_machine.dm | 11 ++-- code/game/objects/items/lore_radio.dm | 57 ++++++++++++------- code/game/objects/objs.dm | 11 ++++ code/game/objects/structures/survey_probe.dm | 54 +++++++++++++++++- .../abstract/abstract_weather_marker.dm | 15 ++++- code/modules/mapping/planet_types/asteroid.dm | 1 + code/modules/mapping/planet_types/grass.dm | 1 + code/modules/mapping/planet_types/jungle.dm | 1 + .../mapping/planet_types/lore/konyang.dm | 1 + .../mapping/planet_types/lore/srandmarr.dm | 1 + .../mapping/planet_types/lore/uueoaesa.dm | 2 + code/modules/mapping/planet_types/snow.dm | 1 + code/modules/overmap/exoplanets/exoplanet.dm | 12 +++- code/modules/weather/_weather.dm | 48 ++++++++++++---- code/modules/weather/weather_fsm.dm | 13 +++++ code/modules/weather/weather_fsm_states.dm | 18 ++++-- html/changelogs/geeves-weather_warning.yml | 8 +++ 20 files changed, 225 insertions(+), 49 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/signals_weather.dm create mode 100644 html/changelogs/geeves-weather_warning.yml diff --git a/aurorastation.dme b/aurorastation.dme index 4128972d235..edd440f49f9 100644 --- a/aurorastation.dme +++ b/aurorastation.dme @@ -170,6 +170,7 @@ #include "code\__DEFINES\dcs\signals\signals_spatial_grid.dm" #include "code\__DEFINES\dcs\signals\signals_subsystem.dm" #include "code\__DEFINES\dcs\signals\signals_turf.dm" +#include "code\__DEFINES\dcs\signals\signals_weather.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_attack.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_main.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_movable.dm" diff --git a/code/__DEFINES/dcs/signals/signals_weather.dm b/code/__DEFINES/dcs/signals/signals_weather.dm new file mode 100644 index 00000000000..f3466599681 --- /dev/null +++ b/code/__DEFINES/dcs/signals/signals_weather.dm @@ -0,0 +1,12 @@ +// Signals related to weather and weather transitions +// Sent primarily from weather_fsm.dm + +// global (weather) signals +// These are signals which can be listened to by any component on any parent +// start global signals with "!", this used to be necessary but now it's just a formatting choice + +/// Called by weather_fsm.dm whenever a weather transition begins +#define COMSIG_GLOB_Z_WEATHER_CHANGE "!z_weather_change" + +/// Called by survey_probe.dm whenever a survey probe broadcasts a weather change +#define COMSIG_GLOB_Z_WEATHER_BROADCAST "!z_weather_broadcast" diff --git a/code/controllers/subsystems/weather.dm b/code/controllers/subsystems/weather.dm index 4196f51905c..3766b890155 100644 --- a/code/controllers/subsystems/weather.dm +++ b/code/controllers/subsystems/weather.dm @@ -38,8 +38,10 @@ SUBSYSTEM_DEF(weather) if(WS) unregister_weather_system(WS) qdel(WS) - //Create the new weather system and let it register itself - new /obj/abstract/weather_system(locate(1, 1, text2num(topmost_level)), topmost_level, initial_state) + + // Create the new weather system and let it register itself + var/obj/abstract/weather_system/new_weather_system = new /obj/abstract/weather_system(locate(1, 1, text2num(topmost_level)), topmost_level, initial_state) + return new_weather_system ///Registers a given weather system obj for getting updates by SSweather. /datum/controller/subsystem/weather/proc/register_weather_system(var/obj/abstract/weather_system/WS) diff --git a/code/datums/state_machine.dm b/code/datums/state_machine.dm index af14c3266c1..c2ed0fc3269 100644 --- a/code/datums/state_machine.dm +++ b/code/datums/state_machine.dm @@ -79,16 +79,19 @@ var/global/list/state_machines = list() var/list/options = current_state.get_open_transitions(holder_instance) if(LAZYLEN(options)) var/singleton/state_transition/choice = choose_transition(options) - current_state.exited_state(holder_instance) - current_state = choice.target - current_state.entered_state(holder_instance) - return current_state + handle_next_transition(holder_instance, choice) // Decides which transition to walk into, to the next state. // By default it chooses the first one on the list. /datum/state_machine/proc/choose_transition(list/valid_transitions) return valid_transitions[1] +/// Handles changing the state, based on the state_transition chosen in `evaluate()`. +/datum/state_machine/proc/handle_next_transition(var/datum/holder_instance, var/singleton/state_transition/chosen_transition) + current_state.exited_state(holder_instance) + current_state = chosen_transition.target + current_state.entered_state(holder_instance) + // Forces the FSM to switch to a specific state, no matter what. // Use responsibly. /datum/state_machine/proc/set_state(new_state_type) diff --git a/code/game/objects/items/lore_radio.dm b/code/game/objects/items/lore_radio.dm index 70d77a39615..48e2195deb5 100644 --- a/code/game/objects/items/lore_radio.dm +++ b/code/game/objects/items/lore_radio.dm @@ -1,3 +1,5 @@ +#define WEATHER_RADIO_CHANNEL "Shortband Weather Broadcast" + /obj/item/lore_radio name = "analog radio" desc = "A portable radio capable of receiving radio waves from nearby space systems." @@ -11,8 +13,9 @@ /obj/item/lore_radio/Initialize() . = ..() - if(!current_station && SSatlas.current_sector?.lore_radio_stations) - current_station = pick(SSatlas.current_sector.lore_radio_stations) + if(!current_station) + var/list/possible_stations = get_possible_stations() + current_station = pick(possible_stations) if(starts_on) toggle_receiving() RegisterSignal(SSdcs, COMSIG_GLOB_LORE_RADIO_BROADCAST, PROC_REF(relay_lore_radio)) @@ -24,27 +27,33 @@ to_chat(user, SPAN_NOTICE("\The [src] is listening to \the [current_station] radio station.")) /obj/item/lore_radio/attack_self(var/mob/user) - if(SSatlas.current_sector?.lore_radio_stations) - var/picked_station = tgui_input_list(user, "Select the radio frequency:", "Radio Station Selection", SSatlas.current_sector.lore_radio_stations, current_station) - if(picked_station) - current_station = picked_station - if(!receiving) - toggle_receiving(user) - else - audible_message("[src] only emits white noise...") + var/list/possible_stations = get_possible_stations() + var/picked_station = tgui_input_list(user, "Select the radio frequency:", "Radio Station Selection", possible_stations, current_station) + if(picked_station) + current_station = picked_station + if(!receiving) + toggle_receiving(user) /obj/item/lore_radio/AltClick(var/mob/user) toggle_receiving(user) +/obj/item/lore_radio/proc/get_possible_stations() + var/list/possible_stations = list(WEATHER_RADIO_CHANNEL) + if(SSatlas.current_sector?.lore_radio_stations) + possible_stations += SSatlas.current_sector.lore_radio_stations + return possible_stations + /obj/item/lore_radio/proc/toggle_receiving(var/mob/user) if(!receiving) receiving = TRUE if(user) user.visible_message("[user] flicks \the [src] on.", SPAN_NOTICE("You flick \the [src] on."), range = 3) + RegisterSignal(SSdcs, COMSIG_GLOB_Z_WEATHER_BROADCAST, PROC_REF(relay_weather_broadcast)) else receiving = FALSE if(user) user.visible_message("[user] flicks \the [src] off.", SPAN_NOTICE("You flick \the [src] off."), range = 3) + UnregisterSignal(SSdcs, COMSIG_GLOB_Z_WEATHER_BROADCAST, PROC_REF(relay_weather_broadcast)) /obj/item/lore_radio/proc/relay_lore_radio(var/datum/source, var/radio_station, var/radio_message) SIGNAL_HANDLER @@ -52,13 +61,23 @@ if(!receiving || radio_station != current_station) return - var/displayed_message = radio_message ? "\The [src.name] transmits, \"[radio_message]\"" : "\The [src] only emits white noise..." - audible_message(displayed_message) if(radio_message) - var/list/hearers = get_hearers_in_view(7, src) - var/list/clients_in_hearers = list() - for(var/mob/mob in hearers) - if(mob.client) - clients_in_hearers += mob.client - if(length(clients_in_hearers)) - INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, animate_chat), radio_message, null, FALSE, clients_in_hearers, 2 SECONDS) + output_spoken_message(radio_message) + else + audible_message("The [SPAN_BOLD("[name]")] only emits white noise...") // using name instead of src so it doesn't add a bolded The or whatever, better control of what displays + +/// Listens to when a weather change on this Z-level is broadcasted from a configured weather reader (survey probe), and reads it aloud +/obj/item/lore_radio/proc/relay_weather_broadcast(var/datum/source, var/z_level, var/singleton/state_transition/weather/weather_transition, var/time_to_transition, var/broadcast_message) + SIGNAL_HANDLER + + if(!receiving || current_station != WEATHER_RADIO_CHANNEL) + return + + var/turf/current_turf = get_turf(src) + var/list/connected_z_levels = GetConnectedZlevels(current_turf.z) + if(!(z_level in connected_z_levels)) + return + + output_spoken_message(broadcast_message) + +#undef WEATHER_RADIO_CHANNEL diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index c4d5c0d7142..b40e1a8dcad 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -309,3 +309,14 @@ /obj/proc/clean() clean_blood() color = initial(color) + +/obj/proc/output_spoken_message(var/message, var/message_verb = "transmits", var/display_overhead = TRUE, var/overhead_time = 2 SECONDS) + audible_message("\The [src.name] [message_verb], \"[message]\"") + if(display_overhead) + var/list/hearers = get_hearers_in_view(7, src) + var/list/clients_in_hearers = list() + for(var/mob/mob in hearers) + if(mob.client) + clients_in_hearers += mob.client + if(length(clients_in_hearers)) + INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, animate_chat), message, null, FALSE, clients_in_hearers, overhead_time) diff --git a/code/game/objects/structures/survey_probe.dm b/code/game/objects/structures/survey_probe.dm index a3ff40cc388..455fcc9dea6 100644 --- a/code/game/objects/structures/survey_probe.dm +++ b/code/game/objects/structures/survey_probe.dm @@ -1,3 +1,7 @@ +#define SURVEY_TYPE_ATMOSPHERIC "atmospheric" +#define SURVEY_TYPE_GROUND "ground" +#define SURVEY_TYPE_GEOMAGNETIC "geomagnetic" + /obj/structure/survey_probe name = "atmosphere probe" desc = "\ @@ -25,11 +29,13 @@ var/start_deployed = FALSE ///Extra information for variant types - manufacturer, faction, etc. var/desc_extra = "This probe was manufactured by Orion Express, but it is based on on older model designed by Hephaestus Industries." - var/survey_type = "atmospheric" + var/survey_type = SURVEY_TYPE_ATMOSPHERIC /obj/structure/survey_probe/Initialize(mapload) . = ..() desc_extended += desc_extra + if(survey_type == SURVEY_TYPE_ATMOSPHERIC) + desc += " When deployed, this probe will read and relay weather data to compatible devices." if(start_deployed) deploy() @@ -69,11 +75,49 @@ anchored = TRUE density = TRUE icon_state = "[initial(icon_state)]_deployed" + if(survey_type == SURVEY_TYPE_ATMOSPHERIC) + RegisterSignal(SSdcs, COMSIG_GLOB_Z_WEATHER_CHANGE, PROC_REF(relay_weather_change)) + addtimer(CALLBACK(src, PROC_REF(read_initial_weather)), 2 SECONDS) + output_spoken_message("Initializing weather detection subsystem...") + +/// Reads the current weather status aloud when deployed on a planet with weather +/obj/structure/survey_probe/proc/read_initial_weather() + var/turf/current_turf = get_turf(src) + + var/obj/abstract/weather_system/weather = current_turf.weather || SSweather.weather_by_z["[current_turf.z]"] + if(!weather) + output_spoken_message("No weather conditions detected.") + return + + var/singleton/state/weather/current_weather_state = weather.weather_system.current_state + if(current_weather_state) + output_spoken_message("Reading current weather conditions as \"[current_weather_state.name]\".") /obj/structure/survey_probe/proc/undeploy() anchored = FALSE density = FALSE icon_state = initial(icon_state) + if(survey_type == SURVEY_TYPE_ATMOSPHERIC) + UnregisterSignal(SSdcs, COMSIG_GLOB_Z_WEATHER_CHANGE) + +/// When a weather transition (see weather_fsm.dm) starts on this z_level, this will speak it aloud, and then broadcast it to any other devices listening to the broadcast global signal +/obj/structure/survey_probe/proc/relay_weather_change(var/datum/source, var/z_level, var/singleton/state_transition/weather/weather_transition, var/time_to_transition) + SIGNAL_HANDLER + + var/turf/current_turf = get_turf(src) + var/list/connected_z_levels = GetConnectedZlevels(current_turf.z) + if(!(z_level in connected_z_levels)) + return + + var/singleton/state/weather/expected_weather_state = weather_transition.target + var/broadcast_message = "Expecting shift to new weather condition, \"[expected_weather_state.name]\", in approximately [DisplayTimeText(time_to_transition)]." + output_spoken_message(broadcast_message) + + // received the message, now broadcast it to receivers + // also send over other data, so unique receivers can have their own handling + // think of it as the probe sending not just a radio message, but a broad band of data + // yes, this does mean repeated messages if multiple atmospheric probes are set up + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_Z_WEATHER_BROADCAST, z_level, weather_transition, time_to_transition, broadcast_message) /obj/structure/survey_probe/proc/survey_end() if(timer_id) @@ -184,7 +228,7 @@ The probe has to be deployed first before it is used. Wrench it to deploy, then click with empty hand to activate." icon_state = "ground_probe" - survey_type = "ground" + survey_type = SURVEY_TYPE_GROUND /obj/structure/survey_probe/ground/get_report(T, is_exoplanet, is_asteroid) // turf @@ -228,7 +272,7 @@ The probe has to be deployed first before it is used. Wrench it to deploy, then click with empty hand to activate." icon_state = "magnet_probe" - survey_type = "geomagnetic" + survey_type = SURVEY_TYPE_GEOMAGNETIC /obj/structure/survey_probe/magnet/get_report(T, is_exoplanet, is_asteroid) . = "Geomagnetic survey results:" @@ -248,3 +292,7 @@ . += "
No data available from geomagnetic analysis" else . += "
No data available from geomagnetic analysis" + +#undef SURVEY_TYPE_ATMOSPHERIC +#undef SURVEY_TYPE_GROUND +#undef SURVEY_TYPE_GEOMAGNETIC diff --git a/code/modules/abstract/abstract_weather_marker.dm b/code/modules/abstract/abstract_weather_marker.dm index 5a3d9bd2c1e..51999af4221 100644 --- a/code/modules/abstract/abstract_weather_marker.dm +++ b/code/modules/abstract/abstract_weather_marker.dm @@ -1,10 +1,17 @@ /obj/abstract/weather_marker name = "Weather Marker" + icon = 'icons/effects/map_effects.dmi' + icon_state = "weather_marker" + /// The weather type we want. This needs to be a weather singleton type, such as /singleton/state/weather/rain/storm. /// These should be used for forcing weather in an away site or an event map. var/weather_type - icon = 'icons/effects/map_effects.dmi' - icon_state = "weather_marker" + + /// Whether this weather system supports having watery weather + var/has_water_weather = FALSE + + /// Whether this weather system supports having icy weather + var/has_icy_weather = FALSE /obj/abstract/weather_marker/Initialize() ..() @@ -15,4 +22,6 @@ if(!ispath(weather_type)) log_debug("Invalid weather type mapped in at [x] [y] [z]!") return INITIALIZE_HINT_QDEL - SSweather.setup_weather_system(z, weather_type) + var/obj/abstract/weather_system/new_weather_system = SSweather.setup_weather_system(z, weather_type) + new_weather_system.has_water_weather = has_water_weather + new_weather_system.has_icy_weather = has_icy_weather diff --git a/code/modules/mapping/planet_types/asteroid.dm b/code/modules/mapping/planet_types/asteroid.dm index 3fde8bfb0e5..28be593f40d 100644 --- a/code/modules/mapping/planet_types/asteroid.dm +++ b/code/modules/mapping/planet_types/asteroid.dm @@ -42,6 +42,7 @@ surface_color = COLOR_BLUE_GRAY scanimage = "asteroid.png" possible_themes = list(/datum/exoplanet_theme/barren/asteroid/ice) + has_icy_weather = TRUE rock_colors = list(COLOR_ASH) planetary_area = /area/exoplanet/barren/asteroid ruin_planet_type = PLANET_ASTEROID diff --git a/code/modules/mapping/planet_types/grass.dm b/code/modules/mapping/planet_types/grass.dm index 6cb8eb559c7..3739c44e50a 100644 --- a/code/modules/mapping/planet_types/grass.dm +++ b/code/modules/mapping/planet_types/grass.dm @@ -12,6 +12,7 @@ rock_colors = list(COLOR_ASTEROID_ROCK, COLOR_GRAY80, COLOR_BROWN) plant_colors = list("#3c772e","#27614b","#3f8d35","#185f18","#799628", "RANDOM") possible_themes = list(/datum/exoplanet_theme/grass) + has_water_weather = TRUE ruin_planet_type = PLANET_GRASS ruin_allowed_tags = RUIN_LOWPOP|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL soil_data = list("Low density organic matter layer", "Rich microbiome layer", "Moderate water layer", "Large rock particle layer", "Iron oxide layer") diff --git a/code/modules/mapping/planet_types/jungle.dm b/code/modules/mapping/planet_types/jungle.dm index b50e69d86a6..15917bf5b25 100644 --- a/code/modules/mapping/planet_types/jungle.dm +++ b/code/modules/mapping/planet_types/jungle.dm @@ -11,6 +11,7 @@ has_trees = TRUE possible_themes = list(/datum/exoplanet_theme/jungle) initial_weather_state = /singleton/state/weather/rain/storm/jungle_planet + has_water_weather = TRUE ruin_planet_type = PLANET_GROVE ruin_allowed_tags = RUIN_LOWPOP|RUIN_SCIENCE|RUIN_HOSTILE|RUIN_WRECK|RUIN_NATURAL diff --git a/code/modules/mapping/planet_types/lore/konyang.dm b/code/modules/mapping/planet_types/lore/konyang.dm index 439f88b1df6..2e2487d3b80 100644 --- a/code/modules/mapping/planet_types/lore/konyang.dm +++ b/code/modules/mapping/planet_types/lore/konyang.dm @@ -8,6 +8,7 @@ color = "#68e968" planetary_area = /area/exoplanet/grass/konyang initial_weather_state = /singleton/state/weather/rain/storm/jungle_planet + has_water_weather = TRUE scanimage = "konyang.png" massvolume = "0.89/0.99" surfacegravity = "0.93" diff --git a/code/modules/mapping/planet_types/lore/srandmarr.dm b/code/modules/mapping/planet_types/lore/srandmarr.dm index 9aa37ca1683..712154753fe 100644 --- a/code/modules/mapping/planet_types/lore/srandmarr.dm +++ b/code/modules/mapping/planet_types/lore/srandmarr.dm @@ -135,6 +135,7 @@ color = "#b5dfeb" planetary_area = /area/exoplanet/adhomai initial_weather_state = /singleton/state/weather/calm/snow_planet + has_icy_weather = TRUE scanimage = "adhomai.png" massvolume = "0.86/0.98" surfacegravity = "0.80" diff --git a/code/modules/mapping/planet_types/lore/uueoaesa.dm b/code/modules/mapping/planet_types/lore/uueoaesa.dm index e7329925740..3886cbf4e8c 100644 --- a/code/modules/mapping/planet_types/lore/uueoaesa.dm +++ b/code/modules/mapping/planet_types/lore/uueoaesa.dm @@ -136,6 +136,7 @@ flora_diversity = 0 has_trees = FALSE initial_weather_state = /singleton/state/weather/calm/jungle_planet + has_water_weather = TRUE small_flora_types = list(/datum/seed/xuizi, /datum/seed/gukhe, /datum/seed/sarezhi, /datum/seed/flower/serkiflower, /datum/seed/sthberry) surface_color = "#e8faff" generated_name = FALSE @@ -280,6 +281,7 @@ generated_name = FALSE ruin_planet_type = PLANET_LORE initial_weather_state = /singleton/state/weather/calm/jungle_planet + has_water_weather = TRUE ruin_type_whitelist = list( /datum/map_template/ruin/exoplanet/ouerea_heph_mining, /datum/map_template/ruin/exoplanet/ouerea_village, diff --git a/code/modules/mapping/planet_types/snow.dm b/code/modules/mapping/planet_types/snow.dm index 92d3550ae3a..4d50f520a2c 100644 --- a/code/modules/mapping/planet_types/snow.dm +++ b/code/modules/mapping/planet_types/snow.dm @@ -7,6 +7,7 @@ weather = "Global full-atmosphere hydrological weather system. Barely-habitable ambient low temperatures. Frequently dangerous, unpredictable meteorological upsets" surfacewater = "Majority frozen, 70% surface water" initial_weather_state = /singleton/state/weather/calm/snow_planet + has_icy_weather = TRUE planetary_area = /area/exoplanet/snow flora_diversity = 4 has_trees = TRUE diff --git a/code/modules/overmap/exoplanets/exoplanet.dm b/code/modules/overmap/exoplanets/exoplanet.dm index d4053991d6a..f6f4c0d7eb1 100644 --- a/code/modules/overmap/exoplanets/exoplanet.dm +++ b/code/modules/overmap/exoplanets/exoplanet.dm @@ -61,9 +61,15 @@ var/list/possible_themes = list(/datum/exoplanet_theme) var/datum/exoplanet_theme/theme - ///What weather state to use for this planet initially. If null, will not initialize any weather system. Must be a typepath rather than an instance. + /// What weather state to use for this planet initially. If null, will not initialize any weather system. Must be a typepath rather than an instance. var/singleton/state/weather/initial_weather_state = /singleton/state/weather/calm + /// Whether the weather system supports having watery weather + var/has_water_weather = FALSE + + /// Whether the weather system supports having icy weather + var/has_icy_weather = FALSE + var/features_budget = 4 var/list/possible_features = list() var/list/spawned_features @@ -553,7 +559,9 @@ /obj/effect/overmap/visitable/sector/exoplanet/proc/set_weather(var/singleton/state/weather/W) initial_weather_state = W //Tells all our levels exposed to the sky to force change the weather. - SSweather.setup_weather_system(map_z[length(map_z)], initial_weather_state) + var/obj/abstract/weather_system/new_weather_system = SSweather.setup_weather_system(map_z[length(map_z)], initial_weather_state) + new_weather_system.has_water_weather = has_water_weather + new_weather_system.has_icy_weather = has_icy_weather ///Setup the initial weather state for the planet. Doesn't apply it to our z levels however. /obj/effect/overmap/visitable/sector/exoplanet/proc/generate_weather() diff --git a/code/modules/weather/_weather.dm b/code/modules/weather/_weather.dm index 29513f89cbe..60ef4a5c50d 100644 --- a/code/modules/weather/_weather.dm +++ b/code/modules/weather/_weather.dm @@ -30,21 +30,44 @@ invisibility = 0 appearance_flags = (RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM) - var/water_material = null // Material to use for the properties of rain. - var/ice_material = null // Material to use for the properties of snow and hail. - var/list/affecting_zs // What z-levels are we affecting? - var/datum/state_machine/weather/weather_system // What is our internal state and how do we decide what state to use? - var/next_weather_transition = 0 // What world.time will we next evaluate our state? + // Temporarily removing these, we do not have the same material system as Nebula - var/obj/abstract/lightning_overlay/lightning_overlay // A visible atom used for animated lighting effects. - var/tmp/list/vis_contents_additions // Holder for a list used to add required atoms to turf vis_contents. + // /// Material to use for the properties of rain. + // var/water_material = null + + // /// Material to use for the properties of snow and hail. + // var/ice_material = null + + /// Whether this weather system supports having watery weather + var/has_water_weather = FALSE + + /// Whether this weather system supports having icy weather + var/has_icy_weather = FALSE + + /// What z-levels are we affecting? + var/list/affecting_zs + + /// What is our internal state and how do we decide what state to use? + var/datum/state_machine/weather/weather_system + + /// What world.time will we next evaluate our state? + var/next_weather_transition = 0 + + /// We've evaluated a new weather pattern and we're in the process of transitioning to it + var/transitioning_weather = FALSE + + /// A visible atom used for animated lighting effects. + var/obj/abstract/lightning_overlay/lightning_overlay + + /// Holder for a list used to add required atoms to turf vis_contents. + var/tmp/list/vis_contents_additions // Main heartbeat proc, called by SSweather. /obj/abstract/weather_system/proc/tick() // Check if we should move to a new state. - if(world.time >= next_weather_transition) + if(world.time >= next_weather_transition && !transitioning_weather) weather_system.evaluate() // Change wind direction and speed. @@ -82,10 +105,15 @@ // - TODO: track and check exoplanet temperature. // - TODO: compare to a list of 'acceptable' states if(istype(next_state)) + // Temporarily removing these, we do not have the same material system as Nebula + // if(next_state.is_liquid) + // return !!water_material + // if(next_state.is_ice) + // return !!ice_material if(next_state.is_liquid) - return !!water_material + return has_water_weather if(next_state.is_ice) - return !!ice_material + return has_icy_weather return TRUE return FALSE diff --git a/code/modules/weather/weather_fsm.dm b/code/modules/weather/weather_fsm.dm index 3f8d3e47117..36a73c8d7aa 100644 --- a/code/modules/weather/weather_fsm.dm +++ b/code/modules/weather/weather_fsm.dm @@ -8,3 +8,16 @@ if(length(transitions)) return pick(transitions) //pickweight(transitions) return ..() + +/datum/state_machine/weather/handle_next_transition(var/obj/abstract/weather_system/holder_instance, var/singleton/state_transition/chosen_transition) + holder_instance.transitioning_weather = TRUE + var/time_to_transition = (rand(1, 3) MINUTES) + (rand(-30, 30) SECONDS) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_Z_WEATHER_CHANGE, holder_instance.z, chosen_transition, time_to_transition) + addtimer(CALLBACK(src, PROC_REF(finalize_weather_transition), holder_instance, chosen_transition), time_to_transition) + +/// Exits the old weather state, enters the new one, and finishes transitioning +/datum/state_machine/weather/proc/finalize_weather_transition(var/obj/abstract/weather_system/holder_instance, var/singleton/state_transition/chosen_transition) + current_state.exited_state(holder_instance) + current_state = chosen_transition.target + current_state.entered_state(holder_instance) + holder_instance.transitioning_weather = FALSE diff --git a/code/modules/weather/weather_fsm_states.dm b/code/modules/weather/weather_fsm_states.dm index 21059e73886..fb49554897e 100644 --- a/code/modules/weather/weather_fsm_states.dm +++ b/code/modules/weather/weather_fsm_states.dm @@ -29,12 +29,18 @@ ABSTRACT_TYPE(/singleton/state/weather) weather.icon_state = icon_state weather.alpha = alpha - if(is_liquid && weather.water_material) - var/material/mat = SSmaterials.get_material_by_name(weather.water_material) - weather.color = mat.icon_colour - else if(is_ice && weather.ice_material) - var/material/mat = SSmaterials.get_material_by_name(weather.ice_material) - weather.color = mat.icon_colour + // Temporarily removing the material checks, we do not have the same material system as Nebula + // if(is_liquid && weather.water_material) + // var/material/mat = SSmaterials.get_material_by_name(weather.water_material) + // weather.color = mat.icon_colour + // else if(is_ice && weather.ice_material) + // var/material/mat = SSmaterials.get_material_by_name(weather.ice_material) + // weather.color = mat.icon_colour + + if(is_liquid) + weather.color = "#689dd4" + else if(is_ice) + weather.color = "#a9c8e8" else weather.color = COLOR_WHITE diff --git a/html/changelogs/geeves-weather_warning.yml b/html/changelogs/geeves-weather_warning.yml new file mode 100644 index 00000000000..72f4dc61228 --- /dev/null +++ b/html/changelogs/geeves-weather_warning.yml @@ -0,0 +1,8 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Atmospheric probes will now relay changes in weather when deployed. Analog radios can be tuned into the weather broadcast and receive it, provided they're in the same sector / connected z-levels." + - bugfix: "Fixed weather transitions to rainy / icy weather not working." + - qol: "Changed rainy / icy weather to have a blue color, reducing eye strain."