using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using NewHorizons.Utility; using Newtonsoft.Json; using static NewHorizons.External.Modules.ShipLogModule; namespace NewHorizons.External.Configs { /// /// Configuration for a specific star system /// [JsonObject] public class StarSystemConfig { /// /// Whether this system can be warped to via the warp drive /// [DefaultValue(true)] public bool canEnterViaWarpDrive = true; /// /// Do you want a clean slate for this star system? Or will it be a modified version of the original. /// [DefaultValue(true)] public bool destroyStockPlanets = true; /// /// Should the time loop be enabled in this system? /// [DefaultValue(true)] public bool enableTimeLoop = true; /// /// Set to the FactID that must be revealed before it can be warped to. Don't set `CanEnterViaWarpDrive` to `false` if /// you're using this, that would make no sense. /// public string factRequiredForWarp; /// /// Should the player not be able to view the map in this system? /// public bool mapRestricted; /// /// Customize the skybox for this system /// public SkyboxConfig skybox; /// /// Set to `true` if you want to spawn here after dying, not Timber Hearth. You can still warp back to the main star /// system. /// public bool startHere; [System.Obsolete("travelAudioClip is deprecated, please use travelAudio instead")] public string travelAudioClip; [System.Obsolete("travelAudioFilePath is deprecated, please use travelAudio instead")] public string travelAudioFilePath; /// /// The audio that will play when travelling in space. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. /// public string travelAudio; /// /// Coordinates that the vessel can use to warp to your solar system. /// public NomaiCoordinates coords; /// /// The position in the solar system the vessel will warp to. /// public MVector3 vesselPosition; /// /// Euler angles by which the vessel will be oriented. /// public MVector3 vesselRotation; /// /// The relative position to the vessel that you will be teleported to when you exit the vessel through the black hole. /// public MVector3 warpExitPosition; /// /// Euler angles by which the warp exit will be oriented. /// public MVector3 warpExitRotation; /// /// Manually layout ship log entries in detective mode /// public EntryPositionInfo[] entryPositions; /// /// A list of fact IDs to reveal when the game starts. /// public string[] initialReveal; /// /// List colors of curiosity entries /// public CuriosityColorInfo[] curiosities; public class NomaiCoordinates { [MinLength(2)] [MaxLength(6)] public int[] x; [MinLength(2)] [MaxLength(6)] public int[] y; [MinLength(2)] [MaxLength(6)] public int[] z; } [JsonObject] public class SkyboxConfig { /// /// Path to the Unity asset bundle to load the skybox material from /// public string assetBundle; /// /// Whether to destroy the star field around the player /// public bool destroyStarField; /// /// Path to the material within the asset bundle specified by `assetBundle` to use for the skybox /// public string path; } /// /// Makes sure they are all numbers are unique and between 0 and 5. /// private static int[] FixAxis(int[] axis) => axis.Distinct().Where(i => (i >= 0 && i <= 5)).ToArray(); public void FixCoordinates() { if (coords != null) { coords.x = FixAxis(coords.x); coords.y = FixAxis(coords.y); coords.z = FixAxis(coords.z); } } public void Merge(StarSystemConfig otherConfig) { // Imagine if this used reflection // True by default so if one is false go false canEnterViaWarpDrive = canEnterViaWarpDrive && otherConfig.canEnterViaWarpDrive; destroyStockPlanets = destroyStockPlanets && otherConfig.destroyStockPlanets; enableTimeLoop = enableTimeLoop && otherConfig.enableTimeLoop; // If current one is null take the other factRequiredForWarp = string.IsNullOrEmpty(factRequiredForWarp) ? otherConfig.factRequiredForWarp : factRequiredForWarp; skybox = skybox == null ? otherConfig.skybox : skybox; travelAudio = string.IsNullOrEmpty(travelAudio) ? otherConfig.travelAudio : travelAudio; // False by default so if one is true go true mapRestricted = mapRestricted || otherConfig.mapRestricted; mapRestricted = mapRestricted || otherConfig.mapRestricted; startHere = startHere || otherConfig.startHere; entryPositions = Concatenate(entryPositions, otherConfig.entryPositions); curiosities = Concatenate(curiosities, otherConfig.curiosities); initialReveal = Concatenate(initialReveal, otherConfig.initialReveal); } private T[] Concatenate(T[] array1, T[] array2) { return (array1 ?? new T[0]).Concat(array2 ?? new T[0]).ToArray(); } public void Migrate() { // Backwards compatability // Should be the only place that obsolete things are referenced #pragma warning disable 612, 618 if (!string.IsNullOrEmpty(travelAudioClip)) travelAudio = travelAudioClip; if (!string.IsNullOrEmpty(travelAudioFilePath)) travelAudio = travelAudioFilePath; } } }