Skip to content

Commit

Permalink
Day/Night Time Cycle For Maps (#1234)
Browse files Browse the repository at this point in the history
# Description

Add real world Day/Night cycle changing, with Ambient color
interpolation and some configurable features for mappers.
High inspired by
[Nuclear-14](https://github.com/Vault-Overseers/nuclear-14.git) and
[Crystall Punk 14](https://github.com/crystallpunk-14/)

TimeCycle use 24h day calculation, instead coefficient, like in N14. 

---

# TODO

[ ] - Add more examples/prepared map palettes for Day/Night ambient.
[ ] - (Optional) Move all palette description into List of variables,
instead calling `IPrototypeManager` every minute passing.

---


https://github.com/user-attachments/assets/cc5d1b8c-bd25-4042-8cee-e2edfa0d9acc


![image](https://github.com/user-attachments/assets/abcdc11d-fdb1-4b48-8599-0116a5797f8b)

---

# Changelog

:cl:
- add: Added Day/Night time cycle for admins and mapers.
  • Loading branch information
DocNITE authored Nov 18, 2024
1 parent 3f8194a commit ab0fa7c
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 1 deletion.
94 changes: 94 additions & 0 deletions Content.Server/TimeCycle/TimeCycleSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
using Robust.Shared.Timing;
using Robust.Shared.Prototypes;
using Robust.Shared.Map.Components;
using Content.Shared.TimeCycle;

namespace Content.Server.TimeCycle;

public sealed partial class TimeCycleSystem : EntitySystem
{
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;

public override void Initialize()
{
base.Initialize();
}

public override void Update(float frameTime)
{
var curTime = _gameTiming.CurTime;
var query = EntityQueryEnumerator<TimeCycleComponent, MapLightComponent>();

while (query.MoveNext(out var mapid, out var timeComp, out var mapLightComp))
{
if (timeComp.Paused
|| curTime < timeComp.DelayTime)
continue;

// Should be used for developing time palletes or for debuging
// O-o-or... You can cosplay pucchi from JoJo 6 with his 'Made In Heaven'
timeComp.DelayTime = curTime + (timeComp.SpeedUp ? timeComp.SpeedUpMinuteDuration : timeComp.MinuteDuration);

// Pass minute of map time
timeComp.CurrentTime += TimeSpan.FromMinutes(1);

// Change ambient color
UpdateAmbientColor(mapid, timeComp, mapLightComp);
}

base.Update(frameTime);
}

private void UpdateAmbientColor(EntityUid mapid, TimeCycleComponent timeComp, MapLightComponent mapLightComp)
{
if (!_prototypeManager.TryIndex(timeComp.PalettePrototype, out TimeCyclePalettePrototype? timeEntries)
|| timeEntries is null)
return;

var timeInCycle = GetTimeInCycle(timeComp.CurrentTime);
mapLightComp.AmbientLightColor = GetInterpolatedColor(timeEntries, timeInCycle);
Dirty(mapid, mapLightComp);
}

// We should convert current 'TimeSpan' (with days) time into one day cycle time (in 24 hours)
private TimeSpan GetTimeInCycle(TimeSpan timeSpan) =>
TimeSpan.FromMilliseconds(timeSpan.TotalMilliseconds % TimeSpan.FromHours(24).TotalMilliseconds);

private Color GetInterpolatedColor(TimeCyclePalettePrototype proto, TimeSpan timeInCycle)
{
// If there is no one any time entries of palette - return black
if (proto.TimeEntries is null)
return Color.Black;

var currentTime = timeInCycle.TotalHours;
var startTime = -1;
var endTime = -1;

foreach (KeyValuePair<int, Color> kvp in proto.TimeEntries)
{
var hour = kvp.Key;
var color = kvp.Value;

if (hour <= currentTime)
startTime = hour;
else if (hour >= currentTime && endTime == -1)
endTime = hour;
}

if (startTime == -1)
startTime = 0;
else if (endTime == -1)
endTime = 23;

var entryStart = proto.TimeEntries[startTime];
var entryEnd = proto.TimeEntries[endTime];
var entryProgress = GetEntryProgress(TimeSpan.FromHours(startTime), TimeSpan.FromHours(endTime), timeInCycle);

return Color.InterpolateBetween(entryStart, entryEnd, entryProgress);
}

private float GetEntryProgress(TimeSpan startTime, TimeSpan endTime, TimeSpan currentTime) =>
((float)(currentTime.TotalMinutes - startTime.TotalMinutes) / (float)(endTime.TotalMinutes - startTime.TotalMinutes));

}
2 changes: 1 addition & 1 deletion Content.Server/Toolshed/Commands/VisualizeCommand.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System.Linq;
using System.Linq;
using Content.Server.Administration;
using Content.Server.EUI;
using Content.Shared.Administration;
Expand Down
27 changes: 27 additions & 0 deletions Content.Shared/TimeCycle/TimeCycleComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
namespace Content.Shared.TimeCycle;

[RegisterComponent]
public sealed partial class TimeCycleComponent : Component
{
// Delayed time, before minute have been passed
public TimeSpan? DelayTime;

[DataField]
public bool SpeedUp;

[DataField]
public bool Paused;

[DataField]
public TimeSpan MinuteDuration { get; set; } = TimeSpan.FromSeconds(4);

[DataField]
public TimeSpan SpeedUpMinuteDuration { get; set; } = TimeSpan.FromMilliseconds(10);

// NOTE: Default time should be is noon
[DataField]
public TimeSpan CurrentTime { get; set; } = TimeSpan.FromHours(12);

[DataField]
public string PalettePrototype = "DefaultTimeCycle";
}
16 changes: 16 additions & 0 deletions Content.Shared/TimeCycle/TimeCyclePalettePrototype.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using Robust.Shared.Prototypes;

namespace Content.Shared.TimeCycle;

/// <summary>
///
/// </summary>
[Prototype("timeCyclePalette")]
public sealed partial class TimeCyclePalettePrototype : IPrototype
{
[IdDataField]
public string ID { get; private set; } = default!;

[DataField]
public Dictionary<int, Color> TimeEntries = default!;
}
30 changes: 30 additions & 0 deletions Resources/Prototypes/time_cycle_palletes.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
- type: timeCyclePalette
id: DefaultTimeCycle
timeEntries:
0: "#000000" # Night
2: "#000000" # Late night
4: "#02020b" # Very-Early-Morning
6: "#312716" # Early-Dawn
7: "#4E3D23" # Dawn
8: "#58372d" # Sunrise
9: "#876A42" # Early-Morning
10: "#A08042" # Mid-Morning
12: "#A88F73" # Noon
14: "#C1A78A" # Early-Afternoon
16: "#7D6244" # Afternoon
18: "#8C6130" # Sunset
20: "#543521" # Dusk
22: "#02020b" # Early night
24: "#000000" # Night

- type: timeCyclePalette
id: Gothic
timeEntries:
0: "#000000" # Night
2: "#000000" # Late night
6: "#11122c" # Sunrise
12: "#d8b059" # Noon
18: "#73586b" # Sunset
20: "#11122c" # Dusk
21: "#000000" # Early night
24: "#000000" # Night

0 comments on commit ab0fa7c

Please sign in to comment.