From 4a77631dbefdb86ca05bcae86993ba5a2647fa7b Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 13 Jul 2022 22:20:20 -0400 Subject: [PATCH 1/2] Add SpawnSignal and SpawnDialogue to the API --- NewHorizons/Builder/Props/DialogueBuilder.cs | 17 ++++-- NewHorizons/INewHorizons.cs | 54 +++++++++++++++++++- NewHorizons/NewHorizonsApi.cs | 45 +++++++++++++++- 3 files changed, 109 insertions(+), 7 deletions(-) diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index 1ff2f0d9..c6b57cb8 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -8,21 +8,26 @@ namespace NewHorizons.Builder.Props { public static class DialogueBuilder { - public static void Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModBehaviour mod) + // Returns the character dialogue tree and remote dialogue trigger, if applicable. + public static (CharacterDialogueTree, RemoteDialogueTrigger) Make(GameObject go, Sector sector, PropModule.DialogueInfo info, IModBehaviour mod) { // In stock I think they disable dialogue stuff with conditions // Here we just don't make it at all if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return; var dialogue = MakeConversationZone(go, sector, info, mod.ModHelper); - if (info.remoteTriggerPosition != null || info.remoteTriggerRadius != 0) MakeRemoteDialogueTrigger(go, sector, info, dialogue); + + RemoteDialogueTrigger remoteTrigger = null; + if (info.remoteTriggerPosition != null || info.remoteTriggerRadius != 0) remoteTrigger = MakeRemoteDialogueTrigger(go, sector, info, dialogue); // Make the character look at the player // Useful for dialogue replacement if (!string.IsNullOrEmpty(info.pathToAnimController)) MakePlayerTrackingZone(go, dialogue, info); + + return (dialogue, remoteTrigger); } - public static void MakeRemoteDialogueTrigger(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, CharacterDialogueTree dialogue) + private static RemoteDialogueTrigger MakeRemoteDialogueTrigger(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, CharacterDialogueTree dialogue) { GameObject conversationTrigger = new GameObject("ConversationTrigger"); conversationTrigger.SetActive(false); @@ -50,9 +55,11 @@ namespace NewHorizons.Builder.Props conversationTrigger.transform.parent = sector?.transform ?? planetGO.transform; conversationTrigger.transform.position = planetGO.transform.TransformPoint(info.remoteTriggerPosition ?? info.position); conversationTrigger.SetActive(true); + + return remoteDialogueTrigger; } - public static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, IModHelper mod) + private static CharacterDialogueTree MakeConversationZone(GameObject planetGO, Sector sector, PropModule.DialogueInfo info, IModHelper mod) { GameObject conversationZone = new GameObject("ConversationZone"); conversationZone.SetActive(false); @@ -99,7 +106,7 @@ namespace NewHorizons.Builder.Props return dialogueTree; } - public static void MakePlayerTrackingZone(GameObject go, CharacterDialogueTree dialogue, PropModule.DialogueInfo info) + private static void MakePlayerTrackingZone(GameObject go, CharacterDialogueTree dialogue, PropModule.DialogueInfo info) { var character = go.transform.Find(info.pathToAnimController); diff --git a/NewHorizons/INewHorizons.cs b/NewHorizons/INewHorizons.cs index fd10e7e6..7c647003 100644 --- a/NewHorizons/INewHorizons.cs +++ b/NewHorizons/INewHorizons.cs @@ -14,22 +14,74 @@ namespace NewHorizons [Obsolete("Create(Dictionary config) is deprecated, please use LoadConfigs(IModBehaviour mod) instead")] void Create(Dictionary config, IModBehaviour mod); + /// + /// Will load all configs in the regular folders (planets, systems, translations, etc) for this mod. + /// The NH addon config template is just a single call to this API method. + /// void LoadConfigs(IModBehaviour mod); + /// + /// Retrieve the root GameObject of a custom planet made by creating configs. + /// Will only work if the planet has been created (see GetStarSystemLoadedEvent) + /// GameObject GetPlanet(string name); + /// + /// The name of the current star system loaded. + /// string GetCurrentStarSystem(); + /// + /// An event invoked when the player begins loading the new star system, before the scene starts to load. + /// Gives the name of the star system being switched to. + /// UnityEvent GetChangeStarSystemEvent(); + /// + /// An event invoked when NH has finished generating all planets for a new star system. + /// Gives the name of the star system that was just loaded. + /// UnityEvent GetStarSystemLoadedEvent(); + /// + /// Allows you to overwrite the default system. This is where the player is respawned after dying. + /// bool SetDefaultSystem(string name); + /// + /// Allows you to instantly begin a warp to a new star system. + /// Will return false if that system does not exist (cannot be warped to). + /// bool ChangeCurrentStarSystem(string name); + /// + /// Returns the uniqueIDs of each installed NH addon. + /// string[] GetInstalledAddons(); - GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignWithNormal); + /// + /// Allows you to spawn a copy of a prop by specifying its path. + /// This is the same as using Props->details in a config, but also returns the spawned gameObject to you. + /// + GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, + float scale, bool alignWithNormal); + + /// + /// Allows you to spawn an AudioSignal on a planet. + /// This is the same as using Props->signals in a config, but also returns the spawned AudioSignal to you. + /// This method will not set its position. You will have to do that with the returned object. + /// + AudioSignal SpawnSignal(IModBehaviour mod, GameObject root, string audio, string name, string frequency, + float sourceRadius = 1f, float detectionRadius = 20f, float identificationRadius = 10f, bool insideCloak = false, + bool onlyAudibleToScope = true, string reveals = ""); + + /// + /// Allows you to spawn character dialogue on a planet. Also returns the RemoteDialogueTrigger if remoteTriggerRadius is specified. + /// This is the same as using Props->dialogue in a config, but also returns the spawned game objects to you. + /// This method will not set the position of the dialogue or remote trigger. You will have to do that with the returned objects. + /// + (CharacterDialogueTree, RemoteDialogueTrigger) SpawnDialogue(IModBehaviour mod, GameObject root, string xmlFile, float radius = 1f, + float range = 1f, string blockAfterPersistentCondition = null, float lookAtRadius = 1f, string pathToAnimController = null, + float remoteTriggerRadius = 0f); } } diff --git a/NewHorizons/NewHorizonsApi.cs b/NewHorizons/NewHorizonsApi.cs index 191d87dd..eadeecbc 100644 --- a/NewHorizons/NewHorizonsApi.cs +++ b/NewHorizons/NewHorizonsApi.cs @@ -1,4 +1,5 @@ using NewHorizons.Builder.Props; +using NewHorizons.External.Modules; using NewHorizons.Utility; using OWML.Common; using OWML.Utils; @@ -107,9 +108,51 @@ namespace NewHorizons } } - public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, float scale, bool alignWithNormal) + public GameObject SpawnObject(GameObject planet, Sector sector, string propToCopyPath, Vector3 position, Vector3 eulerAngles, + float scale, bool alignWithNormal) { return DetailBuilder.MakeDetail(planet, sector, propToCopyPath, position, eulerAngles, scale, alignWithNormal); } + + public AudioSignal SpawnSignal(IModBehaviour mod, GameObject root, string audio, string name, string frequency, + float sourceRadius = 1f, float detectionRadius = 20f, float identificationRadius = 10f, bool insideCloak = false, + bool onlyAudibleToScope = true, string reveals = "") + { + var info = new SignalModule.SignalInfo() + { + audio = audio, + detectionRadius = detectionRadius, + frequency = frequency, + identificationRadius = identificationRadius, + insideCloak = insideCloak, + name = name, + onlyAudibleToScope = onlyAudibleToScope, + position = MVector3.zero, + reveals = reveals, + sourceRadius = sourceRadius + }; + + return SignalBuilder.Make(root, null, info, mod).GetComponent(); + } + + public (CharacterDialogueTree, RemoteDialogueTrigger) SpawnDialogue(IModBehaviour mod, GameObject root, string xmlFile, float radius = 1f, + float range = 1f, string blockAfterPersistentCondition = null, float lookAtRadius = 1f, string pathToAnimController = null, + float remoteTriggerRadius = 0f) + { + var info = new PropModule.DialogueInfo() + { + blockAfterPersistentCondition = blockAfterPersistentCondition, + lookAtRadius = lookAtRadius, + pathToAnimController = pathToAnimController, + position = Vector3.zero, + radius = radius, + remoteTriggerPosition = null, + range = range, + remoteTriggerRadius = remoteTriggerRadius, + xmlFile = xmlFile + }; + + return DialogueBuilder.Make(root, null, info, mod); + } } } From 79cff0645cc468fdb42dd17c4ce1a40f6ab47a2b Mon Sep 17 00:00:00 2001 From: Nick Date: Wed, 13 Jul 2022 22:26:14 -0400 Subject: [PATCH 2/2] Oops. --- NewHorizons/Builder/Props/DialogueBuilder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NewHorizons/Builder/Props/DialogueBuilder.cs b/NewHorizons/Builder/Props/DialogueBuilder.cs index c6b57cb8..e2d2cf6f 100644 --- a/NewHorizons/Builder/Props/DialogueBuilder.cs +++ b/NewHorizons/Builder/Props/DialogueBuilder.cs @@ -13,7 +13,7 @@ namespace NewHorizons.Builder.Props { // In stock I think they disable dialogue stuff with conditions // Here we just don't make it at all - if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return; + if (info.blockAfterPersistentCondition != null && PlayerData._currentGameSave.GetPersistentCondition(info.blockAfterPersistentCondition)) return (null, null); var dialogue = MakeConversationZone(go, sector, info, mod.ModHelper);