diff --git a/NewHorizons/Builder/Volumes/DayNightAudioVolumeBuilder.cs b/NewHorizons/Builder/Volumes/DayNightAudioVolumeBuilder.cs new file mode 100644 index 00000000..738f30f6 --- /dev/null +++ b/NewHorizons/Builder/Volumes/DayNightAudioVolumeBuilder.cs @@ -0,0 +1,36 @@ +using NewHorizons.Builder.Props; +using NewHorizons.Components.Volumes; +using NewHorizons.External.Modules.Volumes.VolumeInfos; +using NewHorizons.Utility.OuterWilds; +using OWML.Common; +using UnityEngine; + +namespace NewHorizons.Builder.Volumes +{ + public static class DayNightAudioVolumeBuilder + { + public static NHDayNightAudioVolume Make(GameObject planetGO, Sector sector, DayNightAudioVolumeInfo info, IModBehaviour mod) + { + var go = GeneralPropBuilder.MakeNew("DayNightAudioVolume", planetGO, sector, info); + go.layer = Layer.AdvancedEffectVolume; + + var audioVolume = go.AddComponent(); + audioVolume.sunName = info.sun; + audioVolume.dayWindow = info.dayWindow; + audioVolume.dayAudio = info.dayAudio; + audioVolume.nightAudio = info.nightAudio; + audioVolume.modBehaviour = mod; + audioVolume.volume = info.volume; + + var shape = go.AddComponent(); + shape.radius = info.radius; + + var owTriggerVolume = go.AddComponent(); + owTriggerVolume._shape = shape; + + go.SetActive(true); + + return audioVolume; + } + } +} diff --git a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs index 88cfc622..bdaa4a5a 100644 --- a/NewHorizons/Builder/Volumes/VolumesBuildManager.cs +++ b/NewHorizons/Builder/Volumes/VolumesBuildManager.cs @@ -35,6 +35,13 @@ namespace NewHorizons.Builder.Volumes AudioVolumeBuilder.Make(go, sector, audioVolume, mod); } } + if (config.Volumes.dayNightAudioVolumes != null) + { + foreach (var dayNightAudioVolume in config.Volumes.dayNightAudioVolumes) + { + DayNightAudioVolumeBuilder.Make(go, sector, dayNightAudioVolume, mod); + } + } if (config.Volumes.notificationVolumes != null) { foreach (var notificationVolume in config.Volumes.notificationVolumes) diff --git a/NewHorizons/Components/Volumes/NHDayNightAudioVolume.cs b/NewHorizons/Components/Volumes/NHDayNightAudioVolume.cs new file mode 100644 index 00000000..709c31d5 --- /dev/null +++ b/NewHorizons/Components/Volumes/NHDayNightAudioVolume.cs @@ -0,0 +1,142 @@ +using NewHorizons.Utility.Files; +using NewHorizons.Utility.OuterWilds; +using OWML.Common; +using UnityEngine; + +namespace NewHorizons.Components.Volumes +{ + public class NHDayNightAudioVolume : AudioVolume + { + public float dayWindow = 180f; + public string dayAudio; + public string nightAudio; + public string sunName; + public IModBehaviour modBehaviour; + public float volume; + + private OWAudioSource _daySource; + private OWAudioSource _nightSource; + + private Transform _planetTransform; + private Transform _sunTransform; + + private bool _wasDay; + + public override void Start() + { + _fadeSeconds = 2f; + + _planetTransform = gameObject.GetAttachedOWRigidbody().transform; + _sunTransform = AstroObjectLocator.GetAstroObject(sunName).GetAttachedOWRigidbody().transform; + + if (!string.IsNullOrEmpty(nightAudio)) + { + var nightGO = new GameObject("NightAudioSource"); + nightGO.transform.SetParent(transform); + nightGO.AddComponent(); + _nightSource = nightGO.AddComponent(); + } + + if (!string.IsNullOrEmpty(dayAudio)) + { + var dayGO = new GameObject("DayAudioSource"); + dayGO.transform.SetParent(transform); + dayGO.AddComponent(); + _daySource = dayGO.AddComponent(); + } + + enabled = false; + } + + public override void Init() + { + base.Init(); + + if (_daySource != null) + { + _daySource.Stop(); + _daySource.SetLocalVolume(0f); + + _daySource.rolloffMode = AudioRolloffMode.Custom; + _daySource.SetCustomCurve(AudioSourceCurveType.CustomRolloff, AnimationCurve.Linear(0f, 1f, 1f, 1f)); + _daySource.spatialBlend = 1f; + _daySource.spread = 180f; + _daySource.dopplerLevel = 0f; + _daySource.SetMaxVolume(volume); + AudioUtilities.SetAudioClip(_daySource, dayAudio, modBehaviour); + } + + if (_nightSource != null) + { + _nightSource.Stop(); + _nightSource.SetLocalVolume(0f); + + _nightSource.rolloffMode = AudioRolloffMode.Custom; + _nightSource.SetCustomCurve(AudioSourceCurveType.CustomRolloff, AnimationCurve.Linear(0f, 1f, 1f, 1f)); + _nightSource.spatialBlend = 1f; + _nightSource.spread = 180f; + _nightSource.dopplerLevel = 0f; + _nightSource.SetMaxVolume(volume); + AudioUtilities.SetAudioClip(_nightSource, nightAudio, modBehaviour); + } + } + + public override void Activate() + { + enabled = true; + _isActive = true; + UpdatePlayState(IsDay()); + } + + public override void Deactivate() + { + enabled = false; + _isActive = false; + + _daySource?.FadeOut(_fadeSeconds, _pauseOnFadeOut ? OWAudioSource.FadeOutCompleteAction.PAUSE : OWAudioSource.FadeOutCompleteAction.STOP, 0f); + _nightSource?.FadeOut(_fadeSeconds, _pauseOnFadeOut ? OWAudioSource.FadeOutCompleteAction.PAUSE : OWAudioSource.FadeOutCompleteAction.STOP, 0f); + } + + public void Update() + { + var isDay = IsDay(); + + if (isDay) + { + if (!_wasDay) + { + UpdatePlayState(isDay); + } + } + else if (_wasDay) + { + UpdatePlayState(isDay); + } + + _wasDay = isDay; + } + + private void UpdatePlayState(bool isDay) + { + if (!_initialized) + { + Init(); + } + if (isDay) + { + _daySource?.FadeIn(_fadeSeconds, false, _randomizePlayhead, 1f); + _nightSource?.FadeOut(_fadeSeconds, _pauseOnFadeOut ? OWAudioSource.FadeOutCompleteAction.PAUSE : OWAudioSource.FadeOutCompleteAction.STOP, 0f); + } + else + { + _daySource?.FadeOut(_fadeSeconds, _pauseOnFadeOut ? OWAudioSource.FadeOutCompleteAction.PAUSE : OWAudioSource.FadeOutCompleteAction.STOP, 0f); + _nightSource?.FadeIn(_fadeSeconds, false, _randomizePlayhead, 1f); + } + } + + private bool IsDay() + { + return Vector3.Angle(_planetTransform.position - Locator.GetPlayerTransform().position, Locator.GetPlayerTransform().position - _sunTransform.position) < dayWindow * 0.5f; + } + } +} diff --git a/NewHorizons/External/Modules/Volumes/VolumeInfos/DayNightAudioVolumeInfo.cs b/NewHorizons/External/Modules/Volumes/VolumeInfos/DayNightAudioVolumeInfo.cs new file mode 100644 index 00000000..25f71870 --- /dev/null +++ b/NewHorizons/External/Modules/Volumes/VolumeInfos/DayNightAudioVolumeInfo.cs @@ -0,0 +1,39 @@ +using Newtonsoft.Json; +using System.ComponentModel; +using System.ComponentModel.DataAnnotations; + +namespace NewHorizons.External.Modules.Volumes.VolumeInfos +{ + [JsonObject] + public class DayNightAudioVolumeInfo : PriorityVolumeInfo + { + /// + /// The audio to use during the day. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. Leave empty for no daytime audio. + /// + public string dayAudio; + + /// + /// The audio to use during the day. Can be a path to a .wav/.ogg/.mp3 file, or taken from the AudioClip list. Leave empty for no nightime audio. + /// + public string nightAudio; + + /// + /// The name of the astro object used to determine if it is day or night. + /// + public string sun; + + /// + /// Angle in degrees defining daytime. Inside this window it will be day and outside it will be night. + /// + [Range(0f, 360f)] + [DefaultValue(180f)] + public float dayWindow = 180f; + + /// + /// The loudness of the audio + /// + [Range(0f, 1f)] + [DefaultValue(1f)] + public float volume = 1f; + } +} diff --git a/NewHorizons/External/Modules/Volumes/VolumesModule.cs b/NewHorizons/External/Modules/Volumes/VolumesModule.cs index f11189d9..6e3afe19 100644 --- a/NewHorizons/External/Modules/Volumes/VolumesModule.cs +++ b/NewHorizons/External/Modules/Volumes/VolumesModule.cs @@ -11,6 +11,11 @@ namespace NewHorizons.External.Modules.Volumes /// public AudioVolumeInfo[] audioVolumes; + /// + /// Add day night audio volumes to this planet. These volumes play a different clip depending on the time of day. + /// + public DayNightAudioVolumeInfo[] dayNightAudioVolumes; + /// /// Add destruction volumes to this planet. /// Destroys bodies if they enter this volume. Can kill the player and recall the scout probe.