// Distant Lands 2024 // COZY: Stylized Weather 3 // All code included in this file is protected under the Unity Asset Store Eula using System.Collections; using UnityEngine; using DistantLands.Cozy.Data; using UnityEngine.Serialization; namespace DistantLands.Cozy { [ExecuteAlways] public class CozyTimeModule : CozyModule { public CozyTransitModule transit; public PerennialProfile perennialProfile; public CozyDateOverride overrideDate; [Range(0, 1)] public float yearPercentage = 0; public float modifiedDayPercentage; public bool transitioningTime; [FormerlySerializedAs("m_DayPercentage")] [CozySearchable] public MeridiemTime currentTime = 0; public int AbsoluteDay => currentDay + GetDaysPerYear() * currentYear; [CozySearchable] public int currentDay; [CozySearchable] public int currentYear; public CozyTimeModule parentModule; public override void InitializeModule() { base.InitializeModule(); weatherSphere.timeModule = this; } internal override bool CheckIfModuleCanBeRemoved(out string warning) { if (weatherSphere.GetModule() != null) { warning = "Transit Module"; return false; } warning = ""; return true; } internal override bool CheckIfModuleCanBeAdded(out string warning) { if (weatherSphere.GetModule() != null) { warning = "System Time Module"; return false; } warning = ""; return true; } void Start() { SetupTime(); } void Update() { if (weatherSphere.timeModule == null) weatherSphere.timeModule = this; ManageTime(); yearPercentage = GetCurrentYearPercentage(); modifiedDayPercentage = transit ? transit.ModifyDayPercentage(currentTime) / 360 : currentTime; } void SetupTime() { if (perennialProfile.resetTimeOnStart) currentTime = perennialProfile.startTime; if (perennialProfile.realisticYear) perennialProfile.daysPerYear = perennialProfile.GetRealisticDaysPerYear(currentYear); } /// /// Constrains the time to fit within the length parameters set on the perennial profile. /// private void ConstrainTime() { if (currentTime >= 1) { currentTime -= 1; ChangeDay(1); weatherSphere.events.RaiseOnDayChange(); } if (currentTime < 0) { currentTime += 1; ChangeDay(-1); weatherSphere.events.RaiseOnDayChange(); } } private void ChangeDay(int change) { if (overrideDate) { overrideDate.ChangeDay(change); return; } if (!perennialProfile.progressDay) return; currentDay += change; if (currentDay >= perennialProfile.daysPerYear) { currentDay -= perennialProfile.daysPerYear; currentYear++; weatherSphere.events.RaiseOnYearChange(); } if (currentDay < 0) { currentDay += perennialProfile.daysPerYear; currentYear--; weatherSphere.events.RaiseOnYearChange(); } } public int GetDaysPerYear() { if (overrideDate) return overrideDate.DaysPerYear(); if (perennialProfile.realisticYear) return perennialProfile.GetRealisticDaysPerYear(currentYear); else return perennialProfile.daysPerYear; } public void GetSunTransitTime(out MeridiemTime sunrise, out MeridiemTime sunset) { if (transit) { transit.GetSunTransitTime(out sunrise, out sunset); return; } sunrise = 0.25f; sunset = 0.75f; } /// /// Returns the current year percentage (0 - 1). /// public float GetCurrentYearPercentage() { if (overrideDate) return overrideDate.GetCurrentYearPercentage(); float dat = DayAndTime(); return dat / (float)GetDaysPerYear(); } /// /// Returns the current year percentage (0 - 1) after a number of ticks has passed. /// public float GetCurrentYearPercentage(float inTIme) { if (overrideDate) return overrideDate.GetCurrentYearPercentage(inTIme); float dat = DayAndTime() + inTIme; return dat / perennialProfile.daysPerYear; } /// /// Gets the current day plus the current day percentage (0-1). /// public float DayAndTime() { if (overrideDate) return overrideDate.DayAndTime(); return currentDay + currentTime; } /// /// Manages the movement of time in the scene. /// public void ManageTime() { if (Application.isPlaying && !perennialProfile.pauseTime) currentTime += modifiedTimeSpeed * Time.deltaTime; ConstrainTime(); } public float modifiedTimeSpeed { get { return perennialProfile.timeMovementSpeed * (perennialProfile.pauseTime ? 0 : 1) * (perennialProfile.modulateTimeSpeed ? perennialProfile.timeSpeedMultiplier.Evaluate(currentTime) : 1) / 1440; } } /// /// Skips the weather system forward by the ticksToSkip value. /// public void SkipTime(MeridiemTime timeToSkip) { currentTime += (float)timeToSkip; if (weatherSphere.GetModule()) weatherSphere.GetModule().SkipTime(timeToSkip); foreach (CozySystem i in weatherSphere.systems) { i.SkipTime(timeToSkip); } } public void SkipTime(MeridiemTime timeToSkip, int daysToSkip) { currentTime += (float)timeToSkip; currentDay += daysToSkip; if (weatherSphere.GetModule()) weatherSphere.GetModule().SkipTime(timeToSkip + daysToSkip); foreach (CozySystem i in weatherSphere.systems) { i.SkipTime(timeToSkip + daysToSkip); } } public void SetHour(int hour) { currentTime = new MeridiemTime(hour, currentTime.minutes, currentTime.seconds, currentTime.milliseconds); } public void SetMinute(int minute) { currentTime = new MeridiemTime(currentTime.hours, minute, currentTime.seconds, currentTime.milliseconds); } /// /// Returns the title for the current month. /// public string MonthTitle(float month) { if (perennialProfile.realisticYear) { GetCurrentMonth(out string monthName, out int monthDay, out float monthPercentage); return monthName + " " + monthDay; } else { float j = Mathf.Floor(month * 12); float monthLength = perennialProfile.daysPerYear / 12; float monthTime = DayAndTime() - (j * monthLength); PerennialProfile.DefaultYear monthName = (PerennialProfile.DefaultYear)j; PerennialProfile.TimeDivisors monthTimeName = PerennialProfile.TimeDivisors.Mid; if ((monthTime / monthLength) < 0.33f) monthTimeName = PerennialProfile.TimeDivisors.Early; else if ((monthTime / monthLength) > 0.66f) monthTimeName = PerennialProfile.TimeDivisors.Late; else monthTimeName = PerennialProfile.TimeDivisors.Mid; return $"{monthTimeName} {monthName}"; } } public void GetCurrentMonth(out string monthName, out int monthDay, out float monthPercentage) { int i = currentDay; int j = 0; while (i > ((perennialProfile.useLeapYear && currentYear % 4 == 0) ? perennialProfile.leapYear[j].days : perennialProfile.standardYear[j].days)) { i -= (perennialProfile.useLeapYear && currentYear % 4 == 0) ? perennialProfile.leapYear[j].days : perennialProfile.standardYear[j].days; j++; if (j >= ((perennialProfile.useLeapYear && currentYear % 4 == 0) ? perennialProfile.leapYear.Length : perennialProfile.standardYear.Length)) break; } PerennialProfile.Month k = (perennialProfile.useLeapYear && currentYear % 4 == 0) ? perennialProfile.leapYear[j] : perennialProfile.standardYear[j]; monthName = k.name; monthDay = i; monthPercentage = k.days; } /// /// Smoothly skips a set amount of time into the future. /// The day percentage (given in a float or Meridiem Time) to skip forward. /// The time in seconds it takes to transition to the new time. /// public void TransitionTime(float timeToSkip, float time) { StartCoroutine(TransitionTime(currentTime, timeToSkip, time)); } IEnumerator TransitionTime(float startDayPercentage, float timeToSkip, float time) { transitioningTime = true; float t = time; float targetTime = timeToSkip % 1; float targetDay = Mathf.Floor(timeToSkip); float transitionSpeed = timeToSkip / time; while (t > 0) { float div = 1 - (t / time); yield return new WaitForEndOfFrame(); currentTime += Time.deltaTime * transitionSpeed; t -= Time.deltaTime; } transitioningTime = false; } } }