Snaxi Fixes (#38639)

* first batch

* fix corners AGAIN

* runtime
This commit is contained in:
west3436
2025-12-03 08:33:23 -05:00
committed by GitHub
parent afc3bac6b7
commit e81c7e5a2d
12 changed files with 205 additions and 52 deletions

View File

@@ -270,6 +270,7 @@ var/MAX_EXPLOSION_RANGE = 32
#define NO_FLORA (1<<4) // Prevents plants from growing
#define NO_LOOT (1<<5) // No loot spawning here
#define DEFER_EDGING (1<<6) // Skip adding edges on init
#define SHUTTLE_TURF (1<<7) // Turf is part of a shuttle
//turf edge flags
#define EDGE_CARDINAL 1<<1 // edges on cardinals only

View File

@@ -191,10 +191,20 @@ On the map dm file, redefine the following:
T.set_light(next_light_range, light_power, planet.current_timeOfDay, lowpriority)
// Force lighting change on a list of turfs (used mainly for when shuttles leave)
/datum/subsystem/daynightcycle/proc/update_turf_lighting(var/list/turf/turfs, var/datum/planet_type/planet)
if(!turfs.len || !planet)
/datum/subsystem/daynightcycle/proc/update_turf_lighting(var/list/turf/turfs, var/datum/planet_type/planet = null)
if(!turfs.len)
return
var/light_power = (planet.current_timeOfDay == TOD_NIGHTTIME) ? 3 : 10
light_power *= planet.weather_mod
var/timeOfDay
var/light_power
if(planet)
timeOfDay = planet.current_timeOfDay
light_power = (timeOfDay == TOD_NIGHTTIME) ? 3 : 10
light_power *= planet.weather_mod
else
timeOfDay = current_timeOfDay
light_power = next_light_power * weather_mod
for(var/turf/T in turfs)
T.set_light(next_light_range, light_power, planet.current_timeOfDay, lowpriority = FALSE)
T.set_light(next_light_range, light_power, timeOfDay, lowpriority = FALSE)

View File

@@ -61,3 +61,35 @@ var/list/precip_state_to_texture = list()
C.register_weather_turf(S)
return C
// Restart a specific climate in case it gets corrupted
/datum/subsystem/weather/proc/restart_climate(var/datum/climate/C)
if(!C || !istype(C))
return FALSE
var/climate_type = C.type
var/climate_z = C.z
var/datum/allocation/climate_allocation = C.allocation
climates -= C
C.clear_forecast()
if(C.current_weather)
qdel(C.current_weather)
if(C.weather_image)
for(var/turf/T in C.weather_turfs)
T.vis_contents -= C.weather_image
qdel(C.weather_image)
qdel(C)
var/datum/climate/new_climate = new climate_type(climate_z, climate_allocation, FALSE)
climates += new_climate
if(climate_allocation && climate_allocation.turfs)
for(var/turf/unsimulated/floor/snow/S in climate_allocation.turfs)
new_climate.register_weather_turf(S)
else
for(var/turf/unsimulated/floor/snow/S in block(locate(1, 1, climate_z), locate(world.maxx, world.maxy, climate_z)))
new_climate.register_weather_turf(S)
return TRUE

View File

@@ -57,18 +57,17 @@ var/list/weathertracker = list() //associative list, gathers time spent one each
weather_image.UpdatePrecipitation(WEATHER_CALM)
// Register any outdoor turf with this climate (generalized for all weather types)
/datum/climate/proc/register_weather_turf(var/turf/T)
/datum/climate/proc/register_weather_turf(var/turf/T,var/force = FALSE)
if(!T)
return
if(!isopensurface(T.loc))
if(T in weather_turfs)
weather_turfs -= T
return
if(T in weather_turfs)
return
weather_turfs += T
if(!force)
if(!isopensurface(T.loc))
if(T in weather_turfs)
weather_turfs -= T
return
weather_turfs |= T
if(weather_image)
T.vis_contents += weather_image
T.vis_contents |= weather_image
// Unregister an outdoor turf from this climate
/datum/climate/proc/unregister_weather_turf(var/turf/T)
@@ -83,15 +82,30 @@ var/list/weathertracker = list() //associative list, gathers time spent one each
return
/datum/climate/proc/forecast()
if(!current_weather)
CRASH("Forecast called with null current_weather on [src]")
if(!istype(current_weather, /datum/weather))
CRASH("Forecast called with invalid current_weather ([current_weather]) on [src] - expected weather instance, got [current_weather.type]")
// Validate that current weather type has transitions defined
if(!(current_weather.type in weather_transitions))
CRASH("Forecast called but current weather type [current_weather.type] not found in weather_transitions for [src]")
var/cycle = 1
clear_forecast()
forecasts = list(current_weather) //project based on current weather
while(forecasts.len <= PREDICTION_MINIMUM+1 && cycle <= PREDICTION_MAXIMUM)
var/datum/weather/W = forecasts[forecasts.len]
if(!istype(W, /datum/weather))
CRASH("Forecast found invalid weather in forecasts list: [W]")
var/list/possible_transitions = weather_transitions[W.type]
if(!possible_transitions || !possible_transitions.len)
break //No further transitions possible
var/path = pickweight(possible_transitions)
if(isnull(path))
CRASH("Forecast got null path from pickweight for weather type [W.type] - transitions: [json_encode(possible_transitions)]")
if(!ispath(path, /datum/weather))
CRASH("Forecast got invalid path [path] from pickweight for weather type [W.type] - expected weather type path")
if(path == W.type)
W.timeleft += round(rand(cycle_freq[1],cycle_freq[2]),SS_WAIT_WEATHER)
else
@@ -171,7 +185,8 @@ var/list/weathertracker = list() //associative list, gathers time spent one each
current_weather.execute()
current_weather.update_weather_sounds()
else
weather_transitions[current_weather.type] = list(weather = 100)
weather_transitions[current_weather.type] = list()
weather_transitions[current_weather.type][weather] = 100
else if(istype(weather,/datum/weather))
//We have been given a specific weather datum. It may be modified, so run it no matter what.
@@ -183,7 +198,8 @@ var/list/weathertracker = list() //associative list, gathers time spent one each
current_weather.execute()
else
var/datum/weather/W = weather
weather_transitions[current_weather.type] = list(W.type = 100)
weather_transitions[current_weather.type] = list()
weather_transitions[current_weather.type][W.type] = 100
else
WARNING("Change weather was called with [weather], neither a weather datum nor a path.")

View File

@@ -161,11 +161,12 @@
if(!isopensurface(T) || !istype(T,/turf/space))
for(var/obj/O in T.contents)
if(istype(O,/obj/structure/shuttle))
corner = TRUE
break
if(istype(T,/turf/space))
corner = TRUE
break
if(corner)
continue
T.shuttle_turf = TRUE
T.turf_flags |= SHUTTLE_TURF
return
/datum/shuttle/Destroy()
@@ -726,10 +727,10 @@
linked_area.contents.Add(new_turf)
new_turf.change_area(old_area,linked_area)
if(isshuttleturf(old_turf) || old_turf.shuttle_turf)
if(isshuttleturf(old_turf) || (old_turf.turf_flags & SHUTTLE_TURF))
new_turf.ChangeTurf(old_turf.type, allow = 1)
new_turf.shuttle_turf = TRUE
old_turf.shuttle_turf = FALSE
new_turf.turf_flags |= SHUTTLE_TURF
old_turf.turf_flags &= ~SHUTTLE_TURF
new_turfs[C] = new_turf
//***Remove old turf from shuttle's area****
@@ -876,10 +877,16 @@
// doing this for source and destination in case we move between planets
var/datum/allocation/source_allocation = SSmapping.get_allocation(trf = our_center)
var/datum/climate/source_climate = SSweather.get_climate(our_center.z, source_allocation)
if(!source_climate)
source_climate = SSweather.get_climate(our_center.z, null)
var/datum/allocation/dest_allocation = SSmapping.get_allocation(trf = new_center)
var/datum/climate/dest_climate = SSweather.get_climate(new_center.z, dest_allocation)
if(!dest_climate)
dest_climate = SSweather.get_climate(new_center.z, null)
for(var/turf/T in linked_area.contents)
if(T in corner_turfs)
continue
if(source_climate)
source_climate.unregister_weather_turf(T)
if(dest_climate)
@@ -892,9 +899,25 @@
// Re-register turfs left behind by the shuttle with the source climate
if(source_climate)
for(var/turf/old_turf in old_turfs)
source_climate.register_weather_turf(old_turf)
var/datum/planet_type/source_planet = source_climate.allocation?.ptype
source_climate.register_weather_turf(old_turf, TRUE)
var/datum/planet_type/source_planet = source_climate?.allocation?.ptype
if(source_planet)
SSDayNight.update_turf_lighting(old_turfs, source_planet)
else if(our_center.z in daynight_z_lvls) //pre-mapped day/night users like snaxi or jungle
for(var/turf/old_turf in old_turfs)
if(IsEven(old_turf.x) && IsEven(old_turf.y))
var/area/A = get_area(old_turf)
if(isopensurface(A))
daynight_turfs |= old_turf
else
for(var/cdir in cardinal)
var/turf/T1 = get_step(old_turf, cdir)
var/area/A1 = get_area(T1)
if(istype(A1, /area/surface))
daynight_turfs |= old_turf
break
SSDayNight.update_turf_lighting(old_turfs)
return 1

View File

@@ -29,11 +29,11 @@ var/list/climatecomps = list()
dat += "<center>"
dat += "<div class='modal'><div class='modal-content'><div class='line'><b>Weather Report</b></div><br>"
var/datum/climate/C = SSweather.get_climate(src.z)
if(C)
if(C?.current_weather)
var/datum/weather/W = C.current_weather
var/reported_temp = C.current_weather.temperature - 273.15
var/remaining_time = formatTimeDuration(C.current_weather.timeleft)
dat += "<b>Current Weather:</b> <div class='line'>[C.current_weather.name]</div>"
var/reported_temp = W.temperature - 273.15
var/remaining_time = formatTimeDuration(W.timeleft)
dat += "<b>Current Weather:</b> <div class='line'>[W.name]</div>"
dat += "<b>Temperature:</b> <div class='line'>[reported_temp] Celcius</div>"
dat += W.weather_details()
dat += "<b>Next Meteorlogical Event:</b> <div class='line'>[remaining_time]</div>"

View File

@@ -89,6 +89,7 @@
T.dynamic_lighting = 1
if(SSlighting && SSlighting.initialized && !T.lighting_overlay)
new /atom/movable/lighting_overlay(T, TRUE)
update_weather_overlays(T)
/obj/structure/shuttle/diag_wall/New()
..()
@@ -107,6 +108,11 @@
if(istype(T,/turf/space))
T.dynamic_lighting = 0
T.lighting_clear_overlay()
var/datum/climate/Cold = SSweather.get_climate(T.z)
if(Cold)
Cold.unregister_weather_turf(T, TRUE)
plane = initial(plane)
layer = initial(layer)
..()
T = get_turf(destination)
if(T)
@@ -116,6 +122,25 @@
T.dynamic_lighting = 1
if(!T.lighting_overlay)
new /atom/movable/lighting_overlay(T, TRUE)
update_weather_overlays(T)
/obj/structure/shuttle/diag_wall/proc/update_weather_overlays(var/turf/T)
var/climate_added = FALSE
for(var/turf/adjT in range(1, T))
if(adjT == T)
continue
if(istype(adjT, T.type))
for(var/obj/effect/weather_holder/WH in adjT.vis_contents)
T.vis_contents |= WH
climate_added = TRUE
break
if(climate_added)
break
var/datum/climate/Cnew = SSweather.get_climate(T.z)
if(climate_added && Cnew)
Cnew.register_weather_turf(T, TRUE)
plane = EFFECTS_PLANE
layer = SNOW_OVERLAY_LAYER + 1
/obj/structure/shuttle/diag_wall/Cross(atom/movable/mover, turf/target, height=1.5, air_group = 0)
if(air_group)

View File

@@ -58,7 +58,6 @@
// if STANDING ON THE EDGE OF THE z-level will transition you to another
var/can_border_transition = 0
var/shuttle_turf = FALSE // is this turf part of a shuttle and ISN'T A SHUTTLE TURF TYPE REEE
/*
* Technically obsoleted by base_turf
//For building on the asteroid.
@@ -246,7 +245,7 @@
var/move_to_z = src.z
if(ZL.transition_crosswrap_z && ZL.transition_crosswrap_z.len>=4)
locked_to_current_z=TRUE //prevent shuffling z-level later in the code.
randomize_drift_position=FALSE
@@ -258,7 +257,7 @@
move_to_z=ZL.transition_crosswrap_z[3]
else if(A.x<=TRANSITIONEDGE) // WEST
move_to_z=ZL.transition_crosswrap_z[4]
// Prevent MoMMIs from leaving the derelict and to ensure Exile Implants work properly.
for(var/mob/living/L in contents_brought)

View File

@@ -53,17 +53,17 @@
sorted_climates += C
for(var/datum/climate/C in sorted_climates)
if(!C.current_weather)
continue
var/datum/weather/W = C.current_weather
var/sector_display = C.allocation ? "([C.allocation.sector[1]], [C.allocation.sector[2]])" : "N/A"
var/weather_display = W ? "[W.name] <a href='?_src_=vars;Vars=\ref[W]'>\[VV\]</A>" : "<font color='red'>ERROR: NULL</font>"
var/timeleft_display = W ? "<a href='?src=\ref[src];climate_timeleft=\ref[W]'>[formatTimeDuration(W.timeleft)]</A>" : "<font color='red'>N/A</font>"
dat += {"<tr>
<td>Z-[C.z]</td>
<td>[sector_display]</td>
<td>[C.name] <a href='?_src_=vars;Vars=\ref[C]'>\[VV\]</A></td>
<td>[W.name] <a href='?_src_=vars;Vars=\ref[W]'>\[VV\]</A></td>
<td><a href='?src=\ref[src];climate_timeleft=\ref[W]'>[formatTimeDuration(W.timeleft)]</A></td>
<td><a href='?src=\ref[src];climate_weather=\ref[C]'>Change Weather</A></td>
<td>[weather_display]</td>
<td>[timeleft_display]</td>
<td><a href='?src=\ref[src];climate_weather=\ref[C]'>Change Weather</A> | <a href='?src=\ref[src];climate_restart=\ref[C]'>Restart</A></td>
</tr>"}
dat += {"

View File

@@ -691,6 +691,20 @@
message_admins("<span class='notice'>[key_name(usr)] changed the weather to [nu] for Z-[C.z].</span>", 1)
climate_panel()
else if(href_list["climate_restart"])
if(!check_rights(R_ADMIN))
return
var/datum/climate/C = locate(href_list["climate_restart"])
if(!C || !istype(C))
return
var/response = alert(usr, "This will completely restart the climate controller for Z-[C.z]. Continue?", "Restart Climate", "Yes", "No")
if(response != "Yes")
return
SSweather.restart_climate(C)
log_admin("[key_name(usr)] restarted the climate controller for Z-[C.z].")
message_admins("<span class='notice'>[key_name(usr)] restarted the climate controller for Z-[C.z].</span>", 1)
climate_panel()
else if(href_list["delay_round_end"])
if(!check_rights(R_SERVER))
return

View File

@@ -10,8 +10,16 @@ var/blizzardz = 1
/datum/event/blizzard/start()
if(blizzard_ready)
var/datum/climate/C = pick(climates) //one lucky z-level gets a blizzard!
var/list/arctic_climates = list()
for(var/datum/climate/C in climates)
if(istype(C, /datum/climate/arctic))
arctic_climates += C
if(!arctic_climates.len)
CRASH("BLIZZARD: No arctic climates found")
var/datum/climate/C = pick(arctic_climates)
var/datum/weather/W = C.current_weather
if(!W)
CRASH("BLIZZARD: Current weather is null for climate [C]")
if(istype(W,/datum/weather/snow/blizzard))
command_alert(/datum/command_alert/blizzard_extended)
W.timeleft += round(rand(4 MINUTES, 10 MINUTES),SS_WAIT_WEATHER)
@@ -19,12 +27,20 @@ var/blizzardz = 1
blizzard_ready = FALSE
command_alert(/datum/command_alert/blizzard_start)
W.timeleft = round(rand(2 MINUTES, 4 MINUTES),SS_WAIT_WEATHER)
// Temporarily override transitions to force blizzard
var/list/old_transitions = C.weather_transitions[W.type]
C.change_weather(/datum/weather/snow/blizzard, force = FALSE)
C.forecast()
// Restore original transitions after forecasting
C.weather_transitions[W.type] = old_transitions
C.clear_forecast()
var/datum/weather/blizzard = new /datum/weather/snow/blizzard(C)
blizzard.timeleft = round(rand(C.cycle_freq[1], C.cycle_freq[2]), SS_WAIT_WEATHER)
C.forecasts = list(blizzard)
for(var/i = 1; i <= PREDICTION_MINIMUM; i++)
var/datum/weather/last = C.forecasts[C.forecasts.len]
var/list/possible = C.weather_transitions[last.type]
if(!possible || !possible.len)
break
var/next_path = pickweight(possible)
if(!next_path)
break
var/datum/weather/next = new next_path(C)
C.forecasts += next
spawn(blizzard_cooldown)
blizzard_ready = TRUE
@@ -38,10 +54,27 @@ var/blizzardz = 1
if(blizzard_ready)
blizzard_ready = 0
command_alert(/datum/command_alert/omega_blizzard)
var/datum/climate/C = pick(climates)
var/list/arctic_climates = list()
for(var/datum/climate/C in climates)
if(istype(C, /datum/climate/arctic))
arctic_climates += C
if(!arctic_climates.len)
CRASH("OMEGA BLIZZARD: No arctic climates found")
var/datum/climate/C = pick(arctic_climates)
var/datum/weather/W = C.current_weather
if(!W)
CRASH("OMEGA BLIZZARD: Current weather is null for climate [C]")
W.timeleft = round(rand(8 MINUTES, 10 MINUTES),SS_WAIT_WEATHER)
var/list/old_transitions = C.weather_transitions[W.type]
C.weather_transitions[W.type] = list(/datum/weather/snow/blizzard/omega = 100)
C.forecast()
C.weather_transitions[W.type] = old_transitions
C.clear_forecast()
var/datum/weather/omega = new /datum/weather/snow/blizzard/omega(C)
C.forecasts = list(omega)
for(var/i = 1; i <= PREDICTION_MINIMUM; i++)
var/datum/weather/last = C.forecasts[C.forecasts.len]
var/list/possible = C.weather_transitions[last.type]
if(!possible || !possible.len)
break
var/next_path = pickweight(possible)
if(!next_path)
break
var/datum/weather/next = new next_path(C)
C.forecasts += next

View File

@@ -28915,7 +28915,7 @@
"boF" = (
/obj/structure/shuttle/engine/propulsion/left,
/obj/structure/shuttle/diag_wall/smooth,
/turf/space,
/turf/simulated/floor/plating,
/area/shuttle/escape_pod1)
"boG" = (
/obj/machinery/door/unpowered/shuttle,
@@ -28929,7 +28929,7 @@
/obj/structure/shuttle/diag_wall/smooth{
dir = 4
},
/turf/space,
/turf/simulated/floor/plating,
/area/shuttle/escape_pod1)
"boI" = (
/turf/simulated/wall,
@@ -29185,7 +29185,7 @@
"bpz" = (
/obj/structure/shuttle/engine/propulsion/left,
/obj/structure/shuttle/diag_wall/smooth,
/turf/space,
/turf/simulated/floor/plating,
/area/shuttle/escape_pod2)
"bpA" = (
/obj/machinery/door/unpowered/shuttle,
@@ -29199,7 +29199,7 @@
/obj/structure/shuttle/diag_wall/smooth{
dir = 4
},
/turf/space,
/turf/simulated/floor/plating,
/area/shuttle/escape_pod2)
"bpC" = (
/obj/machinery/light/small{