diff --git a/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs b/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs index b6ca8df8..d2edd47b 100644 --- a/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs +++ b/NewHorizons/Builder/Atmosphere/VolumesBuilder.cs @@ -28,15 +28,15 @@ namespace NewHorizons.Builder.Atmosphere var innerRadius = config.Base.surfaceSize; - GameObject volumesGO = new GameObject("Volumes"); + var volumesGO = new GameObject("Volumes"); volumesGO.SetActive(false); volumesGO.transform.parent = planetGO.transform; - GameObject rulesetGO = new GameObject("Ruleset"); + var rulesetGO = new GameObject("Ruleset"); rulesetGO.SetActive(false); rulesetGO.transform.parent = volumesGO.transform; - SphereShape SS = rulesetGO.AddComponent(); + var SS = rulesetGO.AddComponent(); SS.SetCollisionMode(Shape.CollisionMode.Volume); SS.SetLayer(Shape.Layer.Sector); SS.layerMask = -1; @@ -45,7 +45,7 @@ namespace NewHorizons.Builder.Atmosphere rulesetGO.AddComponent(); - PlanetoidRuleset PR = rulesetGO.AddComponent(); + var PR = rulesetGO.AddComponent(); PR._altitudeFloor = innerRadius; PR._altitudeCeiling = sphereOfInfluence; PR._shuttleLandingRadius = sphereOfInfluence; @@ -54,7 +54,7 @@ namespace NewHorizons.Builder.Atmosphere rulesetGO.AddComponent(); - EffectRuleset ER = rulesetGO.AddComponent(); + var ER = rulesetGO.AddComponent(); ER._type = EffectRuleset.BubbleType.Underwater; ER._material = _gdMaterial; @@ -66,32 +66,6 @@ namespace NewHorizons.Builder.Atmosphere } ER._cloudMaterial = cloudMaterial; - if (config.Base.zeroGravityRadius != 0) - { - var zeroGObject = new GameObject("ZeroGVolume"); - zeroGObject.transform.parent = volumesGO.transform; - zeroGObject.transform.localPosition = Vector3.zero; - zeroGObject.transform.localScale = Vector3.one * config.Base.zeroGravityRadius; - zeroGObject.layer = LayerMask.NameToLayer("BasicEffectVolume"); - - var sphereCollider = zeroGObject.AddComponent(); - sphereCollider.radius = 1; - sphereCollider.isTrigger = true; - - var owCollider = zeroGObject.AddComponent(); - owCollider._parentBody = owrb; - owCollider._collider = sphereCollider; - - var triggerVolume = zeroGObject.AddComponent(); - triggerVolume._owCollider = owCollider; - - var zeroGVolume = zeroGObject.AddComponent(); - zeroGVolume._attachedBody = owrb; - zeroGVolume._triggerVolume = triggerVolume; - zeroGVolume._inheritable = true; - zeroGVolume._priority = 1; - } - volumesGO.transform.position = planetGO.transform.position; rulesetGO.SetActive(true); volumesGO.SetActive(true); diff --git a/NewHorizons/Builder/General/GravityBuilder.cs b/NewHorizons/Builder/General/GravityBuilder.cs index 5fa6c33e..997e7a04 100644 --- a/NewHorizons/Builder/General/GravityBuilder.cs +++ b/NewHorizons/Builder/General/GravityBuilder.cs @@ -50,7 +50,7 @@ namespace NewHorizons.Builder.General gravityVolume._upperSurfaceRadius = config.Base.surfaceSize; gravityVolume._lowerSurfaceRadius = 0; gravityVolume._layer = 3; - gravityVolume._priority = 0; + gravityVolume._priority = config.Base.gravityVolumePriority; gravityVolume._alignmentPriority = 0; gravityVolume._surfaceAcceleration = config.Base.surfaceGravity; gravityVolume._inheritable = false; diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index f76f54da..b2ffeff8 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -21,18 +21,47 @@ namespace NewHorizons.Builder.Props var dialogue = MakeConversationZone(go, sector, info, mod.ModHelper); RemoteDialogueTrigger remoteTrigger = null; - if (info.remoteTriggerPosition != null || info.remoteTriggerRadius != 0) remoteTrigger = MakeRemoteDialogueTrigger(go, sector, info, dialogue); + if (info.remoteTriggerPosition != null || info.remoteTriggerRadius != 0) + { + remoteTrigger = MakeRemoteDialogueTrigger(go, sector, info, dialogue); + } + + if (!string.IsNullOrEmpty(info.rename)) + { + dialogue.name = info.rename; + if (remoteTrigger != null) + { + remoteTrigger.name = $"{info.rename}_{remoteTrigger.name}"; + } + } + + if (!string.IsNullOrEmpty(info.parentPath)) + { + var parent = go.transform.Find(info.parentPath); + if (parent != null) + { + dialogue.transform.parent = parent; + if (remoteTrigger != null) + { + remoteTrigger.transform.parent = parent; + } + } + } // Make the character look at the player // Useful for dialogue replacement - if (!string.IsNullOrEmpty(info.pathToAnimController)) MakePlayerTrackingZone(go, dialogue, info); + // Overrides parent path for dialogue + if (!string.IsNullOrEmpty(info.pathToAnimController)) + { + MakePlayerTrackingZone(go, dialogue, info); + } return (dialogue, remoteTrigger); } private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, CharacterDialogueTree dialogue) { - GameObject conversationTrigger = new GameObject("ConversationTrigger"); + var conversationTrigger = new GameObject("ConversationTrigger"); conversationTrigger.SetActive(false); var remoteDialogueTrigger = conversationTrigger.AddComponent(); @@ -64,7 +93,7 @@ namespace NewHorizons.Builder.Props private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, IModHelper mod) { - GameObject conversationZone = new GameObject("ConversationZone"); + var conversationZone = new GameObject("ConversationZone"); conversationZone.SetActive(false); conversationZone.layer = LayerMask.NameToLayer("Interactible"); @@ -88,10 +117,11 @@ namespace NewHorizons.Builder.Props var dialogueTree = conversationZone.AddComponent(); var xml = File.ReadAllText(Path.Combine(mod.Manifest.ModFolderPath, info.xmlFile)); - var text = new TextAsset(xml); - - // Text assets need a name to be used with VoiceMod - text.name = Path.GetFileNameWithoutExtension(info.xmlFile); + var text = new TextAsset(xml) + { + // Text assets need a name to be used with VoiceMod + name = Path.GetFileNameWithoutExtension(info.xmlFile) + }; dialogueTree.SetTextXml(text); AddTranslation(xml); @@ -146,7 +176,7 @@ namespace NewHorizons.Builder.Props if (info.lookAtRadius > 0) { - GameObject playerTrackingZone = new GameObject("PlayerTrackingZone"); + var playerTrackingZone = new GameObject("PlayerTrackingZone"); playerTrackingZone.SetActive(false); playerTrackingZone.layer = LayerMask.NameToLayer("BasicEffectVolume"); @@ -194,22 +224,22 @@ namespace NewHorizons.Builder.Props private static void AddTranslation(string xml) { - XmlDocument xmlDocument = new XmlDocument(); + var xmlDocument = new XmlDocument(); xmlDocument.LoadXml(xml); - XmlNode xmlNode = xmlDocument.SelectSingleNode("DialogueTree"); - XmlNodeList xmlNodeList = xmlNode.SelectNodes("DialogueNode"); + var xmlNode = xmlDocument.SelectSingleNode("DialogueTree"); + var xmlNodeList = xmlNode.SelectNodes("DialogueNode"); string characterName = xmlNode.SelectSingleNode("NameField").InnerText; TranslationHandler.AddDialogue(characterName); foreach (object obj in xmlNodeList) { - XmlNode xmlNode2 = (XmlNode)obj; + var xmlNode2 = (XmlNode)obj; var name = xmlNode2.SelectSingleNode("Name").InnerText; - XmlNodeList xmlText = xmlNode2.SelectNodes("Dialogue/Page"); + var xmlText = xmlNode2.SelectNodes("Dialogue/Page"); foreach (object page in xmlText) { - XmlNode pageData = (XmlNode)page; + var pageData = (XmlNode)page; var text = pageData.InnerText; // The text is trimmed in DialogueText constructor (_listTextBlocks), so we also need to trim it for the key TranslationHandler.AddDialogue(text, true, name); @@ -218,7 +248,7 @@ namespace NewHorizons.Builder.Props xmlText = xmlNode2.SelectNodes("DialogueOptionsList/DialogueOption/Text"); foreach (object option in xmlText) { - XmlNode optionData = (XmlNode)option; + var optionData = (XmlNode)option; var text = optionData.InnerText; // The text is trimmed in CharacterDialogueTree.LoadXml, so we also need to trim it for the key TranslationHandler.AddDialogue(text, true, characterName, name); diff --git a/NewHorizons/Builder/Props/ProjectionBuilder.cs b/NewHorizons/Builder/Props/ProjectionBuilder.cs index f8d49b3a..eef9bbae 100644 --- a/NewHorizons/Builder/Props/ProjectionBuilder.cs +++ b/NewHorizons/Builder/Props/ProjectionBuilder.cs @@ -170,8 +170,7 @@ namespace NewHorizons.Builder.Props slideCollectionContainer.slideCollection = slideCollection; - // Idk why but it wants reveals to be comma delimited not a list - if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + LinkShipLogFacts(info, slideCollectionContainer); StreamingHandler.SetUpStreaming(slideReelObj, sector); @@ -284,8 +283,7 @@ namespace NewHorizons.Builder.Props target.slideCollection = g.AddComponent(); target.slideCollection._slideCollectionContainer = slideCollectionContainer; - // Idk why but it wants reveals to be comma delimited not a list - if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + LinkShipLogFacts(info, slideCollectionContainer); g.SetActive(true); @@ -370,7 +368,8 @@ namespace NewHorizons.Builder.Props var mindSlideCollection = standingTorch.AddComponent(); mindSlideCollection._slideCollectionContainer = slideCollectionContainer; - // Make sure that these slides play when the player wanders into the beam + LinkShipLogFacts(info, slideCollectionContainer); + mindSlideProjector.SetMindSlideCollection(mindSlideCollection); standingTorch.SetActive(true); @@ -450,6 +449,14 @@ namespace NewHorizons.Builder.Props Slide.WriteModules(modules, ref slide._modulesList, ref slide._modulesData, ref slide.lengths); } + + private static void LinkShipLogFacts(ProjectionInfo info, SlideCollectionContainer slideCollectionContainer) + { + // Idk why but it wants reveals to be comma delimited not a list + if (info.reveals != null) slideCollectionContainer._shipLogOnComplete = string.Join(",", info.reveals); + // Don't use null value, NRE in SlideCollectionContainer.Initialize + slideCollectionContainer._playWithShipLogFacts = info.playWithShipLogFacts ?? Array.Empty(); + } } public class VisionTorchTarget : MonoBehaviour diff --git a/NewHorizons/Builder/Volumes/PriorityVolumeBuilder.cs b/NewHorizons/Builder/Volumes/PriorityVolumeBuilder.cs new file mode 100644 index 00000000..13aeb430 --- /dev/null +++ b/NewHorizons/Builder/Volumes/PriorityVolumeBuilder.cs @@ -0,0 +1,17 @@ +using NewHorizons.External.Modules; +using UnityEngine; + +namespace NewHorizons.Builder.Volumes +{ + public static class PriorityVolumeBuilder + { + public static TVolume Make(GameObject planetGO, Sector sector, VolumesModule.PriorityVolumeInfo info) where TVolume : PriorityVolume + { + var volume = VolumeBuilder.Make(planetGO, sector, info); + + volume.SetPriority(info.priority); + + return volume; + } + } +} diff --git a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs index 9b13db4f..74815e13 100644 --- a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs +++ b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs @@ -78,6 +78,13 @@ namespace NewHorizons.Builder.Volumes VolumeBuilder.Make(go, sector, insulatingVolume); } } + if (config.Volumes.zeroGravityVolumes != null) + { + foreach (var zeroGravityVolume in config.Volumes.zeroGravityVolumes) + { + ZeroGVolumeBuilder.Make(go, sector, zeroGravityVolume); + } + } } } } diff --git a/NewHorizons/Builder/Volumes/ZeroGVolumeBuilder.cs b/NewHorizons/Builder/Volumes/ZeroGVolumeBuilder.cs new file mode 100644 index 00000000..931d1608 --- /dev/null +++ b/NewHorizons/Builder/Volumes/ZeroGVolumeBuilder.cs @@ -0,0 +1,17 @@ +using NewHorizons.External.Modules; +using UnityEngine; + +namespace NewHorizons.Builder.Volumes +{ + public static class ZeroGVolumeBuilder + { + public static ZeroGVolume Make(GameObject planetGO, Sector sector, VolumesModule.PriorityVolumeInfo info) + { + var volume = PriorityVolumeBuilder.Make(planetGO, sector, info); + + volume._inheritable = true; + + return volume; + } + } +} diff --git a/NewHorizons/External/Configs/PlanetConfig.cs b/NewHorizons/External/Configs/PlanetConfig.cs index c4558fee..259b53f5 100644 --- a/NewHorizons/External/Configs/PlanetConfig.cs +++ b/NewHorizons/External/Configs/PlanetConfig.cs @@ -415,6 +415,20 @@ namespace NewHorizons.External.Configs if (ring.curve != null) ring.scaleCurve = ring.curve; } } + + if (Base.zeroGravityRadius != 0f) + { + Volumes ??= new VolumesModule(); + Volumes.zeroGravityVolumes ??= new VolumesModule.PriorityVolumeInfo[0]; + + Volumes.zeroGravityVolumes = Volumes.zeroGravityVolumes.Append(new VolumesModule.PriorityVolumeInfo() + { + priority = 1, + rename = "ZeroGVolume", + radius = Base.zeroGravityRadius, + parentPath = "Volumes" + }).ToArray(); + } // So that old mods still have shock effects if (ShockEffect == null && Star == null && name != "Sun" && name != "EyeOfTheUniverse" && FocalPoint == null) diff --git a/NewHorizons/External/Modules/BaseModule.cs b/NewHorizons/External/Modules/BaseModule.cs index 2d434f66..338f3c05 100644 --- a/NewHorizons/External/Modules/BaseModule.cs +++ b/NewHorizons/External/Modules/BaseModule.cs @@ -82,9 +82,9 @@ namespace NewHorizons.External.Modules public float surfaceSize; /// - /// Radius of the zero gravity volume. This will make it so no gravity from any planet will affect you. Useful for satellites. + /// Optional. You can force this planet's gravity to be felt over other gravity/zero-gravity sources by increasing this number. /// - public float zeroGravityRadius; + public int gravityVolumePriority; #region Obsolete @@ -115,6 +115,9 @@ namespace NewHorizons.External.Modules [Obsolete("SphereOfInfluence is deprecated, please use soiOverride instead")] public float sphereOfInfluence; + [Obsolete("zeroGravityRadius is deprecated, please use Volumes->ZeroGravityVolumes instead")] + public float zeroGravityRadius; + #endregion Obsolete } } \ No newline at end of file diff --git a/NewHorizons/External/Modules/PropModule.cs b/NewHorizons/External/Modules/PropModule.cs index fa81ebf0..cdd7dc54 100644 --- a/NewHorizons/External/Modules/PropModule.cs +++ b/NewHorizons/External/Modules/PropModule.cs @@ -450,6 +450,16 @@ namespace NewHorizons.External.Modules /// Relative path to the xml file defining the dialogue. /// public string xmlFile; + + /// + /// Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix. + /// + public string rename; + + /// + /// Optionally set the parent object that the dialogue and remote trigger will be attached to + /// + public string parentPath; } [JsonObject] @@ -617,10 +627,18 @@ namespace NewHorizons.External.Modules public MVector3 position; /// - /// The ship log entries revealed after finishing this slide reel. + /// The ship log facts revealed after finishing this slide reel. /// public string[] reveals; + /// + /// The ship log facts that make the reel play when they are displayed in the computer (by selecting entries or arrows). + /// You should probably include facts from `reveals` here. + /// If you only specify a rumor fact, then it would only play in its ship log entry if this has revealed only + /// rumor facts because an entry with revealed explore facts doesn't display rumor facts. + /// + public string[] playWithShipLogFacts; + /// /// The rotation of this slideshow. /// @@ -712,7 +730,7 @@ namespace NewHorizons.External.Modules // SlideShipLogEntryModule /// - /// Ship log entry revealed when viewing this slide + /// Ship log fact revealed when viewing this slide /// public string reveal; diff --git a/NewHorizons/External/Modules/VolumesModule.cs b/NewHorizons/External/Modules/VolumesModule.cs index 9211f495..5791dd9a 100644 --- a/NewHorizons/External/Modules/VolumesModule.cs +++ b/NewHorizons/External/Modules/VolumesModule.cs @@ -55,6 +55,12 @@ namespace NewHorizons.External.Modules /// public VolumeInfo[] reverbVolumes; + /// + /// Add zero-gravity volumes to this planet. + /// Good for surrounding planets which are using a static position to stop the player being pulled away. + /// + public PriorityVolumeInfo[] zeroGravityVolumes; + [JsonObject] public class VolumeInfo { @@ -79,6 +85,17 @@ namespace NewHorizons.External.Modules public string rename; } + [JsonObject] + public class PriorityVolumeInfo : VolumeInfo + { + /// + /// The priority for this volume's effects to be applied. + /// Ex, a player in a gravity volume with priority 0, and zero-gravity volume with priority 1, will feel zero gravity. + /// + [DefaultValue(1)] + public int priority = 1; + } + [JsonObject] public class RevealVolumeInfo : VolumeInfo { diff --git a/NewHorizons/Schemas/body_schema.json b/NewHorizons/Schemas/body_schema.json index cbd0b20d..0c3bb8be 100644 --- a/NewHorizons/Schemas/body_schema.json +++ b/NewHorizons/Schemas/body_schema.json @@ -497,10 +497,10 @@ "description": "A scale height used for a number of things. Should be the approximate radius of the body.", "format": "float" }, - "zeroGravityRadius": { - "type": "number", - "description": "Radius of the zero gravity volume. This will make it so no gravity from any planet will affect you. Useful for satellites.", - "format": "float" + "gravityVolumePriority": { + "type": "integer", + "description": "Optional. You can force this planet's gravity to be felt over other gravity/zero-gravity sources by increasing this number.", + "format": "int32" } } }, @@ -1105,6 +1105,14 @@ "xmlFile": { "type": "string", "description": "Relative path to the xml file defining the dialogue." + }, + "rename": { + "type": "string", + "description": "Optionally rename the dialogue object. The remote trigger volume will be renamed to have this as a prefix." + }, + "parentPath": { + "type": "string", + "description": "Optionally set the parent object that the dialogue and remote trigger will be attached to" } } }, @@ -1425,7 +1433,14 @@ }, "reveals": { "type": "array", - "description": "The ship log entries revealed after finishing this slide reel.", + "description": "The ship log facts revealed after finishing this slide reel.", + "items": { + "type": "string" + } + }, + "playWithShipLogFacts": { + "type": "array", + "description": "The ship log facts that make the reel play when they are displayed in the computer (by selecting entries or arrows).\nYou should probably include facts from `reveals` here.\nIf you only specify a rumor fact, then it would only play in its ship log entry if this has revealed only\nrumor facts because an entry with revealed explore facts doesn't display rumor facts.", "items": { "type": "string" } @@ -1504,7 +1519,7 @@ }, "reveal": { "type": "string", - "description": "Ship log entry revealed when viewing this slide" + "description": "Ship log fact revealed when viewing this slide" }, "spotIntensityMod": { "type": "number", @@ -2473,6 +2488,13 @@ "items": { "$ref": "#/definitions/VolumeInfo" } + }, + "zeroGravityVolumes": { + "type": "array", + "description": "Add zero-gravity volumes to this planet. \nGood for surrounding planets which are using a static position to stop the player being pulled away.", + "items": { + "$ref": "#/definitions/PriorityVolumeInfo" + } } } }, @@ -2794,6 +2816,35 @@ "observe", "snapshot" ] + }, + "PriorityVolumeInfo": { + "type": "object", + "additionalProperties": false, + "properties": { + "position": { + "description": "The location of this volume. Optional (will default to 0,0,0).", + "$ref": "#/definitions/MVector3" + }, + "radius": { + "type": "number", + "description": "The radius of this volume.", + "format": "float" + }, + "parentPath": { + "type": "string", + "description": "The relative path from the planet to the parent of this object. Optional (will default to the root sector)." + }, + "rename": { + "type": "string", + "description": "An optional rename of this volume." + }, + "priority": { + "type": "integer", + "description": "The priority for this volume's effects to be applied. \nEx, a player in a gravity volume with priority 0, and zero-gravity volume with priority 1, will feel zero gravity.", + "format": "int32", + "default": 1 + } + } } }, "$docs": {