-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Day night cycles #74948
Day night cycles #74948
Conversation
code/game/area/areas.dm
Outdated
LAZYCLEARLIST(adjacent_day_night_turf_cache) | ||
LAZYINITLIST(adjacent_day_night_turf_cache) | ||
|
||
for(var/turf/iterating_turf in contents) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looping over area contents is extremely slow. It loops over every turf in the entire world to check if they are in the area.
for(var/turf/iterating_turf in contents) | |
for(var/turf/iterating_turf as anything in get_contained_turfs()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dunno if it's showing for you but GitHub is telling me I changed the indenting even though I didn't 🤷♀️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
worth noting that this is liable to force a good amount of list work, depending on the size of the area and how much has been drawn over it, since it resolves to be removed turfs.
it doesn't mean it's worse then the turfs in world method, but it can be liable to show up as a painpoint if called too early after init. how bad depends on the area, space is the classical worst case scenario.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done this, and tested. I haven't noticed any abnormalities?
/** | ||
* This will calculate all adjacent turfs in this area and add them to a cache for lighting effects. | ||
* | ||
* WARNING: This proc is VERY expensive and should be used sparingly. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When is this called?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only once when an area is setup. It's expensive, so it's used very little. As little as possible. Which is next to never aside from startup which impacts times by a fraction.
continue | ||
adjacent_day_night_turf_cache[iterating_turf] = list(DAY_NIGHT_TURF_INDEX_BITFIELD, DAY_NIGHT_TURF_INDEX_APPEARANCE) | ||
adjacent_day_night_turf_cache[iterating_turf][DAY_NIGHT_TURF_INDEX_BITFIELD] = bitfield | ||
RegisterSignal(iterating_turf, COMSIG_PARENT_QDELETING, PROC_REF(clear_adjacent_turf)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this ever called more than once? Surely this is going to cause signal overrides?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nope, see previous comment
var/datum/lightzone/next_lightzone = get_lightzone(current_iterating_lightzone.end_hour) | ||
var/segments = ((!current_iterating_lightzone.end_hour ? 24 : current_iterating_lightzone.end_hour) - current_iterating_lightzone.start_hour) | ||
var/transition_color = BlendRGB(current_iterating_lightzone.light_color, next_lightzone.light_color, transition_value) | ||
var/transition_alpha = (current_iterating_lightzone.light_alpha * (1 - transition_value)) + (next_lightzone.light_alpha * (0 + transition_value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have a LERP macro which I think you're doing manually here?
name = "early morning" | ||
start_hour = 4 | ||
end_hour = 8 | ||
light_color = "#0000a6" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Every one of these should use the color defines
Important note, turf luminosity no longer impacts visuals, currently only impacting things like view() calls |
code/game/area/areas.dm
Outdated
for(var/bit_step in ALL_JUNCTION_DIRECTIONS) | ||
var/turf/target_turf | ||
switch(bit_step) | ||
if(NORTH_JUNCTION) | ||
target_turf = locate(iterating_turf.x, iterating_turf.y + 1, iterating_turf.z) | ||
if(SOUTH_JUNCTION) | ||
target_turf = locate(iterating_turf.x, iterating_turf.y - 1, iterating_turf.z) | ||
if(EAST_JUNCTION) | ||
target_turf = locate(iterating_turf.x + 1, iterating_turf.y, iterating_turf.z) | ||
if(WEST_JUNCTION) | ||
target_turf = locate(iterating_turf.x - 1, iterating_turf.y, iterating_turf.z) | ||
if(NORTHEAST_JUNCTION) | ||
if(bitfield & NORTH_JUNCTION || bitfield & EAST_JUNCTION) | ||
continue | ||
target_turf = locate(iterating_turf.x + 1, iterating_turf.y + 1, iterating_turf.z) | ||
if(SOUTHEAST_JUNCTION) | ||
if(bitfield & SOUTH_JUNCTION || bitfield & EAST_JUNCTION) | ||
continue | ||
target_turf = locate(iterating_turf.x + 1, iterating_turf.y - 1, iterating_turf.z) | ||
if(SOUTHWEST_JUNCTION) | ||
if(bitfield & SOUTH_JUNCTION || bitfield & WEST_JUNCTION) | ||
continue | ||
target_turf = locate(iterating_turf.x - 1, iterating_turf.y - 1, iterating_turf.z) | ||
if(NORTHWEST_JUNCTION) | ||
if(bitfield & NORTH_JUNCTION || bitfield & WEST_JUNCTION) | ||
continue | ||
target_turf = locate(iterating_turf.x - 1, iterating_turf.y + 1, iterating_turf.z) | ||
if(!target_turf) | ||
continue | ||
var/area/target_area = target_turf.loc | ||
if(target_area == src) | ||
continue | ||
if(!target_area.outdoors || target_area.underground) | ||
continue | ||
bitfield ^= bit_step |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is very strange, are you doing this just to ensure looping for this second bit?
ESPECIALLY because this is done for every turf in potentially huge areas, this seems like something that would be worth unrolling (wouldn't even lose all that much)
var/mutable_appearance/appearance_to_add = mutable_appearance( | ||
icon = 'icons/effects/daynight_blend.dmi', | ||
icon_state = "[adjacent_day_night_turf_cache[iterating_turf][DAY_NIGHT_TURF_INDEX_BITFIELD]]", | ||
layer = DAY_NIGHT_LIGHTING_LAYER, | ||
offset_spokesman = iterating_turf, | ||
plane = LIGHTING_PLANE, | ||
alpha = incoming_controller.current_light_alpha, | ||
appearance_flags = RESET_COLOR | RESET_ALPHA | RESET_TRANSFORM | ||
) | ||
appearance_to_add.color = incoming_controller.current_light_color |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This feels like something that should be cached, with a color, alpha, bitfield and z level string key. Least going off gut it may not be quite such a big deal idk
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like it's not really needed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
how hot is this code?
/** | ||
* Compiles a lookup table using the loaded lightzones for each hour so we can reference it later when switching to said hour. | ||
*/ | ||
/datum/day_night_controller/proc/compile_transitions() | ||
var/hour_index = 0 // We start at 1 as this is 24hr time | ||
var/datum/lightzone/current_iterating_lightzone | ||
var/transition_value = 0 | ||
for(var/i in 1 to MIDNIGHT_RESET) | ||
var/datum/lightzone/check_lightzone = get_lightzone(hour_index) | ||
if(current_iterating_lightzone != check_lightzone) | ||
current_iterating_lightzone = check_lightzone | ||
transition_value = 0 | ||
var/datum/lightzone/next_lightzone = get_lightzone(current_iterating_lightzone.end_hour) | ||
var/segments = ((!current_iterating_lightzone.end_hour ? 24 : current_iterating_lightzone.end_hour) - current_iterating_lightzone.start_hour) | ||
var/transition_color = BlendRGB(current_iterating_lightzone.light_color, next_lightzone.light_color, transition_value) | ||
var/transition_alpha = (current_iterating_lightzone.light_alpha * (1 - transition_value)) + (next_lightzone.light_alpha * (0 + transition_value)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be worth looking into color gradients instead of rolling your own, tho I'm not sure if that's what you're doing here or not
https://www.byond.com/docs/ref/#/{notes}/color-gradient
@@ -8,6 +8,9 @@ | |||
///the turf that our light is applied to | |||
var/turf/affected_turf | |||
|
|||
/// Area which gets linked to a lighting object to make it consider the luminosity from the day/night blending from the area. Yes this isn't ideal, but applying luminosity up to 2 (from both sources) on the turf is not ideal either | |||
var/area/day_night_area |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not a massive fan of how this works I'ma be honest, needing to reach in and touch the object, the datum var read, etc. sucks
Would a sources list/bitflag work here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also don't like how this is tied directly to day night stuff by name, that's its purpose in terms of this pr but this allows an area to decide if a lighting object should provide lumin or not, it's more general then the name implies
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a way to implement the bitflag? I could set the bitflag and unset it accordingly. But it would just be two options
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I thought incorrectly about how overlay lighting worked.
Something like a bool or a flag seems less... messy? idk.
If the area's lum changes that's fine, can't be helped. I guess I'd mostly just object to the name being so bespoke if so.
I am a bit worried about what happens if areas change, or if a turf loses its lighting object, but that's not related to this all that directly
code/modules/cargo/order.dm
Outdated
requisition_text+= "Time of Order: [station_time_timestamp()]<br/>" | ||
requisition_text+= "Time of Order: [SSday_night.get_twentyfourhour_timestamp()]<br/>" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This seems strictly worse in terms of names
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated it to be more readable, idk what else id name it since that's as informative as it gets
welcome back, i'm excited to see this in the game. |
/datum/day_night_controller/proc/update_time(hour) | ||
if(color_lookup_table["[hour ? hour - 1 : 24]"] == color_lookup_table["[hour]"] && alpha_lookup_table["[hour ? hour - 1 : 24]"] == alpha_lookup_table["[hour]"]) // Why change the color of the light when it's the same as the last????? | ||
return | ||
update_lighting(color_lookup_table["[hour]"], alpha_lookup_table["[hour]"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add an animation transition to this i beg of you, in all honesty it should have a transition played from here to the next hour if performance allows, would let this look far smoother
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I might try to do this at some point, but that's a lot of stress for little gain, since the changes aren't that often
if you supply me with the color values, see the light zones for reference |
This PR has been inactive for long enough to be automatically marked as stale. This means it is at risk of being auto closed in ~ 7 days, please address any outstanding review items and ensure your PR is finished, if these are all true and you are auto-staled anyway, you need to actively ask maintainers if your PR will be merged. Once you have done any of the previous actions then you should request a maintainer remove the stale label on your PR, to reset the stale timer. If you feel no maintainer will respond in that time, you may wish to close this PR youself, while you seek maintainer comment, as you will then be able to reopen the PR yourself |
A bit late to this, but this is such a good addition to the game. Very very excited to see the this project at its conclusion |
This PR has been inactive for long enough to be automatically marked as stale. This means it is at risk of being auto closed in ~ 7 days, please address any outstanding review items and ensure your PR is finished, if these are all true and you are auto-staled anyway, you need to actively ask maintainers if your PR will be merged. Once you have done any of the previous actions then you should request a maintainer remove the stale label on your PR, to reset the stale timer. If you feel no maintainer will respond in that time, you may wish to close this PR youself, while you seek maintainer comment, as you will then be able to reopen the PR yourself |
@Gandalf2k15 are you able to fix conflicts? @LemonInTheDark can we merge this as is? |
I am concerned about the overhead of I don't think? I have any issues outside of that |
This PR has been inactive for long enough to be automatically marked as stale. This means it is at risk of being auto closed in ~ 7 days, please address any outstanding review items and ensure your PR is finished, if these are all true and you are auto-staled anyway, you need to actively ask maintainers if your PR will be merged. Once you have done any of the previous actions then you should request a maintainer remove the stale label on your PR, to reset the stale timer. If you feel no maintainer will respond in that time, you may wish to close this PR youself, while you seek maintainer comment, as you will then be able to reopen the PR yourself |
About The Pull Request
(remade at the request of san)
Greetings! Today I bring you a new system to be used in the game. A day and night controller.
I've been wanting a way out of the darkness of icebox for quite a long time, and I hope this is the best way!
This basically adds a system that will set an areas lighting to something that would make sense for the time of day.
Example of this in action(video sped up massively)
dreamseeker_pEasneSJ6t.mp4
Key points:
New time system
The new time system aims to provide a more random feeling to the station while maintaining a system that can easily be used to access the current in game IC time. This is shown on most items that are in-game and used to show the old IC station time. This does not change how the OOC world time works.
Why have I added this?
Well, it's so there can be a more noticeable change in the outside environment during a 30 minute to 3-hour round. Before, this would never have been possible, and it makes sense to make all IC time uniform. It just would not be noticeable if every minute that passed was just a minute.
Lightzones
Lightzones are datums that are used to define what sort of lighting any affected areas in the controller should look like. This can be changed to whatever you want, but they must all add up to 24 hours.
Day night controllers
These are what are used to control Z-level day/night cycles, they can currently only be loaded by adding an entry to the map config JSON, but adding more ways to add day/night controllers is trivial at worst.
Day-night controllers compile assigned timezones to build a lookup table for hourly updates to the atmosphere. These lookup tables are compiled so that the transitions between timezones are as smooth as possible.
After testing using the turf lighting update system, I realised it just was not fast enough, so I decided to take inspiration from Azarak's day night system on Horizon, so the area system now uses mutable appearances as underlays.
How the effect is achieved
This system uses a combination of area underlays and turf luminosity as well as turf underlays to dynamically build a "lightmap" for the map.
The open areas use area underlays to efficiently generate a thematic colour and light intensity, while the luminosity is used to determine if you can actually see in the dark.
This also applies to adjacent turfs(turfs that are on the edge of the area and that should affected by the outside lighting), the adjacent turfs are calculated using an algorithm to decide what turfs should have lighting overlays applied. These turfs also hook into the areas luminosity to generate seamless transitions between lighting areas.
To-do:
Why It's Good For The Game
This adds a way for us to have different atmospheres for different maps.
Credits
A special thanks goes to Azarak for some of the logic behind this, specifically the area adjacency turf system, see more at: https://github.com/hrzntal/horizon/pull/247
Changelog
🆑 Gandalf2k15, Azarak
add: Icebox will now show if it's day or night using a new time system.
balance: Solar panels will now generate different amounts of energy depending on what time it is(on icebox).
refactor: The time system backend has changed significantly. Every 2.4 hours 24 hours pass in game.
/:cl: