diff --git a/NewHorizons/Builder/Props/SignalBuilder.cs b/NewHorizons/Builder/Props/SignalBuilder.cs new file mode 100644 index 00000000..193cede2 --- /dev/null +++ b/NewHorizons/Builder/Props/SignalBuilder.cs @@ -0,0 +1,146 @@ +using NewHorizons.External; +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Logger = NewHorizons.Utility.Logger; + +namespace NewHorizons.Builder.Props +{ + public static class SignalBuilder + { + private static AnimationCurve _customCurve = null; + + private static Dictionary _customSignalNames; + private static Stack _availableSignalNames; + + public static void Reset() + { + _customSignalNames = new Dictionary(); + _availableSignalNames = new Stack (new int[] + { + 17, + 18, + 19, + 26, + 27, + 28, + 29, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59 + }); + } + + public static SignalName AddSignalName(string str) + { + if (_availableSignalNames.Count == 0) + { + Logger.LogWarning($"There are no more available SignalName spots. Cannot use name [{str}]."); + return SignalName.Default; + } + + Logger.Log($"Registering new signal name [{str}]"); + var newName = (SignalName)_availableSignalNames.Pop(); + _customSignalNames.Add(newName, str.ToUpper()); + return newName; + } + + public static string GetCustomSignalName(SignalName signalName) + { + if (_customSignalNames.ContainsKey(signalName)) return _customSignalNames[signalName]; + return null; + } + + public static void Make(GameObject body, Sector sector, SignalModule module) + { + foreach(var info in module.Signals) + { + Make(body, sector, info); + } + } + + public static void Make(GameObject body, Sector sector, SignalModule.SignalInfo info) + { + var signalGO = new GameObject($"Signal_{info.Name}"); + signalGO.SetActive(false); + signalGO.transform.parent = sector.transform; + signalGO.transform.localPosition = info.Position != null ? (Vector3)info.Position : Vector3.zero; + + var source = signalGO.AddComponent(); + var owAudioSource = signalGO.AddComponent(); + var audioSignal = signalGO.AddComponent(); + + var frequency = StringToFrequency(info.Frequency); + var name = StringToSignalName(info.Name); + + AudioClip clip = SearchUtilities.FindResourceOfTypeAndName(info.AudioClip); + if (clip == null) return; + + audioSignal.SetSector(sector); + audioSignal._frequency = frequency; + if (name == SignalName.Default) + { + name = AddSignalName(info.Name); + if(name == SignalName.Default) audioSignal._preventIdentification = true; + } + audioSignal._name = name; + audioSignal._sourceRadius = info.SourceRadius; + audioSignal._onlyAudibleToScope = info.OnlyAudibleToScope; + + source.clip = clip; + source.loop = true; + source.minDistance = 0; + source.maxDistance = 30; + source.velocityUpdateMode = AudioVelocityUpdateMode.Fixed; + source.rolloffMode = AudioRolloffMode.Custom; + + if(_customCurve == null) + _customCurve = GameObject.Find("Moon_Body/Sector_THM/Characters_THM/Villager_HEA_Esker/Signal_Whistling").GetComponent().GetCustomCurve(AudioSourceCurveType.CustomRolloff); + + source.SetCustomCurve(AudioSourceCurveType.CustomRolloff, _customCurve); + source.playOnAwake = false; + source.spatialBlend = 1f; + source.volume = 0.5f; + + owAudioSource.SetTrack(OWAudioMixer.TrackName.Signal); + + signalGO.SetActive(true); + } + + private static SignalFrequency StringToFrequency(string str) + { + foreach(SignalFrequency freq in Enum.GetValues(typeof(SignalFrequency))) + { + if (str.Equals(freq.ToString())) return freq; + } + return SignalFrequency.Default; + } + + private static SignalName StringToSignalName(string str) + { + foreach (SignalName name in Enum.GetValues(typeof(SignalName))) + { + if (str.Equals(name.ToString())) return name; + } + return SignalName.Default; + } + } +} diff --git a/NewHorizons/External/IPlanetConfig.cs b/NewHorizons/External/IPlanetConfig.cs index d03c1318..5f726a2a 100644 --- a/NewHorizons/External/IPlanetConfig.cs +++ b/NewHorizons/External/IPlanetConfig.cs @@ -18,5 +18,6 @@ namespace NewHorizons.External FocalPointModule FocalPoint { get; } PropModule Props { get; } SpawnModule Spawn { get; } + SignalModule Signal { get; } } } diff --git a/NewHorizons/External/PlanetConfig.cs b/NewHorizons/External/PlanetConfig.cs index 8d4e37d6..1cefbd2f 100644 --- a/NewHorizons/External/PlanetConfig.cs +++ b/NewHorizons/External/PlanetConfig.cs @@ -22,6 +22,7 @@ namespace NewHorizons.External public FocalPointModule FocalPoint { get; set; } public PropModule Props { get; set; } public SpawnModule Spawn { get; set; } + public SignalModule Signal { get; set; } public PlanetConfig(Dictionary dict) { diff --git a/NewHorizons/External/SignalModule.cs b/NewHorizons/External/SignalModule.cs new file mode 100644 index 00000000..b7c1d2f9 --- /dev/null +++ b/NewHorizons/External/SignalModule.cs @@ -0,0 +1,24 @@ +using NewHorizons.Utility; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace NewHorizons.External +{ + public class SignalModule : Module + { + public SignalInfo[] Signals; + + public class SignalInfo + { + public MVector3 Position; + public string Frequency; + public string Name; + public string AudioClip; + public float SourceRadius = 1f; + public bool OnlyAudibleToScope = true; + } + } +} diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 05654428..aa4cc78e 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -101,6 +101,10 @@ namespace NewHorizons // TODO: Make this configurable probably Instance.ModHelper.Events.Unity.FireOnNextUpdate(() => Locator.GetPlayerBody().gameObject.AddComponent()); + // Some builders need to be reset each time + SignalBuilder.Reset(); + + // We do our own AstroObject tracking AstroObjectLocator.RefreshList(); foreach (AstroObject ao in GameObject.FindObjectsOfType()) { @@ -312,6 +316,9 @@ namespace NewHorizons if (body.Config.FocalPoint != null) FocalPointBuilder.Make(go, body.Config.FocalPoint); + if (body.Config.Signal != null) + SignalBuilder.Make(go, sector, body.Config.Signal); + // Do stuff that's shared between generating new planets and updating old ones go = SharedGenerateBody(body, go, sector, owRigidBody, ao); diff --git a/NewHorizons/NewHorizons.csproj b/NewHorizons/NewHorizons.csproj index 486ddf83..d5d94965 100644 --- a/NewHorizons/NewHorizons.csproj +++ b/NewHorizons/NewHorizons.csproj @@ -30,4 +30,7 @@ + + + \ No newline at end of file diff --git a/NewHorizons/Utility/Patches.cs b/NewHorizons/Utility/Patches.cs index ece09eb6..dfdbb8f1 100644 --- a/NewHorizons/Utility/Patches.cs +++ b/NewHorizons/Utility/Patches.cs @@ -1,4 +1,5 @@ -using OWML.Common; +using NewHorizons.Builder.Props; +using OWML.Common; using System; using System.Collections.Generic; using System.Linq; @@ -17,6 +18,7 @@ namespace NewHorizons.Utility Main.Instance.ModHelper.HarmonyHelper.AddPrefix("CheckShipOutsideSolarSystem", typeof(Patches), nameof(Patches.CheckShipOutersideSolarSystem)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("LateUpdate", typeof(Patches), nameof(Patches.OnSunLightParamUpdaterLateUpdate)); Main.Instance.ModHelper.HarmonyHelper.AddPrefix("Update", typeof(Patches), nameof(Patches.OnSunSurfaceAudioControllerUpdate)); + Main.Instance.ModHelper.HarmonyHelper.AddPrefix("SignalNameToString", typeof(Patches), nameof(Patches.OnAudioSignalSignalNameToString)); // Postfixes Main.Instance.ModHelper.HarmonyHelper.AddPostfix("Start", typeof(Patches), nameof(Patches.OnEllipticOrbitLineStart)); @@ -93,5 +95,47 @@ namespace NewHorizons.Utility __instance._audioSource.SetLocalVolume(num * num * __instance._fade); return false; } + + public static bool OnAudioSignalSignalNameToString(SignalName __0, ref string __result) + { + switch(__0) + { + case SignalName.WhiteHole_SS_Receiver: + __result = "Sun Station Receiver"; + return false; + case SignalName.WhiteHole_CT_Receiver: + __result = "Ember Twin Receiver"; + return false; + case SignalName.WhiteHole_CT_Experiment: + __result = "White Hole Receiver"; + return false; + case SignalName.WhiteHole_TT_Receiver: + __result = "Ash Twin Receiver"; + return false; + case SignalName.WhiteHole_TT_TimeLoopCore: + __result = "Ash Twin Project"; + return false; + case SignalName.WhiteHole_TH_Receiver: + __result = "Timber Hearth Receiver"; + return false; + case SignalName.WhiteHole_BH_NorthPoleReceiver: + __result = "North Pole Receiver"; + return false; + case SignalName.WhiteHole_BH_ForgeReceiver: + __result = "Black Hole Forge Receiver"; + return false; + case SignalName.WhiteHole_GD_Receiver: + __result = "Giant's Deep Receiver"; + return false; + default: + var customSignalName = SignalBuilder.GetCustomSignalName(__0); + if (customSignalName == null) return true; + else + { + __result = customSignalName; + return false; + } + } + } } } diff --git a/NewHorizons/Utility/SearchUtilities.cs b/NewHorizons/Utility/SearchUtilities.cs new file mode 100644 index 00000000..a211fba9 --- /dev/null +++ b/NewHorizons/Utility/SearchUtilities.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using UnityEngine; +using Object = UnityEngine.Object; + +namespace NewHorizons.Utility +{ + public static class SearchUtilities + { + public static List FindObjectsOfTypeAndName(string name) where T : MonoBehaviour + { + T[] firstList = GameObject.FindObjectsOfType(); + List finalList = new List(); + + for (var i = 0; i < firstList.Length; i++) + { + if (firstList[i].name == name) + { + finalList.Add(firstList[i]); + } + } + + return finalList; + } + + public static List FindResourcesOfTypeAndName(string name) where T : Object + { + T[] firstList = Resources.FindObjectsOfTypeAll(); + List finalList = new List(); + + for (var i = 0; i < firstList.Length; i++) + { + if (firstList[i].name == name) + { + finalList.Add(firstList[i]); + } + } + + return finalList; + } + + public static T FindResourceOfTypeAndName(string name) where T : Object + { + T[] firstList = Resources.FindObjectsOfTypeAll(); + + for (var i = 0; i < firstList.Length; i++) + { + if (firstList[i].name == name) + { + return firstList[i]; + } + } + + return null; + } + } +}