mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
252 lines
9.8 KiB
C#
252 lines
9.8 KiB
C#
#region
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using NewHorizons.Components;
|
|
using NewHorizons.External.Modules;
|
|
using NewHorizons.Utility;
|
|
using OWML.Common;
|
|
using UnityEngine;
|
|
using Logger = NewHorizons.Utility.Logger;
|
|
using Object = UnityEngine.Object;
|
|
|
|
#endregion
|
|
|
|
namespace NewHorizons.Builder.Props
|
|
{
|
|
public static class SignalBuilder
|
|
{
|
|
private static AnimationCurve _customCurve;
|
|
|
|
private static Dictionary<SignalName, string> _customSignalNames;
|
|
private static Stack<SignalName> _availableSignalNames;
|
|
private static int _nextCustomSignalName;
|
|
|
|
private static Dictionary<SignalFrequency, string> _customFrequencyNames;
|
|
private static int _nextCustomFrequencyName;
|
|
|
|
public static int NumberOfFrequencies;
|
|
|
|
public static void Init()
|
|
{
|
|
Logger.Log("Initializing SignalBuilder");
|
|
_customSignalNames = new Dictionary<SignalName, string>();
|
|
_availableSignalNames = new Stack<SignalName>(new[]
|
|
{
|
|
(SignalName) 17,
|
|
(SignalName) 18,
|
|
(SignalName) 19,
|
|
(SignalName) 26,
|
|
(SignalName) 27,
|
|
(SignalName) 28,
|
|
(SignalName) 29,
|
|
(SignalName) 33,
|
|
(SignalName) 34,
|
|
(SignalName) 35,
|
|
(SignalName) 36,
|
|
(SignalName) 37,
|
|
(SignalName) 38,
|
|
(SignalName) 39,
|
|
(SignalName) 50,
|
|
(SignalName) 51,
|
|
(SignalName) 52,
|
|
(SignalName) 53,
|
|
(SignalName) 54,
|
|
(SignalName) 55,
|
|
(SignalName) 56,
|
|
(SignalName) 57,
|
|
(SignalName) 58,
|
|
(SignalName) 59,
|
|
SignalName.WhiteHole_WH,
|
|
SignalName.WhiteHole_SS_Receiver,
|
|
SignalName.WhiteHole_CT_Receiver,
|
|
SignalName.WhiteHole_CT_Experiment,
|
|
SignalName.WhiteHole_TT_Receiver,
|
|
SignalName.WhiteHole_TT_TimeLoopCore,
|
|
SignalName.WhiteHole_TH_Receiver,
|
|
SignalName.WhiteHole_BH_NorthPoleReceiver,
|
|
SignalName.WhiteHole_BH_ForgeReceiver,
|
|
SignalName.WhiteHole_GD_Receiver
|
|
});
|
|
_customFrequencyNames = new Dictionary<SignalFrequency, string>
|
|
{
|
|
{SignalFrequency.Statue, "FREQ_STATUE"},
|
|
{SignalFrequency.Default, "FREQ_UNKNOWN"},
|
|
{SignalFrequency.WarpCore, "FREQ_WARP_CORE"}
|
|
};
|
|
_nextCustomSignalName = 200;
|
|
_nextCustomFrequencyName = 256;
|
|
NumberOfFrequencies = 8;
|
|
}
|
|
|
|
public static SignalFrequency AddFrequency(string str)
|
|
{
|
|
Logger.Log($"Registering new frequency name [{str}]");
|
|
|
|
if (NumberOfFrequencies == 31)
|
|
{
|
|
Logger.LogWarning($"Can't store any more frequencies, skipping [{str}]");
|
|
return SignalFrequency.Default;
|
|
}
|
|
|
|
var freq = CollectionUtilities.KeyByValue(_customFrequencyNames, str);
|
|
if (freq != default) return freq;
|
|
|
|
freq = (SignalFrequency) _nextCustomFrequencyName;
|
|
_nextCustomFrequencyName *= 2;
|
|
_customFrequencyNames.Add(freq, str);
|
|
|
|
NumberOfFrequencies++;
|
|
|
|
// This stuff happens after the signalscope is Awake so we have to change the number of frequencies now
|
|
Object.FindObjectOfType<Signalscope>()._strongestSignals = new AudioSignal[NumberOfFrequencies + 1];
|
|
|
|
return freq;
|
|
}
|
|
|
|
public static string GetCustomFrequencyName(SignalFrequency frequencyName)
|
|
{
|
|
_customFrequencyNames.TryGetValue(frequencyName, out var name);
|
|
return name;
|
|
}
|
|
|
|
public static SignalName AddSignalName(string str)
|
|
{
|
|
Logger.Log($"Registering new signal name [{str}]");
|
|
SignalName newName;
|
|
|
|
if (_availableSignalNames.Count == 0) newName = (SignalName) _nextCustomSignalName++;
|
|
else newName = _availableSignalNames.Pop();
|
|
|
|
_customSignalNames.Add(newName, str);
|
|
return newName;
|
|
}
|
|
|
|
public static string GetCustomSignalName(SignalName signalName)
|
|
{
|
|
_customSignalNames.TryGetValue(signalName, out var name);
|
|
return name;
|
|
}
|
|
|
|
public static void Make(GameObject body, Sector sector, SignalModule module, IModBehaviour mod)
|
|
{
|
|
foreach (var info in module.signals) Make(body, sector, info, mod);
|
|
}
|
|
|
|
public static void Make(GameObject planetGO, Sector sector, SignalModule.SignalInfo info, IModBehaviour mod)
|
|
{
|
|
var signalGO = new GameObject($"Signal_{info.name}");
|
|
signalGO.SetActive(false);
|
|
signalGO.transform.parent = sector?.transform ?? planetGO.transform;
|
|
signalGO.transform.position =
|
|
planetGO.transform.TransformPoint(info.position != null ? (Vector3) info.position : Vector3.zero);
|
|
signalGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume");
|
|
|
|
var source = signalGO.AddComponent<AudioSource>();
|
|
var owAudioSource = signalGO.AddComponent<OWAudioSource>();
|
|
owAudioSource._audioSource = source;
|
|
|
|
AudioSignal audioSignal;
|
|
if (info.insideCloak) audioSignal = signalGO.AddComponent<CloakedAudioSignal>();
|
|
else audioSignal = signalGO.AddComponent<AudioSignal>();
|
|
audioSignal._owAudioSource = owAudioSource;
|
|
|
|
var frequency = StringToFrequency(info.frequency);
|
|
var name = StringToSignalName(info.name);
|
|
|
|
AudioClip clip = null;
|
|
if (info.audioClip != null) clip = SearchUtilities.FindResourceOfTypeAndName<AudioClip>(info.audioClip);
|
|
else if (info.audioFilePath != null)
|
|
try
|
|
{
|
|
clip = AudioUtilities.LoadAudio(mod.ModHelper.Manifest.ModFolderPath + "/" + info.audioFilePath);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Logger.LogError($"Couldn't load audio file {info.audioFilePath} : {e.Message}");
|
|
}
|
|
|
|
if (clip == null)
|
|
{
|
|
Logger.LogError($"Couldn't find AudioClip {info.audioClip} or AudioFile {info.audioFilePath}");
|
|
return;
|
|
}
|
|
|
|
audioSignal.SetSector(sector);
|
|
|
|
if (name == SignalName.Default) audioSignal._preventIdentification = true;
|
|
|
|
audioSignal._frequency = frequency;
|
|
audioSignal._name = name;
|
|
audioSignal._sourceRadius = info.sourceRadius;
|
|
audioSignal._revealFactID = info.reveals;
|
|
audioSignal._onlyAudibleToScope = info.onlyAudibleToScope;
|
|
audioSignal._identificationDistance = info.identificationRadius;
|
|
audioSignal._canBePickedUpByScope = true;
|
|
|
|
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<AudioSource>().GetCustomCurve(AudioSourceCurveType.CustomRolloff);
|
|
|
|
source.SetCustomCurve(AudioSourceCurveType.CustomRolloff, _customCurve);
|
|
// If it can be heard regularly then we play it immediately
|
|
source.playOnAwake = !info.onlyAudibleToScope;
|
|
source.spatialBlend = 1f;
|
|
source.volume = 0.5f;
|
|
source.dopplerLevel = 0;
|
|
|
|
owAudioSource.SetTrack(OWAudioMixer.TrackName.Signal);
|
|
|
|
// Frequency detection trigger volume
|
|
|
|
var signalDetectionGO = new GameObject($"SignalDetectionTrigger_{info.name}");
|
|
signalDetectionGO.SetActive(false);
|
|
signalDetectionGO.transform.parent = sector?.transform ?? planetGO.transform;
|
|
signalDetectionGO.transform.position =
|
|
planetGO.transform.TransformPoint(info.position != null ? (Vector3) info.position : Vector3.zero);
|
|
signalDetectionGO.layer = LayerMask.NameToLayer("AdvancedEffectVolume");
|
|
|
|
var sphereShape = signalDetectionGO.AddComponent<SphereShape>();
|
|
var owTriggerVolume = signalDetectionGO.AddComponent<OWTriggerVolume>();
|
|
var audioSignalDetectionTrigger = signalDetectionGO.AddComponent<AudioSignalDetectionTrigger>();
|
|
|
|
sphereShape.radius = info.detectionRadius == 0 ? info.sourceRadius + 30 : info.detectionRadius;
|
|
audioSignalDetectionTrigger._signal = audioSignal;
|
|
audioSignalDetectionTrigger._trigger = owTriggerVolume;
|
|
|
|
signalGO.SetActive(true);
|
|
signalDetectionGO.SetActive(true);
|
|
}
|
|
|
|
private static SignalFrequency StringToFrequency(string str)
|
|
{
|
|
foreach (SignalFrequency freq in Enum.GetValues(typeof(SignalFrequency)))
|
|
if (str.Equals(freq.ToString()))
|
|
return freq;
|
|
var customName = CollectionUtilities.KeyByValue(_customFrequencyNames, str);
|
|
|
|
if (customName == default) customName = AddFrequency(str);
|
|
|
|
return customName;
|
|
}
|
|
|
|
private static SignalName StringToSignalName(string str)
|
|
{
|
|
foreach (SignalName name in Enum.GetValues(typeof(SignalName)))
|
|
if (str.Equals(name.ToString()))
|
|
return name;
|
|
var customName = CollectionUtilities.KeyByValue(_customSignalNames, str);
|
|
if (customName == default) customName = AddSignalName(str);
|
|
|
|
return customName;
|
|
}
|
|
}
|
|
} |