Files
Matt Atlas cca0dfe7b6 Ports /tg/ and CM planemasters to replace our renderers. (#21458)
Part one of our nefarious plans to destroy lag forever, and also
accomplish some cool shit.

This replaces our renderer system with plane masters, this will also be
used to turn skyboxes into backdrops and thus totally remove skybox
updating lag. Additionally, this will let us manipulate entire planes
very easily to do all sorts of zany shit. All credit goes to the
original coders, this is some seriously cool stuff.

Also fixes some bizarre smoothing behaviour, reduces updateoverlays
calls since now not every single structure in the game tries smoothing
with nothing.

<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/9b7cecd7-3c47-448b-9dd8-9b904640bf82"
/>
<img width="1349" height="1349" alt="image"
src="https://github.com/user-attachments/assets/647d75a2-1bff-45ca-ab92-0aea10631afd"
/>

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
2025-10-16 11:39:15 +00:00

128 lines
4.6 KiB
Plaintext

/*
* Notes on weather:
*
* - Weather is a single object that sits in the vis_contents of all outside turfs on
* its associated z-levels and is removed or added by /turf/proc/update_weather(),
* which is usually called from /turf/proc/set_outside().
*
* - Weather generally assumes any atom that cares about it will ask it directly and
* mobs do this in /mob/living/proc/handle_environment().
*
* - For this system to be scalable, it should minimize the amount of list-based
* processing it does and be primarily passive, allowing mobs to ignore it or
* poll it on their own time.
*
* - The weather object is queued on SSweather and is polled every fifteen seconds at time
* of writing. This is handled in /obj/abstract/weather_system/proc/tick().
*
* - When evaluating, weather will generally get more intense or more severe rather than
* jumping around randomly. Each state will set a minimum duration based on min/max time.
*
* - If polled between weather updates there is a chance of modifying wind speed and direction
* instead.
*/
/obj/abstract/weather_system
plane = GAME_PLANE
layer = ABOVE_PROJECTILE_LAYER
icon = 'icons/effects/weather.dmi'
icon_state = "blank"
invisibility = 0
appearance_flags = (RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM)
// Temporarily removing these, we do not have the same material system as Nebula
// /// 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 && !transitioning_weather)
weather_system.evaluate()
// Change wind direction and speed.
handle_wind()
// Handle periodic effects for ticks (like lightning)
var/singleton/state/weather/rain/weather_state = weather_system.current_state
if(istype(weather_state))
weather_state.tick(src)
/obj/abstract/weather_system/Destroy()
// Clean ourselves out of the vis_contents of our affected turfs.
for(var/tz in affecting_zs)
for(var/turf/T as anything in block(locate(1, 1, tz), locate(world.maxx, world.maxy, tz)))
if(T.weather == src)
T.remove_vis_contents(vis_contents_additions)
T.weather = null
vis_contents_additions.Cut()
SSweather.unregister_weather_system(src)
QDEL_NULL(lightning_overlay)
. = ..()
// Called by /turf/examine() to show current weather status.
/obj/abstract/weather_system/examine(mob/user, distance, is_adjacent, infix, suffix, show_extended)
SHOULD_CALL_PARENT(FALSE)
var/singleton/state/weather/weather_state = weather_system.current_state
if(istype(weather_state))
to_chat(user, weather_state.descriptor)
show_wind(user, force = TRUE)
// Called by /singleton/state/weather to assess validity of a state in the weather FSM.
/obj/abstract/weather_system/proc/supports_weather_state(var/singleton/state/weather/next_state)
// Exoplanet stuff for the future:
// - 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 has_water_weather
if(next_state.is_ice)
return has_icy_weather
return TRUE
return FALSE
// Dummy object for lightning flash animation.
/obj/abstract/lightning_overlay
plane = ABOVE_LIGHTING_PLANE //Future EMISSIVE_PLANE
layer = LIGHTNING_LAYER
icon = 'icons/effects/weather.dmi'
icon_state = "full"
alpha = 0
invisibility = 0