forked from Shardstone/trail-into-darkness
99 lines
3.9 KiB
C#
99 lines
3.9 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace Jovian.Calendar {
|
|
/// <summary>
|
|
/// ScriptableObject defining the rules of an in-game calendar: day length, hours, minutes,
|
|
/// month structure, month names, week length, and starting date. Create via
|
|
/// Assets > Create > Jovian > Calendar > Calendar Settings.
|
|
/// </summary>
|
|
[CreateAssetMenu(fileName = "CalendarSettings", menuName = "Jovian/Calendar/Calendar Settings")]
|
|
public class CalendarSettings : ScriptableObject {
|
|
/// <summary>How many real-time seconds one full 0 to 1 float cycle represents.</summary>
|
|
public float secondsPerFullDay;
|
|
|
|
/// <summary>How many in-world hours per day (e.g. 24, or 16 for a shorter day).</summary>
|
|
public int hoursPerDay;
|
|
|
|
/// <summary>How many in-world minutes per hour (e.g. 60).</summary>
|
|
public int minutesPerHour;
|
|
|
|
/// <summary>
|
|
/// Days in each month, in order. Length of this array defines months per year.
|
|
/// E.g. { 30, 28, 31 } = 3 months with different lengths.
|
|
/// </summary>
|
|
public int[] daysPerMonth;
|
|
|
|
/// <summary>
|
|
/// Custom month names. Must match daysPerMonth.Length.
|
|
/// </summary>
|
|
public string[] monthNames;
|
|
|
|
/// <summary>Optional: days per week for week-tracking. 0 to disable.</summary>
|
|
public int daysPerWeek;
|
|
|
|
// --- Starting date ---
|
|
public int startYear;
|
|
public int startMonth; // 0-indexed
|
|
public int startDay; // 0-indexed
|
|
public int startHour;
|
|
public int startMinute;
|
|
|
|
/// <summary>Number of months in a year, derived from daysPerMonth array length.</summary>
|
|
public int MonthsPerYear => daysPerMonth?.Length ?? 0;
|
|
|
|
/// <summary>Total days in one full year.</summary>
|
|
public int TotalDaysInYear {
|
|
get {
|
|
var total = 0;
|
|
if(daysPerMonth == null) {
|
|
return 0;
|
|
}
|
|
foreach(var t in daysPerMonth) {
|
|
total += t;
|
|
}
|
|
return total;
|
|
}
|
|
}
|
|
|
|
/// <summary>Total in-world minutes in a single day.</summary>
|
|
public int MinutesPerDay => hoursPerDay * minutesPerHour;
|
|
|
|
/// <summary>Validates all calendar parameters. Throws ArgumentException on invalid configuration.</summary>
|
|
public void Validate() {
|
|
if(secondsPerFullDay <= 0f) {
|
|
throw new ArgumentException("SecondsPerFullDay must be > 0");
|
|
}
|
|
if(hoursPerDay <= 0) {
|
|
throw new ArgumentException("HoursPerDay must be > 0");
|
|
}
|
|
if(minutesPerHour <= 0) {
|
|
throw new ArgumentException("MinutesPerHour must be > 0");
|
|
}
|
|
if(daysPerMonth == null || daysPerMonth.Length == 0) {
|
|
throw new ArgumentException("DaysPerMonth must have at least one entry");
|
|
}
|
|
if(monthNames == null || monthNames.Length != daysPerMonth.Length) {
|
|
throw new ArgumentException("MonthNames length must match DaysPerMonth length");
|
|
}
|
|
for(var i = 0; i < daysPerMonth.Length; i++) {
|
|
if(daysPerMonth[i] <= 0) {
|
|
throw new ArgumentException($"DaysPerMonth[{i}] must be > 0");
|
|
}
|
|
}
|
|
if(startMonth < 0 || startMonth >= daysPerMonth.Length) {
|
|
throw new ArgumentException("StartMonth out of range");
|
|
}
|
|
if(startDay < 0 || startDay >= daysPerMonth[startMonth]) {
|
|
throw new ArgumentException("StartDay out of range for StartMonth");
|
|
}
|
|
if(startHour < 0 || startHour >= hoursPerDay) {
|
|
throw new ArgumentException("StartHour out of range");
|
|
}
|
|
if(startMinute < 0 || startMinute >= minutesPerHour) {
|
|
throw new ArgumentException("StartMinute out of range");
|
|
}
|
|
}
|
|
}
|
|
}
|