using NewHorizons.Utility; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Runtime.Serialization; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using System; using NewHorizons.External.Modules.VariableSize; namespace NewHorizons.External.Modules { [JsonObject] public class PropModule { /// /// Place props in predefined positions on the planet /// public DetailInfo[] details; /// /// Add dialogue triggers to this planet /// public DialogueInfo[] dialogue; /// /// Add ship log entry locations on this planet /// public EntryLocationInfo[] entryLocation; /// /// Add Geysers to this planet /// public GeyserInfo[] geysers; /// /// Add translatable text to this planet /// public NomaiTextInfo[] nomaiText; /// /// Details which will be shown from 50km away. Meant to be lower resolution. /// public DetailInfo[] proxyDetails; /// /// Add rafts to this planet /// public RaftInfo[] rafts; /// /// Add triggers that reveal parts of the ship log on this planet /// public RevealInfo[] reveal; /// /// Scatter props around this planet's surface /// public ScatterInfo[] scatter; /// /// Add slideshows (from the DLC) to the planet /// public ProjectionInfo[] slideShows; /// /// A list of quantum groups that props can be added to. An example of a group would be a list of possible locations for a QuantumSocketedObject. /// public QuantumGroupInfo[] quantumGroups; /// /// Add tornadoes to this planet /// public TornadoInfo[] tornados; /// /// Add volcanoes to this planet /// public VolcanoInfo[] volcanoes; /// /// Add black/white-holes to this planet /// public SingularityModule[] singularities; [JsonObject] public class ScatterInfo { /// /// Relative filepath to an asset-bundle /// public string assetBundle; /// /// Number of props to scatter /// public int count; /// /// Offset this prop once it is placed /// public MVector3 offset; /// /// Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle /// public string path; /// /// Rotate this prop once it is placed /// public MVector3 rotation; /// /// Scale this prop once it is placed /// public float scale = 1f; /// /// The number used as entropy for scattering the props /// public int seed; } [JsonObject] public class DetailInfo { /// /// An optional rename of the detail /// public string rename; /// /// Do we override rotation and try to automatically align this object to stand upright on the body's surface? /// public bool alignToNormal; /// /// Relative filepath to an asset-bundle to load the prefab defined in `path` from /// public string assetBundle; /// /// Either the path in the scene hierarchy of the item to copy or the path to the object in the supplied asset bundle /// public string path; /// /// Position of this prop relative to the body's center /// public MVector3 position; /// /// A list of children to remove from this detail /// public string[] removeChildren; /// /// Do we reset all the components on this object? Useful for certain props that have dialogue components attached to /// them. /// public bool removeComponents; /// /// Rotate this prop /// public MVector3 rotation; /// /// Scale the prop /// [DefaultValue(1f)] public float scale = 1f; /// /// If this value is not null, this prop will be quantum. Assign this field to the id of the quantum group it should be a part of. The group it is assigned to determines what kind of quantum object it is /// public string quantumGroupID; /// /// The path (not including the root planet object) of the parent of this game object. Optional (will default to the root sector). /// public string parentPath; } [JsonObject] public class RaftInfo { /// /// Position of the raft /// public MVector3 position; } [JsonObject] public class GeyserInfo { /// /// Position of the geyser /// public MVector3 position; } [JsonObject] public class TornadoInfo { [JsonConverter(typeof(StringEnumConverter))] public enum TornadoType { [EnumMember(Value = @"downwards")] Downwards = 0, [EnumMember(Value = @"upwards")] Upwards = 1, [EnumMember(Value = @"hurricane")] Hurricane = 2 } [Obsolete("Downwards is deprecated. Use Type instead.")] public bool downwards; /// /// Alternative to setting the position. Will choose a random place at this elevation. /// public float elevation; /// /// The height of this tornado. /// [DefaultValue(30f)] public float height = 30f; /// /// Position of the tornado /// public MVector3 position; /// /// The colour of the tornado. /// public MColor tint; /// /// What type of cyclone should this be? Upwards and downwards are both tornados and will push in that direction. /// public TornadoType type = TornadoType.Downwards; /// /// Angular distance from the starting position that it will wander, in terms of the angle around the x-axis. /// [DefaultValue(45f)] public float wanderDegreesX = 45f; /// /// Angular distance from the starting position that it will wander, in terms of the angle around the z-axis. /// [DefaultValue(45f)] public float wanderDegreesZ = 45f; /// /// The rate at which the tornado will wander around the planet. Set to 0 for it to be stationary. Should be around /// 0.1. /// public float wanderRate; /// /// The maximum distance at which you'll hear the sounds of the cyclone. If not set it will scale relative to the size of the cyclone. /// public float audioDistance; } [JsonObject] public class VolcanoInfo { /// /// The colour of the meteor's lava. /// public MColor lavaTint; /// /// Maximum time between meteor launches. /// [DefaultValue(20f)] public float maxInterval = 20f; /// /// Maximum random speed at which meteors are launched. /// [DefaultValue(150f)] public float maxLaunchSpeed = 150f; /// /// Minimum time between meteor launches. /// [DefaultValue(5f)] public float minInterval = 5f; /// /// Minimum random speed at which meteors are launched. /// [DefaultValue(50f)] public float minLaunchSpeed = 50f; /// /// Position of this volcano. /// public MVector3 position; /// /// Scale of the meteors. /// public float scale = 1; /// /// The colour of the meteor's stone. /// public MColor stoneTint; } [JsonObject] public class DialogueInfo { /// /// Prevents the dialogue from being created after a specific persistent condition is set. Useful for remote dialogue /// triggers that you want to have happen only once. /// public string blockAfterPersistentCondition; /// /// If a pathToAnimController is supplied, if you are within this distance the character will look at you. If it is set /// to 0, they will only look at you when spoken to. /// public float lookAtRadius; /// /// If this dialogue is meant for a character, this is the relative path from the planet to that character's /// CharacterAnimController or SolanumAnimController. /// public string pathToAnimController; /// /// When you enter into dialogue, you will look here. /// public MVector3 position; /// /// Radius of the spherical collision volume where you get the "talk to" prompt when looking at. If you use a /// remoteTriggerPosition, you can set this to 0 to make the dialogue only trigger remotely. /// public float radius = 1f; /// /// Allows you to trigger dialogue from a distance when you walk into an area. /// public MVector3 remoteTriggerPosition; /// /// Distance from radius the prompt appears /// [DefaultValue(2f)] public float range = 2f; /// /// The radius of the remote trigger volume. /// public float remoteTriggerRadius; /// /// Relative path to the xml file defining the dialogue. /// public string xmlFile; } [JsonObject] public class RevealInfo { [JsonConverter(typeof(StringEnumConverter))] public enum RevealVolumeType { [EnumMember(Value = @"enter")] Enter = 0, [EnumMember(Value = @"observe")] Observe = 1, [EnumMember(Value = @"snapshot")] Snapshot = 2 } /// /// The max view angle (in degrees) the player can see the volume with to unlock the fact (`observe` only) /// public float maxAngle = 180f; // Observe Only /// /// The max distance the user can be away from the volume to reveal the fact (`snapshot` and `observe` only) /// public float maxDistance = -1f; // Snapshot & Observe Only /// /// The position to place this volume at /// public MVector3 position; /// /// The radius of this reveal volume /// public float radius = 1f; /// /// What needs to be done to the volume to unlock the facts /// public RevealVolumeType revealOn = RevealVolumeType.Enter; /// /// A list of facts to reveal /// public string[] reveals; /// /// An achievement to unlock. Optional. /// public string achievementID; } [JsonObject] public class EntryLocationInfo { /// /// Whether this location is cloaked /// public bool cloaked; /// /// ID of the entry this location relates to /// public string id; /// /// The position of this entry location /// public MVector3 position; } [JsonObject] public class NomaiTextInfo { [JsonConverter(typeof(StringEnumConverter))] public enum NomaiTextType { [EnumMember(Value = @"wall")] Wall = 0, [EnumMember(Value = @"scroll")] Scroll = 1, [EnumMember(Value = @"computer")] Computer = 2, [EnumMember(Value = @"cairn")] Cairn = 3, [EnumMember(Value = @"recorder")] Recorder = 4, [EnumMember(Value = @"preCrashRecorder")] PreCrashRecorder = 5 } /// /// Additional information about each arc in the text /// public NomaiTextArcInfo[] arcInfo; /// /// The normal vector for this object. Used for writing on walls and positioning computers. /// public MVector3 normal; /// /// Position of the root of this text /// public MVector3 position; /// /// The euler angle rotation of this object. Not required if setting the normal. Computers and cairns will orient /// themselves to the surface of the planet automatically. /// public MVector3 rotation; /// /// The random seed used to pick what the text arcs will look like. /// public int seed; // For randomizing arcs /// /// The type of object this is. /// public NomaiTextType type = NomaiTextType.Wall; /// /// The relative path to the xml file for this object. /// public string xmlFile; } [JsonObject] public class NomaiTextArcInfo { [JsonConverter(typeof(StringEnumConverter))] public enum NomaiTextArcType { [EnumMember(Value = @"adult")] Adult = 0, [EnumMember(Value = @"child")] Child = 1, [EnumMember(Value = @"stranger")] Stranger = 2 } /// /// Whether to flip the spiral from left-curling to right-curling or vice versa. /// public bool mirror; /// /// The local position of this object on the wall. /// public MVector2 position; /// /// The type of text to display. /// public NomaiTextArcType type = NomaiTextArcType.Adult; /// /// Which variation of the chosen type to place. If not specified, a random variation will be selected based on the seed provided in the parent module. /// [DefaultValue(-1)] public int variation = -1; /// /// The z euler angle for this arc. /// [Range(0f, 360f)] public float zRotation; } [JsonObject] public class ProjectionInfo { [JsonConverter(typeof(StringEnumConverter))] public enum SlideShowType { [EnumMember(Value = @"slideReel")] SlideReel = 0, [EnumMember(Value = @"autoProjector")] AutoProjector = 1, [EnumMember(Value = @"visionTorchTarget")] VisionTorchTarget = 2, [EnumMember(Value = @"standingVisionTorch")] StandingVisionTorch = 3, } /// /// The position of this slideshow. /// public MVector3 position; /// /// The ship log entries revealed after finishing this slide reel. /// public string[] reveals; /// /// The rotation of this slideshow. /// public MVector3 rotation; /// /// The list of slides for this object. /// public SlideInfo[] slides; /// /// The type of object this is. /// public SlideShowType type = SlideShowType.SlideReel; } [JsonObject] public class SlideInfo { /// /// Ambient light colour when viewing this slide. /// public MColor ambientLightColor; // SlideAmbientLightModule /// /// Ambient light intensity when viewing this slide. /// public float ambientLightIntensity; /// /// Ambient light range when viewing this slide. /// public float ambientLightRange; // SlideBackdropAudioModule /// /// The name of the AudioClip that will continuously play while watching these slides /// public string backdropAudio; /// /// The time to fade into the backdrop audio /// public float backdropFadeTime; // SlideBeatAudioModule /// /// The name of the AudioClip for a one-shot sound when opening the slide. /// public string beatAudio; /// /// The time delay until the one-shot audio /// public float beatDelay; // SlideBlackFrameModule /// /// Before viewing this slide, there will be a black frame for this many seconds. /// public float blackFrameDuration; /// /// The path to the image file for this slide. /// public string imagePath; // SlidePlayTimeModule /// /// Play-time duration for auto-projector slides. /// public float playTimeDuration; // SlideShipLogEntryModule /// /// Ship log entry revealed when viewing this slide /// public string reveal; /// /// Spotlight intensity modifier when viewing this slide. /// public float spotIntensityMod; } [JsonConverter(typeof(StringEnumConverter))] public enum QuantumGroupType { [EnumMember(Value = @"sockets")] Sockets = 0, [EnumMember(Value = @"states")] States = 1, FailedValidation = 10 } [JsonObject] public class QuantumGroupInfo { /// /// What type of group this is: does it define a list of states a single quantum object could take or a list of sockets one or more quantum objects could share? /// public QuantumGroupType type; /// /// A unique string used by props (that are marked as quantum) use to refer back to this group /// public string id; /// /// Only required if type is `sockets`. This lists all the possible locations for any props assigned to this group. /// public QuantumSocketInfo[] sockets; /// /// Optional. Only used if type is `states`. If this is true, then the first prop made part of this group will be used to construct a visibility box for an empty game object, which will be considered one of the states. /// public bool hasEmptyState; /// /// Optional. Only used if type is `states`. If this is true, then the states will be presented in order, rather than in a random order /// public bool sequential; /// /// Optional. Only used if type is `states` and `sequential` is true. If this is false, then after the last state has appeared, the object will no longer change state /// [DefaultValue(true)] public bool loop = true; } [JsonObject] public class QuantumSocketInfo { /// /// The location of this socket /// public MVector3 position; /// /// The rotation the quantum object will take if it's occupying this socket /// public MVector3 rotation; /// /// The probability any props that are part of this group will occupy this socket /// [DefaultValue(1f)] public float probability = 1f; } } }