Introduces starlight to all Horizon exterior areas (#21396)

This introduces logic to place starlight onto turfs under
horizon/exterior, and extends that area across the entirety of the
Horizon's EVA areas, to remove the anachronistic darkness that's been
atop the wings up to now. Handling this at the area level was the
cleanest way I could think to implement it.

<details>
<summary>How it looks!</summary>
<img width="954" height="711" alt="image"
src="https://github.com/user-attachments/assets/ef82f1fe-0720-4559-8dca-390bf1ddff4d"
/>
<img width="924" height="878" alt="image"
src="https://github.com/user-attachments/assets/ffa37bd2-7814-42eb-99ae-ebfc1ed1b680"
/>
<img width="917" height="904" alt="image"
src="https://github.com/user-attachments/assets/8b36f9c9-dbe1-4c5a-bb0c-f5080eb359f4"
/>
<img width="953" height="952" alt="image"
src="https://github.com/user-attachments/assets/531724ba-2a19-4ddd-bd31-70a1ebfb4543"
/>
</details>

**Potential problems:**

<details>
<summary>Shuttle logic problems</summary>
To get this working, all of the Horizon's EVA areas have had to be
covered in the horizon/exterior area - which means there's now an area
clash on the south, west, and east shuttle port, which falls afoul of
the current is_valid check for shuttle landmarks. Notably, how this is
mapped also means that an rfloor silhouette of a shuttle is always left
on the Horizon after a shuttle undocks from any of these landmarks.

<img width="864" height="704" alt="image"
src="https://github.com/user-attachments/assets/4fd27d84-8d7c-4ed7-8333-f934a2d77e03"
/>

The problem here is on the mapping, not the logic - it seems like these
areas were formerly excluded from the horizon/exterior area exactly to
dance around this problem. The solution I've taken tentatively is simply
to remove the area check. This doesn't feel great, but I don't think
there's many situations in which it could bite us - maybe on exoplanets?

The only other solution here is to remap the Horizon's docking ports to
not suffer from this issue, which I'm not eager to do. I honestly just
attribute this to being another fundamental flaw of the Horizon's design
that we have to just dance around until we move off the map. I've
documented that it's purely a mapping issue on the commented code
segment, and that once the mapping issue is resolved there's no issue
with an area check.
</details>

- [x] Figure out how to have starlight carry over after a shuttle
departs
- [x] Resolve the Horizon's shuttles being unable to dock with its
docking ports

---------

Signed-off-by: hazelrat <83198434+hazelrat@users.noreply.github.com>
Co-authored-by: Matt Atlas <mattiathebest2000@hotmail.it>
This commit is contained in:
hazelrat
2025-10-01 18:14:21 +00:00
committed by GitHub
co-authored by Matt Atlas
parent 10c05af44b
commit eef80013fa
12 changed files with 4002 additions and 3969 deletions
+21 -8
View File
@@ -14,7 +14,8 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
var/uid
///Bitflag (Any of `AREA_FLAG_*`). See `code\__DEFINES\misc.dm`.
var/area_flags
var/holomap_color // Color of this area on the holomap. Must be a hex color (as string) or null.
/// Color of this area on the holomap. Must be a hex color (as string) or null.
var/holomap_color
///Do we have an active fire alarm?
var/fire = FALSE
@@ -33,22 +34,27 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
invisibility = INVISIBILITY_LIGHTING
var/obj/machinery/power/apc/apc = null
var/turf/base_turf // The base turf type of the area, which can be used to override the z-level's base turf.
/// The base turf type of the area, which can be used to override the z-level's base turf.
var/turf/base_turf
var/lightswitch = FALSE
var/eject = null
var/requires_power = 1
var/always_unpowered = 0 //this gets overridden to 1 for space in area/New()
/// This gets overridden to 1 for space in area/New()
var/always_unpowered = 0
var/power_equip = 1 // Status vars
// Status vars
var/power_equip = 1
var/power_light = 1
var/power_environ = 1
var/used_equip = 0 // Continuous drain; don't touch these directly.
// Continuous drain; don't touch these directly.
var/used_equip = 0
var/used_light = 0
var/used_environ = 0
var/oneoff_equip = 0 // Used once and cleared each tick.
// Used once and cleared each tick.
var/oneoff_equip = 0
var/oneoff_light = 0
var/oneoff_environ = 0
@@ -71,8 +77,10 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
///Used to decide what kind of reverb the area makes sound have
var/sound_environment = SOUND_AREA_STANDARD_STATION
var/no_light_control = FALSE // If TRUE, lights in area cannot be toggled with light controller.
var/allow_nightmode = FALSE // If TRUE, lights in area will be darkened by the night mode controller.
/// If TRUE, lights in area cannot be toggled with light controller.
var/no_light_control = FALSE
/// If TRUE, lights in area will be darkened by the night mode controller.
var/allow_nightmode = FALSE
var/emergency_lights = FALSE
/**
@@ -98,6 +106,11 @@ GLOBAL_LIST_INIT(area_blurb_stated_to, list())
var/tmp/is_outside = OUTSIDE_NO
/// Should the turfs in this area render starlight accurate to the starlight of the local sector?
/// This is intended for use with EVA areas of ships - such as the wings of the Horizon, for instance.
/// You probably shouldn't be setting this to true on any planet-based maps, or on any indoors areas.
var/needs_starlight = FALSE
/**
* Don't move this to Initialize(). Things in here need to run before SSatoms does.
*/
+5 -1
View File
@@ -90,12 +90,16 @@
new flooring.build_type(src)
flooring = null
set_light(0)
broken = null
burnt = null
flooring_override = null
levelupdate()
// Set light to zero, so glowing turfs cease to glow if turned into plating.
set_light(0)
// Check if this still needs to have starlight - if it does, it'll be given back its starlight.
update_starlight()
if(!defer_icon_update)
update_icon(1)
+17 -10
View File
@@ -20,7 +20,6 @@
explosion_resistance = 3
var/use_space_appearance = TRUE
var/use_starlight = TRUE
/turf/space/dynamic //For use in edge cases where you want the turf to not be completely lit, like in places where you have placed lattice.
dynamic_lighting = 1
@@ -35,7 +34,7 @@
if(use_space_appearance)
appearance = SSskybox.space_appearance_cache[(((x + y) ^ ~(x * y) + z) % 25) + 1]
if(GLOB.config.starlight && use_starlight && GLOB.lighting_overlays_initialized)
if(GLOB.config.starlight && GLOB.lighting_overlays_initialized)
update_starlight()
for(var/atom/movable/AM as mob|obj in src)
@@ -51,6 +50,22 @@
return INITIALIZE_HINT_NORMAL
// Handles starlight logic unique to space turfs.
/turf/space/update_starlight()
. = ..() // We also run the parent proc here, since space may also require starlight from needs_starlight!
// Our parent proc already handled starlight for us, we don't have to do our own checks
if(.)
return
// Otherwise, if a space turf borders a simulated turf, it should be producing starlight.
if(locate(/turf/simulated) in RANGE_TURFS(1, src))
set_light(SSatlas.current_sector.starlight_range, SSatlas.current_sector.starlight_power, l_color = SSskybox.background_color)
// We don't want this doing anything on space, otherwise update_starlight() would run set_light on space turfs twice.
/turf/space/set_default_lighting()
return
/turf/space/Destroy()
// Cleanup cached z_eventually_space values above us.
if (above)
@@ -73,14 +88,6 @@
return 0
/turf/space/proc/update_starlight()
if(!GLOB.config.starlight)
return
if(locate(/turf/simulated) in RANGE_TURFS(1, src))
set_light(SSatlas.current_sector.starlight_range, SSatlas.current_sector.starlight_power, l_color = SSskybox.background_color)
else
set_light(0)
/turf/space/attackby(obj/item/attacking_item, mob/user)
if (istype(attacking_item, /obj/item/stack/rods))
-1
View File
@@ -1,7 +1,6 @@
/turf/space/transit
plane = 0
use_space_appearance = TRUE
use_starlight = TRUE
var/pushdirection
//Overwrite because we dont want people building rods in space.
+58 -13
View File
@@ -19,27 +19,36 @@
// General properties.
var/icon_old = null
var/pathweight = 1 // How much does it cost to pathfind over this turf?
var/blessed = 0 // Has the turf been blessed?
/// How much does it cost to pathfind over this turf?
var/pathweight = 1
/// Has the turf been blessed?
var/blessed = 0
var/footstep_sound = /singleton/sound_category/tiles_footstep
var/list/decals
var/list/blueprints
var/is_hole // If true, turf will be treated as space or a hole
/// If true, turf will be treated as space or a hole
var/is_hole
var/tmp/turf/baseturf
var/roof_type = null // The turf type we spawn as a roof.
/// The turf type we spawn as a roof.
var/roof_type = null
var/tmp/roof_flags = 0
var/movement_cost = 0 // How much the turf slows down movement, if any.
/// How much the turf slows down movement, if any.
var/movement_cost = 0
// Footprint info
var/tracks_footprint = TRUE // Whether footprints will appear on this turf
var/does_footprint = FALSE // Whether stepping on this turf will dirty your shoes or feet with the below
var/footprint_color // The hex color produced by the turf
var/track_distance = 12 // How far the tracks last
/// Whether footprints will appear on this turf
var/tracks_footprint = TRUE
/// Whether stepping on this turf will dirty your shoes or feet with the below
var/does_footprint = FALSE
/// The hex color produced by the turf
var/footprint_color
/// How far the tracks last
var/track_distance = 12
//Mining resources (for the large drills).
var/has_resources
@@ -53,7 +62,12 @@
var/base_icon_state = "plating"
var/base_color = null
var/last_clean //for clean log spam.
///for clean log spam.
var/last_clean
/// Should this turf ever possibly have starlight rendered on it? If it definitely never ever should, set to false.
/// Check update_starlight for possible situations wherein starlight may be rendered on a turf in the first place.
var/use_starlight = TRUE
///what /mob/oranges_ear instance is already assigned to us as there should only ever be one.
///used for guaranteeing there is only one oranges_ear per turf when assigned, speeds up view() iteration
@@ -106,9 +120,6 @@
if (smoothing_flags)
QUEUE_SMOOTH(src)
if (light_range && light_power)
update_light()
if (opacity)
has_opaque_atom = TRUE
@@ -119,6 +130,12 @@
if(A.base_turf)
baseturf = A.base_turf
update_starlight()
if (light_range && light_power)
update_light()
else if(!baseturf)
// Hard-coding this for performance reasons.
baseturf = SSatlas.current_map.base_turf_by_z["[z]"] || /turf/space
@@ -163,6 +180,34 @@
underlay_appearance.dir = adjacency_dir
return TRUE
/// Handles starlight for turfs for whose area's needs_starlight var is set to true.
/// Logic unique to space turfs is set within a child proc of this!
/// If this proc handles starlight, its child doesn't have to - therefore, we return TRUE.
/// If it has failed to handle starlight, we return FALSE so the subsequent logic for space turfs can run.
/turf/proc/update_starlight()
// We don't render starlight if config says we shouldn't.
if(!GLOB.config.starlight)
return TRUE
// If this turf specifically shouldn't be receiving starlight, we cut it here.
if(!use_starlight)
return TRUE
// All area turfs are covered here - they should be starlit if their area's needs_starlight var is true, otherwise they
// are set to their default lighting. Areas can change in-game, so this needs to support removing starlight from a turf too.
// We do this prior to the unique space logic so this also covers space turfs within a needs_starlight area.
var/area/A = get_area(src)
if(A.needs_starlight)
set_light(SSatlas.current_sector.starlight_range, SSatlas.current_sector.starlight_power, l_color = SSskybox.background_color)
return TRUE
else // If we aren't assigning starlight lighting, set the lighting to default so it's possible to undo starlight lighting if an area changes.
set_default_lighting()
return FALSE
/// Restores the default lighting of a turf.
/turf/proc/set_default_lighting()
set_light(initial(light_range), initial(light_power), initial(light_color))
/turf/ex_act(severity)
return 0
+4
View File
@@ -74,6 +74,10 @@
var/turf/new_turf = new path(src)
// If the area requires starlight, we need to fill it back in with starlight after the change.
// Particularly necessary so shuttles don't leave dark patches after undocking with starlit turfs.
update_starlight()
// WARNING WARNING
// Turfs DO NOT lose their signals when they get replaced, REMEMBER THIS
// It's possible because turfs are fucked, and if you have one in a list and it's replaced with another one, the list ref points to the new turf
+1 -1
View File
@@ -420,7 +420,7 @@
break
// Landability check - try to find an already-open space for an LZ
if(attempts >= 10)
if(check_collision(T.loc, block_to_check))
if(check_collision(block_to_check))
valid = FALSE
else // If we're running low on attempts we try to make our own LZ, ignoring landability but still checking for ruins
new_type = /obj/effect/shuttle_landmark/automatic/clearing
+12 -4
View File
@@ -76,7 +76,7 @@
return FALSE
for(var/area/A in shuttle.shuttle_area)
var/list/translation = get_turf_translation(get_turf(shuttle.current_location), get_turf(src), A.contents)
if(check_collision(base_area, list_values(translation)))
if(check_collision(list_values(translation)))
return FALSE
var/conn = GetConnectedZlevels(z)
for(var/w in (z - shuttle.multiz) to z)
@@ -109,15 +109,23 @@
clear_landing_indicators()
activate_ghostroles()
/proc/check_collision(area/target_area, list/target_turfs)
/proc/check_collision(list/target_turfs)
for(var/target_turf in target_turfs)
var/turf/target = target_turf
if(!target)
return TRUE //collides with edge of map
if(target.loc != target_area)
return TRUE //collides with another area
// IMPORTANT: The below area check is commented out as it is not compatible with the Horizon,
// which has docking ports with clashing turfs + areas! There's no good reason for this not to
// be re-enabled once the server's primary map doesn't have such poorly mapped docking ports.
// It being disabled shouldn't cause too many problems in the meantime. Hopefully.
// if(target.loc != target_area)
// return TRUE //clashes with another area
if(target.density)
return TRUE //dense turf
return FALSE
//Self-naming/numbering ones.
@@ -0,0 +1,59 @@
################################
# Example Changelog File
#
# Note: This file, and files beginning with ".", and files that don't end in ".yml" will not be read. If you change this file, you will look really dumb.
#
# Your changelog will be merged with a master changelog. (New stuff added only, and only on the date entry for the day it was merged.)
# When it is, any changes listed below will disappear.
#
# Valid Prefixes:
# bugfix
# - (fixes bugs)
# wip
# - (work in progress)
# qol
# - (quality of life)
# soundadd
# - (adds a sound)
# sounddel
# - (removes a sound)
# rscadd
# - (adds a feature)
# rscdel
# - (removes a feature)
# imageadd
# - (adds an image or sprite)
# imagedel
# - (removes an image or sprite)
# spellcheck
# - (fixes spelling or grammar)
# experiment
# - (experimental change)
# balance
# - (balance changes)
# code_imp
# - (misc internal code change)
# refactor
# - (refactors code)
# config
# - (makes a change to the config files)
# admin
# - (makes changes to administrator tools)
# server
# - (miscellaneous changes to server)
#################################
# Your name.
author: hazelmouse
# Optional: Remove this file after generating master changelog. Useful for PR changelogs that won't get used again.
delete-after: True
# Any changes you've made. See valid prefix list above.
# INDENT WITH TWO SPACES. NOT TABS. SPACES.
# SCREW THIS UP AND IT WON'T WORK.
# Also, this gets changed to [] after reading. Just remove the brackets when you add new shit.
# Please surround your changes in double quotes ("). It works without them, but if you use certain characters it screws up compiling. The quotes will not show up in the changelog.
changes:
- rscadd: "All EVA turfs on the Horizon are now automatically assigned starlight on initialisation, meaning that the wings are no longer entirely dark. This is overwritten if the turfs are modified."
- rscadd: "Implements some minor changes to the Horizon's outer hull."
@@ -39,6 +39,8 @@
base_turf = /turf/space
dynamic_lighting = TRUE
requires_power = FALSE
// This area will place starlight on any turf it's put on!
needs_starlight = TRUE
has_gravity = FALSE
no_light_control = TRUE
allow_nightmode = FALSE
@@ -29,42 +29,42 @@
landmark_tag = "nav_horizon_dock_deck_3_starboard_1"
docking_controller = "airlock_horizon_dock_deck_3_starboard_1"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
/obj/effect/shuttle_landmark/horizon/dock/deck_3/starboard_2
name = "Third Deck Starboard Dock 2"
landmark_tag = "nav_horizon_dock_deck_3_starboard_2"
docking_controller = "airlock_horizon_dock_deck_3_starboard_2"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
/obj/effect/shuttle_landmark/horizon/dock/deck_3/starboard_3
name = "Third Deck Starboard Dock 3"
landmark_tag = "nav_horizon_dock_deck_3_starboard_3"
docking_controller = "airlock_horizon_dock_deck_3_starboard_3"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
/obj/effect/shuttle_landmark/horizon/dock/deck_3/port_1
name = "Third Deck Port Dock 1"
landmark_tag = "nav_horizon_dock_deck_3_port_2"
docking_controller = "airlock_horizon_dock_deck_3_port_2"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
/obj/effect/shuttle_landmark/horizon/dock/deck_3/port_2
name = "Third Deck Port Dock 2"
landmark_tag = "nav_horizon_dock_deck_3_port_4"
docking_controller = "airlock_horizon_dock_deck_3_port_4"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
/obj/effect/shuttle_landmark/horizon/dock/deck_3/port_3
name = "Third Deck Port Dock 3"
landmark_tag = "nav_horizon_dock_deck_3_port_5"
docking_controller = "airlock_horizon_dock_deck_3_port_5"
base_turf = /turf/simulated/floor/reinforced/airless
base_area = /area/space
base_area = /area/horizon/exterior
// ================================ exterior
File diff suppressed because it is too large Load Diff