Skip to content
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 Time Cycle For Maps #1234

Merged
merged 4 commits into from
Nov 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading