Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of VepMod v1.0.5
VepMod.dll
Decompiled a month ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using Photon.Voice; using REPOLib.Objects.Sdk; using TMPro; using Unity.VisualScripting; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations; using UnityEngine.SceneManagement; using UnityEngine.UI; using VepMod.Enemies.Whispral; using VepMod.Patchs; using VepMod.VepFramework; using VepMod.VepFramework.Config; using VepMod.VepFramework.Extensions; using VepMod.VepFramework.Structures.FSM; using VepMod.VepFramework.Structures.Range; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("Vep")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a4c9ac5b8867faa31a7edfa23afd8d10bf82abcf")] [assembly: AssemblyProduct("VepMod")] [assembly: AssemblyTitle("VepMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace VepMod { public static class ConfigRanges { public static readonly RangeValue<float> Volume = RangeValue.Percentage(); public static readonly RangeValue<int> SamplesPerPlayer = RangeValue.Int(5, 20, 20); public static readonly RangeValue<int> SamplingRate = RangeValue.Int(16000, 48000, 48000); public static readonly MinMaxRange<float> ShareDelay = MinMaxRange.Float(10f, 60f, 10f, 10f, 120f, 30f); public static readonly MinMaxRange<float> VoiceDelay = MinMaxRange.Float(6f, 30f, 8f, 6f, 30f, 15f); } [BepInPlugin("com.vep.vepMod", "VepMod", "1.0.5")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class VepMod : BaseUnityPlugin { private static Harmony _harmony; public static ConfigEntry<float> ConfigVoiceVolume; public static ConfigEntry<int> ConfigSamplingRate; public static BoundMinMaxRange<float> ShareDelay; public static ConfigEntry<int> ConfigSamplesPerPlayer; public static BoundMinMaxRange<float> VoiceDelay; public static ConfigEntry<bool> ConfigVoiceFilterEnabled; public static readonly Dictionary<string, ConfigEntry<bool>> EnemyConfigEntries = new Dictionary<string, ConfigEntry<bool>>(); internal Harmony? Harmony { get; set; } private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Expected O, but got Unknown _harmony = new Harmony("VepMod.Plugin"); PreventDelete(); InitConfig(); _harmony.PatchAll(); ((BaseUnityPlugin)this).Logger.LogInfo((object)$"{((BaseUnityPlugin)this).Info.Metadata.GUID} v{((BaseUnityPlugin)this).Info.Metadata.Version} has loaded!"); ((MonoBehaviour)this).StartCoroutine(DroidPrefabLoader.PreloadAsync(delegate(bool success) { if (success) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"LostDroid prefab preloaded successfully."); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"LostDroid prefab preload failed - hallucinations may not work."); } })); } public void OnSceneLoaded(Scene scene, LoadSceneMode mode) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("Scene loaded: " + ((Scene)(ref scene)).name)); } private void InitConfig() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown ((BaseUnityPlugin)this).Logger.LogInfo((object)"Initializing config for VepMod..."); ConfigVoiceVolume = ((BaseUnityPlugin)this).Config.BindRange("General", "Volume", ConfigRanges.Volume, "Volume of the mimic voices."); ShareDelay = ((BaseUnityPlugin)this).Config.BindMinMax("Audio Sharing", "Share Min Delay", "Share Max Delay", ConfigRanges.ShareDelay, "Minimum time between sharing audio clips with other players.", "Maximum time between sharing audio clips with other players."); ConfigSamplesPerPlayer = ((BaseUnityPlugin)this).Config.BindRange("Audio Sharing", "Samples Per Player", ConfigRanges.SamplesPerPlayer, "Maximum number of audio samples stored per player."); VoiceDelay = ((BaseUnityPlugin)this).Config.BindMinMax("Voice Playback", "Voice Min Delay", "Voice Max Delay", ConfigRanges.VoiceDelay, "Minimum time between voice playback commands during Whispral debuff.", "Maximum time between voice playback commands during Whispral debuff."); ConfigVoiceFilterEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Voice Playback", "Voice Filter Enabled?", false, new ConfigDescription("Turning this will enable modifiable filters for which enemies can play back voices during the Whispral debuff.", (AcceptableValueBase)null, Array.Empty<object>())); ConfigSamplingRate = ((BaseUnityPlugin)this).Config.BindRange("Experimental", "Sampling Rate", ConfigRanges.SamplingRate, "Only change this value if the console gives you a warning about your microphone frequency not being supported."); } private void PreventDelete() { ((Component)this).gameObject.transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; } internal void Unpatch() { _harmony.UnpatchSelf(); } } } namespace VepMod.VepFramework { public sealed class VepLogger { private const string Prefix = "VepMod"; private readonly ManualLogSource _log; public bool DebugEnabled { get; set; } private VepLogger(string className, bool debugEnabled = false) { _log = Logger.CreateLogSource("VepMod." + className); DebugEnabled = debugEnabled; } public static VepLogger Create<T>(bool debugEnabled = false) { return new VepLogger(typeof(T).Name, debugEnabled); } public static VepLogger Create(string className, bool debugEnabled = false) { return new VepLogger(className, debugEnabled); } public void Debug(string message) { if (DebugEnabled) { _log.LogDebug((object)message); } } public void Info(string message) { _log.LogInfo((object)message); } public void Warning(string message) { _log.LogWarning((object)message); } public void Error(string message) { _log.LogError((object)message); } } } namespace VepMod.VepFramework.Structures.Range { public sealed class MinMaxRange<T> where T : struct, IComparable<T> { public RangeValue<T> MinRange { get; } public RangeValue<T> MaxRange { get; } public MinMaxRange(RangeValue<T> minRange, RangeValue<T> maxRange) { MinRange = minRange; MaxRange = maxRange; } public T GetMin(T minValue, T maxValue) { if (minValue.CompareTo(maxValue) > 0) { return maxValue; } return minValue; } public T GetMax(T minValue, T maxValue) { if (maxValue.CompareTo(minValue) < 0) { return minValue; } return maxValue; } } public static class MinMaxRange { public static MinMaxRange<float> Float(float minLower, float minUpper, float minDefault, float maxLower, float maxUpper, float maxDefault) { return new MinMaxRange<float>(RangeValue.Float(minLower, minUpper, minDefault), RangeValue.Float(maxLower, maxUpper, maxDefault)); } } public sealed class RangeValue<T> where T : struct, IComparable<T> { public T Min { get; } public T Max { get; } public T Default { get; } public RangeValue(T min, T max, T defaultValue) { if (min.CompareTo(max) > 0) { throw new ArgumentException($"Min ({min}) cannot be greater than Max ({max})"); } Min = min; Max = max; Default = Clamp(defaultValue); } public T Clamp(T value) { if (value.CompareTo(Min) < 0) { return Min; } if (value.CompareTo(Max) > 0) { return Max; } return value; } } public static class RangeValue { public static RangeValue<float> Float(float min, float max, float defaultValue) { return new RangeValue<float>(min, max, defaultValue); } public static RangeValue<int> Int(int min, int max, int defaultValue) { return new RangeValue<int>(min, max, defaultValue); } public static RangeValue<float> Percentage(float defaultValue = 1f) { return new RangeValue<float>(0f, 1f, defaultValue); } } } namespace VepMod.VepFramework.Structures.FSM { public class StateMachineBase<TMachine, TStateId> where TMachine : StateMachineBase<TMachine, TStateId> { public class StateBase { public TMachine Machine { get; set; } public virtual void OnStateEnter(TStateId previous) { } public virtual void OnStateExit(TStateId next) { } public virtual void OnStateUpdate() { } } public class StateBaseTimed : StateBase { public float TimeElapsed { get; protected set; } public override void OnStateEnter(TStateId previous) { base.OnStateEnter(previous); TimeElapsed = 0f; } public override void OnStateUpdate() { base.OnStateUpdate(); TimeElapsed += Time.deltaTime; } } public class StateBaseTransition : StateBaseTimed { public float Duration; public TStateId NextState; public StateBaseTransition(float duration, TStateId nextState) { Duration = duration; NextState = nextState; } public override void OnStateEnter(TStateId previous) { base.OnStateEnter(previous); if (Duration <= 0f) { base.Machine.NextStateStateId = NextState; } } public override void OnStateUpdate() { base.OnStateUpdate(); if (base.TimeElapsed >= Duration) { base.Machine.NextStateStateId = NextState; } } } private readonly StateBase Default = new StateBase(); private readonly Dictionary<TStateId, StateBase> states = new Dictionary<TStateId, StateBase>(); private StateBase _currentStateBaseRunning; public TStateId CurrentStateStateId { get; private set; } public TStateId NextStateStateId { get; set; } public StateMachineBase(TStateId defaultStateId) { CurrentStateStateId = defaultStateId; NextStateStateId = defaultStateId; } public void AddState(TStateId stateId, StateBase stateBase) { stateBase.Machine = this as TMachine; if (states.ContainsKey(stateId)) { Debug.LogWarning((object)$"[FSM] Fsm already defines a state with key {stateId}, it will be overidden"); } states[stateId] = stateBase; } public StateBase GetState(TStateId stateId) { if (!states.TryGetValue(stateId, out StateBase value)) { return Default; } return value; } public T GetStateTyped<T>(TStateId stateId) where T : StateBase { return GetState(stateId) as T; } private void RefreshStatesIO() { for (StateBase state = GetState(NextStateStateId); state != _currentStateBaseRunning; state = GetState(NextStateStateId)) { TStateId nextStateStateId = NextStateStateId; _currentStateBaseRunning?.OnStateExit(nextStateStateId); if (!states.ContainsKey(nextStateStateId)) { Debug.LogWarning((object)$"[FSM] Fsm does not define any state with key {nextStateStateId}, it will play default state"); } _currentStateBaseRunning = GetState(nextStateStateId); _currentStateBaseRunning?.OnStateEnter(CurrentStateStateId); CurrentStateStateId = nextStateStateId; } } public void Update() { RefreshStatesIO(); _currentStateBaseRunning?.OnStateUpdate(); RefreshStatesIO(); } } public abstract class StateMachineComponent<TOwner, TStateId> : MonoBehaviour where TOwner : StateMachineComponent<TOwner, TStateId> { protected sealed class StateMachine : StateMachineBase<StateMachine, TStateId> { public TOwner Owner { get; } public StateMachine(TOwner owner, TStateId defaultKey) : base(defaultKey) { Owner = owner; } } protected StateMachine Fsm; protected abstract TStateId DefaultState { get; } protected virtual void Awake() { Fsm = new StateMachine(this as TOwner, DefaultState); } protected virtual void Update() { Fsm.Update(); } } } namespace VepMod.VepFramework.Extensions { public static class FileSystemSanitizer { private const string DefaultFallback = "unknown"; private static readonly HashSet<string> WindowsReservedNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "CON", "PRN", "AUX", "NUL", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9" }; public static string Sanitize(string input, string fallback = "unknown") { if (string.IsNullOrEmpty(input)) { return fallback; } char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); string text = string.Join("_", input.Split(invalidFileNameChars, StringSplitOptions.RemoveEmptyEntries)); text = text.TrimEnd('.', ' '); if (string.IsNullOrEmpty(text)) { return fallback; } if (WindowsReservedNames.Contains(text)) { text = "_" + text + "_"; } return text; } } public static class TaskExtensions { [CompilerGenerated] private sealed class <AsCoroutine>d__0 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public Task task; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <AsCoroutine>d__0(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; break; case 1: <>1__state = -1; break; } if (!task.IsCompleted) { <>2__current = null; <>1__state = 1; return true; } if (task.Exception != null) { throw task.Exception; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [IteratorStateMachine(typeof(<AsCoroutine>d__0))] public static IEnumerator AsCoroutine(this Task task) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <AsCoroutine>d__0(0) { task = task }; } } } namespace VepMod.VepFramework.Config { public sealed class BoundMinMaxRange<T> where T : struct, IComparable<T> { private readonly MinMaxRange<T> _range; private readonly ConfigEntry<T> _minEntry; private readonly ConfigEntry<T> _maxEntry; public T Min => _range.GetMin(_minEntry.Value, _maxEntry.Value); public T Max => _range.GetMax(_minEntry.Value, _maxEntry.Value); public BoundMinMaxRange(MinMaxRange<T> range, ConfigEntry<T> minEntry, ConfigEntry<T> maxEntry) { _range = range; _minEntry = minEntry; _maxEntry = maxEntry; } } public static class ConfigExtensions { private static AcceptableValueRange<T> ToAcceptableValueRange<T>(this RangeValue<T> range) where T : struct, IComparable, IComparable<T> { return new AcceptableValueRange<T>(range.Min, range.Max); } private static ConfigDescription ToConfigDescription<T>(this RangeValue<T> range, string description) where T : struct, IComparable, IComparable<T> { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown return new ConfigDescription(description, (AcceptableValueBase)(object)range.ToAcceptableValueRange(), Array.Empty<object>()); } public static ConfigEntry<T> BindRange<T>(this ConfigFile config, string section, string key, RangeValue<T> range, string description) where T : struct, IComparable, IComparable<T> { return config.Bind<T>(section, key, range.Default, range.ToConfigDescription(description)); } public static BoundMinMaxRange<T> BindMinMax<T>(this ConfigFile config, string section, string minKey, string maxKey, MinMaxRange<T> range, string minDescription, string maxDescription) where T : struct, IComparable, IComparable<T> { ConfigEntry<T> minEntry = config.Bind<T>(section, minKey, range.MinRange.Default, range.MinRange.ToConfigDescription(minDescription)); ConfigEntry<T> maxEntry = config.Bind<T>(section, maxKey, range.MaxRange.Default, range.MaxRange.ToConfigDescription(maxDescription)); return new BoundMinMaxRange<T>(range, minEntry, maxEntry); } } } namespace VepMod.Patchs { [HarmonyPatch(typeof(EnemyDirector), "FirstSpawnPointAdd")] public class EnemyLoggerPatch { private static readonly VepLogger LOG = VepLogger.Create<EnemyLoggerPatch>(); [HarmonyPrefix] private static void Prefix(EnemyParent _enemyParent) { LOG.Info($"EnemyDirector.FirstSpawnPointAdd: {_enemyParent} added as first spawn point."); } } [HarmonyPatch(typeof(LocalVoiceFramed<short>), "PushDataAsync")] internal class LocalVoiceFramedPatch { private static readonly VepLogger LOG = VepLogger.Create<LocalVoiceFramedPatch>(); private static void Prefix(short[] buf, LocalVoiceFramed<short> __instance) { VepFinder.EnsureInitialized(); if (!IsNotReady()) { VepFinder.LocalMimics.ProcessVoiceData(buf); } } private static bool IsNotReady() { bool flag = !PhotonNetwork.IsConnectedAndReady; WhispralMimics localMimics = VepFinder.LocalMimics; bool flag2 = (Object)(object)localMimics == (Object)null; if (flag || flag2) { return true; } bool flag3 = (Object)(object)((Component)localMimics).gameObject == (Object)null; bool flag4 = (Object)(object)localMimics.PhotonView == (Object)null || !localMimics.PhotonView.IsMine; return flag3 || flag4; } } [HarmonyPatch(typeof(Materials))] internal static class MaterialsImpulsePatch { [HarmonyPrefix] [HarmonyPatch("Impulse")] private static bool Impulse_Prefix(Vector3 origin, bool footstep, HostType hostType) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if (!footstep) { return true; } if ((int)hostType != 0 && (int)hostType != 1) { return true; } if (InvisiblePlayerDebuff.IsPositionNearHiddenPlayer(origin)) { return false; } return true; } } [HarmonyPatch(typeof(PlayerAvatar), "Awake")] internal class PlayerAvatarPatch { private static readonly VepLogger LOG = VepLogger.Create<PlayerAvatarPatch>(); private static void Postfix(PlayerAvatar __instance) { if (PhotonNetwork.IsConnectedAndReady) { WhispralMimics whispralMimics = ((Component)__instance).GetComponent<WhispralMimics>(); if (!Object.op_Implicit((Object)(object)whispralMimics)) { whispralMimics = ((Component)__instance).gameObject.AddComponent<WhispralMimics>(); LOG.Debug("Added Mimics component to PlayerAvatar: " + ((Object)__instance).name); } else { LOG.Warning("PlayerAvatar: " + ((Object)__instance).name + " already has a WhispralMimics component."); } PhotonView component = ((Component)__instance).GetComponent<PhotonView>(); if (!Object.op_Implicit((Object)(object)component) || !component.IsMine) { LOG.Warning("PhotonView is null or not owned by local player."); return; } VepFinder.LocalMimics = whispralMimics; LOG.Info("Set LocalMimics for local PlayerAvatar: " + ((Object)__instance).name); } } } [HarmonyPatch(typeof(PlayerController))] internal static class PlayerControllerPatch { } [HarmonyPatch(typeof(ValuableDirector), "Spawn")] public class ValuableLoggerPatch { [HarmonyPrefix] private static void Prefix(PrefabRef _valuable, ValuableVolume _volume, string _path) { } } public class VepFinder : MonoBehaviour { private static VepFinder _instance; private static bool _initialized; private static readonly VepLogger LOG = VepLogger.Create<VepFinder>(); public static WhispralMimics LocalMimics { get; set; } private void OnDestroy() { if (_initialized) { LocalMimics = null; _instance = null; LOG.Info("VepFinder destroyed, clearing cache."); } } public static void EnsureInitialized() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!Object.op_Implicit((Object)(object)_instance)) { _instance = new GameObject("VepFinder").AddComponent<VepFinder>(); _initialized = true; Object.DontDestroyOnLoad((Object)(object)((Component)_instance).gameObject); Player localPlayer = PhotonNetwork.LocalPlayer; LOG.Info($"MimicsFinder initialized for Player {((localPlayer != null) ? localPlayer.ActorNumber : (-1))}"); } } } } namespace VepMod.Enemies.Whispral { public static class AudioFilters { private const float TwoPi = MathF.PI * 2f; private const float Int16MaxValue = 32768f; private const float AlienVibratoFrequency = 5f; private const float AlienVibratoDepth = 0.05f; private const float AlienRingModFrequency = 200f; private const float AlienRingModMix = 0.3f; public const float PitchShiftLow = 0.5f; public const float PitchShiftHigh = 1.2f; private const float DefaultLowPassCutoff = 4500f; public static float[] ApplyAlienFilter(float[] samples, int sampleRate) { float[] array = new float[samples.Length]; for (int i = 0; i < samples.Length; i++) { float num = (float)i / (float)sampleRate; float num2 = 1f + Mathf.Sin(MathF.PI * 10f * num) * 0.05f; float num3 = (float)i * num2; int num4 = (int)num3; float num5 = num3 - (float)num4; float num6 = ((num4 + 1 >= samples.Length) ? ((num4 >= samples.Length) ? 0f : samples[num4]) : (samples[num4] * (1f - num5) + samples[num4 + 1] * num5)); float num7 = Mathf.Sin(MathF.PI * 400f * num); float num8 = num6 * num7 * 0.3f; array[i] = Mathf.Clamp(num6 * 0.7f + num8, -1f, 1f); } return array; } public static float[] ApplyLowPassFilter(float[] samples, int sampleRate, float cutoffFrequency = 4500f) { float num = 1f / (MathF.PI * 2f * cutoffFrequency); float num2 = 1f / (float)sampleRate; float num3 = num2 / (num + num2); float[] array = new float[samples.Length]; array[0] = samples[0]; for (int i = 1; i < samples.Length; i++) { array[i] = array[i - 1] + num3 * (samples[i] - array[i - 1]); } float[] array2 = new float[samples.Length]; array2[samples.Length - 1] = array[samples.Length - 1]; for (int num4 = samples.Length - 2; num4 >= 0; num4--) { array2[num4] = array2[num4 + 1] + num3 * (array[num4] - array2[num4 + 1]); } return array2; } public static float[] ApplyPitchShift(float[] samples, float pitchFactor) { int num = (int)((float)samples.Length / pitchFactor); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i * pitchFactor; int num3 = (int)num2; float num4 = num2 - (float)num3; if (num3 + 1 < samples.Length) { array[i] = samples[num3] * (1f - num4) + samples[num3 + 1] * num4; } else if (num3 < samples.Length) { array[i] = samples[num3]; } } return array; } public static float[] ConvertBytesToFloats(byte[] byteArray) { int num = byteArray.Length / 2; float[] array = new float[num]; for (int i = 0; i < num; i++) { short num2 = (short)(byteArray[i * 2] | (byteArray[i * 2 + 1] << 8)); array[i] = (float)num2 / 32768f; } return array; } public static byte[] ConvertFloatsToBytes(float[] floatArray) { byte[] array = new byte[floatArray.Length * 2]; for (int i = 0; i < floatArray.Length; i++) { short num = (short)(floatArray[i] * 32767f); array[i * 2] = (byte)((uint)num & 0xFFu); array[i * 2 + 1] = (byte)((uint)(num >> 8) & 0xFFu); } return array; } public static float[] ApplyFadeAndPadding(float[] samples, int sampleRate) { int num = (int)((float)sampleRate * 0.5f); int num2 = (int)((float)sampleRate * 0.02f); float[] array = new float[samples.Length + 2 * num]; for (int i = 0; i < num; i++) { array[i] = 0f; } for (int j = 0; j < samples.Length; j++) { float num3 = 1f; if (j < num2) { num3 = (float)j / (float)num2; } else if (j >= samples.Length - num2) { num3 = (float)(samples.Length - j) / (float)num2; } array[j + num] = samples[j] * num3; } for (int k = samples.Length + num; k < array.Length; k++) { array[k] = 0f; } return array; } } public sealed class DilatedPupilsDebuff : MonoBehaviour { private const float PupilSizeMultiplier = 3f; private const int Priority = 5; private const float SpringSpeedIn = 10f; private const float SpringDampIn = 0.5f; private const float SpringSpeedOut = 5f; private const float SpringDampOut = 0.3f; private const float RefreshInterval = 0.1f; private static readonly VepLogger LOG = VepLogger.Create<DilatedPupilsDebuff>(); private PlayerAvatar? playerAvatar; private float refreshTimer; public bool IsActive { get; private set; } private void Awake() { playerAvatar = ((Component)this).GetComponent<PlayerAvatar>(); } private void Update() { if (IsActive && !((Object)(object)playerAvatar == (Object)null)) { refreshTimer -= Time.deltaTime; if (refreshTimer <= 0f) { ApplyPupilEffect(); refreshTimer = 0.1f; } } } public void ApplyDebuff(bool dilated) { IsActive = dilated; LOG.Debug($"Applying dilated pupils debuff: {dilated}"); if (dilated) { refreshTimer = 0f; ApplyPupilEffect(); } } private void ApplyPupilEffect() { if (!((Object)(object)playerAvatar == (Object)null)) { playerAvatar.OverridePupilSize(3f, 5, 10f, 0.5f, 5f, 0.3f, 0.15f); } } } public sealed class DroidController : StateMachineComponent<DroidController, DroidController.StateId> { public enum StateId { Idle, Wander, Sprint, CheckMap, StalkApproach, StalkStare, StalkFlee } private sealed class IdleState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private const string ClipName = "LostDroidStand"; private const float IdleLoopStart = 0f; private const float IdleLoopEnd = 4.5f; private const float BlendDelay = 0.3f; private const float MinIdleTime = 2f; private const float MaxIdleTime = 4f; private const float PrecomputeRetryInterval = 1f; private const float CheckMapChance = 0.25f; private Animator _animator; private bool _animatorTakenOver; private AnimationClip? _clip; private float _currentTime; private float _duration; private float _precomputeTimer; private GameObject? _targetObject; public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); _duration = Random.Range(2f, 4f); _precomputeTimer = 0f; _animatorTakenOver = false; base.Machine.Owner.ResetPath(); base.Machine.Owner.HasChangedMovementState = false; _animator = base.Machine.Owner.Animator; if ((Object)(object)_animator != (Object)null) { _clip = DroidHelpers.GetAnimationClip(_animator, "LostDroidStand"); if ((Object)(object)_clip != (Object)null) { _targetObject = ((Component)_animator).gameObject; } } base.Machine.Owner.StartPrecomputeDestination(); } public override void OnStateUpdate() { base.OnStateUpdate(); if (!_animatorTakenOver && (Object)(object)_clip != (Object)null && (Object)(object)_targetObject != (Object)null && base.TimeElapsed >= 0.3f) { ((Behaviour)_animator).enabled = false; _currentTime = 0f; _animatorTakenOver = true; } if (_animatorTakenOver && (Object)(object)_clip != (Object)null && (Object)(object)_targetObject != (Object)null) { _currentTime += Time.deltaTime; if (_currentTime >= 4.5f) { _currentTime = 0f; } _clip.SampleAnimation(_targetObject, _currentTime); } if (!base.Machine.Owner.HasPrecomputedDestination) { _precomputeTimer -= Time.deltaTime; if (_precomputeTimer <= 0f) { base.Machine.Owner.StartPrecomputeDestination(); _precomputeTimer = 1f; } } if (!(base.TimeElapsed >= _duration)) { return; } float distanceToPlayer = base.Machine.Owner.GetDistanceToPlayer(); if (distanceToPlayer > 15f && Random.value < 0.1f) { base.Machine.NextStateStateId = StateId.StalkApproach; return; } float value = Random.value; if (value < 0.25f) { base.Machine.NextStateStateId = StateId.CheckMap; } else { base.Machine.NextStateStateId = ((!(Random.value < 0.5f)) ? StateId.Wander : StateId.Sprint); } } public override void OnStateExit(StateId next) { base.OnStateExit(next); if ((Object)(object)_animator != (Object)null && next != StateId.CheckMap) { ((Behaviour)_animator).enabled = true; } } } private abstract class MovementState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private const float SwitchCheckInterval = 1f; private const float SwitchChance = 0.2f; private const float PrecomputeForwardInterval = 0.5f; private float _duration; private float _nextSwitchCheck; private float _nextPrecomputeForward; protected abstract float MinDuration { get; } protected abstract float MaxDuration { get; } protected abstract float Speed { get; } protected abstract StateId SwitchTargetState { get; } protected abstract void SetMovementFlag(bool value); public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); _duration = Random.Range(MinDuration, MaxDuration); _nextSwitchCheck = 1f; _nextPrecomputeForward = 0.5f; if ((uint)(previous - 1) <= 1u) { base.Machine.Owner.TryExtendCurrentPath(); } else if (!base.Machine.Owner.TrySetRandomDestination()) { base.Machine.NextStateStateId = StateId.Idle; return; } base.Machine.Owner.SetSpeed(Speed); SetMovementFlag(value: true); base.Machine.Owner.StartPrecomputeForwardDestination(); } public override void OnStateExit(StateId next) { base.OnStateExit(next); SetMovementFlag(value: false); if ((uint)(next - 1) > 1u) { base.Machine.Owner.ClearPrecomputedForwardDestination(); } } public override void OnStateUpdate() { base.OnStateUpdate(); if (base.Machine.Owner.HasReachedDestination() || base.TimeElapsed >= _duration) { base.Machine.NextStateStateId = StateId.Idle; return; } _nextPrecomputeForward -= Time.deltaTime; if (_nextPrecomputeForward <= 0f) { _nextPrecomputeForward = 0.5f; base.Machine.Owner.StartPrecomputeForwardDestination(); } if (!base.Machine.Owner.HasChangedMovementState && base.TimeElapsed >= _nextSwitchCheck) { _nextSwitchCheck += 1f; if (Random.value < 0.2f) { base.Machine.Owner.HasChangedMovementState = true; base.Machine.NextStateStateId = SwitchTargetState; } } } } private sealed class WanderState : MovementState { protected override float MinDuration => 5f; protected override float MaxDuration => 15f; protected override float Speed => 2f; protected override StateId SwitchTargetState => StateId.Sprint; protected override void SetMovementFlag(bool value) { base.Machine.Owner.IsWalking = value; } } private sealed class SprintState : MovementState { protected override float MinDuration => 3f; protected override float MaxDuration => 8f; protected override float Speed => 5f; protected override StateId SwitchTargetState => StateId.Wander; protected override void SetMovementFlag(bool value) { base.Machine.Owner.IsSprinting = value; } } private sealed class CheckMapState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private enum Phase { Raise, Look, Lower } private const string ClipName = "LostDroidStand"; private const float RaiseStartTime = 4.65f; private const float LookStartTime = 5.5f; private const float LookEndTime = 6.9333334f; private const float LowerEndTime = 7.15f; private const float MinLookDuration = 0.5f; private const float MaxLookDuration = 3f; private Animator? _animator; private AnimationClip? _clip; private Phase _currentPhase; private float _currentTime; private float _lookDuration; private float _lookTimer; private GameObject? _targetObject; public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); _animator = base.Machine.Owner.Animator; if ((Object)(object)_animator == (Object)null) { LOG.Warning("CheckMapState: Animator is null!"); base.Machine.NextStateStateId = StateId.Idle; return; } _clip = DroidHelpers.GetAnimationClip(_animator, "LostDroidStand"); if ((Object)(object)_clip == (Object)null) { LOG.Warning("CheckMapState: Clip 'LostDroidStand' not found!"); base.Machine.NextStateStateId = StateId.Idle; return; } _targetObject = ((Component)_animator).gameObject; base.Machine.Owner.IsWalking = false; base.Machine.Owner.IsSprinting = false; base.Machine.Owner.ResetPath(); ((Behaviour)_animator).enabled = false; _lookDuration = Random.Range(0.5f, 3f); _lookTimer = 0f; _currentPhase = Phase.Raise; _currentTime = 4.65f; LOG.Debug($"CheckMapState: ENTER - Clip length={_clip.length}s, starting at {_currentTime}s"); LOG.Debug($"CheckMapState: Thresholds - Raise={4.65f}s, Look={5.5f}s-{6.9333334f}s, Lower={7.15f}s"); LOG.Debug($"CheckMapState: LookDuration={_lookDuration:F1}s"); _clip.SampleAnimation(_targetObject, _currentTime); } public override void OnStateUpdate() { base.OnStateUpdate(); if ((Object)(object)_clip == (Object)null || (Object)(object)_targetObject == (Object)null) { base.Machine.NextStateStateId = StateId.Idle; return; } _currentTime += Time.deltaTime; switch (_currentPhase) { case Phase.Raise: if (_currentTime >= 5.5f) { LOG.Debug("CheckMapState: Transitioning to Phase.Look"); _currentPhase = Phase.Look; _lookTimer = 0f; } break; case Phase.Look: _lookTimer += Time.deltaTime; if (_currentTime >= 6.9333334f) { if (_lookTimer < _lookDuration) { _currentTime = 5.5f; break; } LOG.Debug("CheckMapState: Transitioning to Phase.Lower"); _currentPhase = Phase.Lower; } break; case Phase.Lower: if (_currentTime >= 7.15f) { LOG.Debug("CheckMapState: Animation complete, returning to Idle"); base.Machine.NextStateStateId = StateId.Idle; return; } break; } _clip.SampleAnimation(_targetObject, _currentTime); } public override void OnStateExit(StateId next) { base.OnStateExit(next); LOG.Debug($"CheckMapState: EXIT -> {next}"); if ((Object)(object)_animator != (Object)null) { ((Behaviour)_animator).enabled = true; } } } private sealed class StalkApproachState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private const float MaxApproachTime = 30f; private const float DestinationUpdateInterval = 1f; private float _nextDestinationUpdate; public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); LOG.Debug("=== STALK: Approach started - running towards player ==="); base.Machine.Owner.IsSprinting = true; base.Machine.Owner.SetSpeed(5f); _nextDestinationUpdate = 0f; if (!base.Machine.Owner.TrySetDestinationToPlayer()) { LOG.Debug("STALK: Failed to set destination to player, aborting"); base.Machine.NextStateStateId = StateId.Idle; } } public override void OnStateUpdate() { base.OnStateUpdate(); float distanceToPlayer = base.Machine.Owner.GetDistanceToPlayer(); bool flag = base.Machine.Owner.HasReachedDestination(); if (base.TimeElapsed >= 30f) { LOG.Debug($"STALK: Approach timeout, dist={distanceToPlayer:F1}m, aborting"); base.Machine.NextStateStateId = StateId.Idle; return; } if (distanceToPlayer <= 5f) { LOG.Debug($"STALK: Arrived near player (distance={distanceToPlayer:F1}m)"); base.Machine.NextStateStateId = StateId.StalkStare; return; } if (flag) { LOG.Debug($"STALK: Reached nav destination but player still at {distanceToPlayer:F1}m, starting stare anyway"); base.Machine.NextStateStateId = StateId.StalkStare; return; } _nextDestinationUpdate -= Time.deltaTime; if (_nextDestinationUpdate <= 0f) { base.Machine.Owner.TrySetDestinationToPlayer(); _nextDestinationUpdate = 1f; } } public override void OnStateExit(StateId next) { base.OnStateExit(next); base.Machine.Owner.IsSprinting = false; base.Machine.Owner.ResetPath(); } } private sealed class StalkStareState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private const float MaxStareTime = 30f; private const float DestinationUpdateInterval = 0.5f; private float _fleeCountdown; private bool _hasBeenSeen; private float _nextDestinationUpdate; public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); LOG.Debug("=== STALK: Staring at player ==="); _hasBeenSeen = false; _fleeCountdown = 2f; _nextDestinationUpdate = 0f; base.Machine.Owner.IsWalking = true; base.Machine.Owner.IsSprinting = false; base.Machine.Owner.SetSpeed(2f); } public override void OnStateUpdate() { base.OnStateUpdate(); base.Machine.Owner.LookAtPlayer(); float distanceToPlayer = base.Machine.Owner.GetDistanceToPlayer(); if (base.Machine.Owner.IsPlayerLookingAtMe && !_hasBeenSeen) { _hasBeenSeen = true; LOG.Debug("=== STALK: Player sees me! Maintaining eye contact... ==="); base.Machine.Owner.IsWalking = false; base.Machine.Owner.ResetPath(); } if (_hasBeenSeen) { _fleeCountdown -= Time.deltaTime; if (_fleeCountdown <= 0f) { LOG.Debug("=== STALK: Eye contact over, fleeing! ==="); base.Machine.NextStateStateId = StateId.StalkFlee; return; } } else if (distanceToPlayer > 3f) { _nextDestinationUpdate -= Time.deltaTime; if (_nextDestinationUpdate <= 0f) { base.Machine.Owner.TrySetDestinationToPlayer(); _nextDestinationUpdate = 0.5f; } } else { base.Machine.Owner.ResetPath(); } if (base.TimeElapsed >= 30f) { LOG.Debug("STALK: Stare timeout, fleeing"); base.Machine.NextStateStateId = StateId.StalkFlee; } } public override void OnStateExit(StateId next) { base.OnStateExit(next); base.Machine.Owner.IsWalking = false; } } private sealed class StalkFleeState : StateMachineBase<StateMachine, StateId>.StateBaseTimed { private const float MaxFleeTime = 10f; public override void OnStateEnter(StateId previous) { base.OnStateEnter(previous); LOG.Debug("=== STALK: Fleeing from player! ==="); base.Machine.Owner.IsSprinting = true; base.Machine.Owner.SetSpeed(5f); if (!base.Machine.Owner.TrySetFleeDestination()) { LOG.Debug("STALK: Failed to set flee destination, going to idle"); base.Machine.NextStateStateId = StateId.Idle; } } public override void OnStateUpdate() { base.OnStateUpdate(); if (base.Machine.Owner.HasReachedDestination() || base.TimeElapsed >= 10f) { LOG.Debug("=== STALK: Flee complete, returning to idle ==="); base.Machine.NextStateStateId = StateId.Idle; } } public override void OnStateExit(StateId next) { base.OnStateExit(next); base.Machine.Owner.IsSprinting = false; } } internal const float WalkSpeed = 2f; internal const float SprintSpeed = 5f; internal const float SprintChance = 0.5f; internal const float StalkMinDistance = 15f; internal const float StalkChance = 0.1f; internal const float StalkArrivalDistance = 5f; internal const float StalkMinKeepDistance = 3f; internal const float StalkFleeDistance = 20f; internal const float StalkStareBeforeFlee = 2f; private static readonly VepLogger LOG = VepLogger.Create<DroidController>(); private static readonly int IsWalkingKey = Animator.StringToHash("isWalking"); private static readonly int IsSprintingKey = Animator.StringToHash("isSprinting"); private static readonly int IsTurningKey = Animator.StringToHash("isTurning"); private static readonly int StunKey = Animator.StringToHash("stun"); private static readonly int AlbedoColorKey = Shader.PropertyToID("_AlbedoColor"); private readonly MaterialTrigger _materialTrigger = new MaterialTrigger(); private DroidFaceAnimationController _animController; private CharacterController _charController; private DroidNameplate _nameplateController; private NavMeshAgent _navAgent; private Transform _rigidbodyTransform; private int _savedAgentTypeID; private int _savedAreaMask = -1; internal Animator Animator; public bool IsWalking { get; set; } public bool IsSprinting { get; set; } public bool IsTurning { get; private set; } public bool HasChangedMovementState { get; set; } public PlayerAvatar SourcePlayer { get; private set; } public Transform ControllerTransform { get; private set; } public DroidMovementController Movement { get; private set; } public bool IsPlayerLookingAtMe => _animController.IsPlayerLookingAtMe; public bool IsStalking { get { StateId currentStateStateId = Fsm.CurrentStateStateId; if ((uint)(currentStateStateId - 4) <= 2u) { return true; } return false; } } protected override StateId DefaultState => StateId.Idle; public bool HasPrecomputedDestination => Movement.HasPrecomputedDestination; protected override void Awake() { } protected override void Update() { if (!((Object)(object)Movement == (Object)null) && !((Object)(object)_navAgent == (Object)null) && _navAgent.isOnNavMesh && !((Object)(object)ControllerTransform == (Object)null)) { Fsm.Update(); StateId currentStateStateId = Fsm.CurrentStateStateId; bool isMovementState = DroidHelpers.IsMovementState(currentStateStateId); Movement.UpdateMovement(isMovementState); Movement.UpdateRotation(); Movement.SyncVisualsToController(((Component)Animator).transform); UpdateAnimationFlags(); Movement.SyncNavAgentPosition(isMovementState); } } public void PlayVoice(bool applyFilter = false) { if ((Object)(object)SourcePlayer == (Object)null || (Object)(object)ControllerTransform == (Object)null) { return; } PlayerAvatar instance = PlayerAvatar.instance; if (!((Object)(object)instance == (Object)null)) { WhispralMimics component = ((Component)instance).GetComponent<WhispralMimics>(); if ((Object)(object)component == (Object)null) { LOG.Warning("WhispralMimics not found on local player"); } else { component.PlayAudioAtTransform(ControllerTransform, SourcePlayer.playerName, applyFilter); } } } private void UpdateAnimationFlags() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) StateId currentStateStateId = Fsm.CurrentStateStateId; if (DroidHelpers.IsMovementState(currentStateStateId) && (Object)(object)ControllerTransform != (Object)null && (Object)(object)Movement != (Object)null) { float num = Quaternion.Angle(ControllerTransform.rotation, Movement.TargetRotation); IsTurning = num > 7f; } else { IsTurning = false; } if ((Object)(object)Animator != (Object)null) { Animator.SetBool(IsWalkingKey, IsWalking); Animator.SetBool(IsSprintingKey, IsSprinting); Animator.SetBool(IsTurningKey, IsTurning); Animator.SetBool(StunKey, false); } } public bool TrySetRandomDestination() { if ((Object)(object)Movement != (Object)null) { return Movement.TrySetRandomDestination(); } return false; } public bool TryExtendCurrentPath() { if ((Object)(object)Movement != (Object)null) { return Movement.TryExtendCurrentPath(); } return false; } public void StartPrecomputeForwardDestination() { Movement?.StartPrecomputeForwardDestination(); } public void ClearPrecomputedForwardDestination() { Movement?.ClearPrecomputedForwardDestination(); } public void StartPrecomputeDestination() { Movement.StartPrecomputeDestination(); } public void ResetPath() { Movement.ResetPath(); } public bool HasReachedDestination() { return Movement.HasReachedDestination(); } public float GetDistanceToPlayer() { return Movement.GetDistanceToPlayer(); } public bool TrySetDestinationToPlayer() { if ((Object)(object)Movement != (Object)null) { return Movement.TrySetDestinationToPlayer(); } return false; } public bool TrySetFleeDestination() { if ((Object)(object)Movement != (Object)null) { return Movement.TrySetFleeDestination(20f); } return false; } public void LookAtPlayer() { Movement.LookAtPlayer(); } public void SetSpeed(float speed) { Movement.SetSpeed(speed); } public static DroidController? Create(PlayerAvatar sourcePlayer, Vector3 spawnPosition) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!DroidPrefabLoader.IsAvailable) { LOG.Warning("LostDroid prefab not available"); return null; } GameObject val = Object.Instantiate<GameObject>(DroidPrefabLoader.DroidPrefab, spawnPosition, Quaternion.identity); if ((Object)(object)val == (Object)null) { LOG.Error("Failed to instantiate LostDroid prefab"); return null; } ((Object)val).name = "HallucinationDroid_" + sourcePlayer.playerName; DroidController droidController = val.AddComponent<DroidController>(); droidController.Initialize(sourcePlayer); return droidController; } private void Initialize(PlayerAvatar sourcePlayer) { //IL_0065: Unknown result type (might be due to invalid IL or missing references) SourcePlayer = sourcePlayer; FindCriticalTransforms(); SaveNavMeshSettings(); DisableEnemyComponents(); SetupNavigation(); SetupMovementController(); SetupAnimator(); SetupAnimationController(); DroidMaterialFixer.FixMaterials(((Component)this).gameObject); ApplyPlayerColor(); SetupNameplate(); InitializeFsm(); LOG.Info($"HallucinationDroid created for {sourcePlayer.playerName} at {ControllerTransform.position}"); } private void SetupMovementController() { if (!((Object)(object)ControllerTransform == (Object)null)) { Movement = ((Component)this).gameObject.AddComponent<DroidMovementController>(); Movement.Initialize(ControllerTransform, _rigidbodyTransform, _navAgent, _charController, _savedAreaMask); Movement.OnNavMeshError += HandleNavMeshError; } } private void HandleNavMeshError() { Fsm.NextStateStateId = StateId.Idle; } private void SetupAnimationController() { _animController = ((Component)this).gameObject.AddComponent<DroidFaceAnimationController>(); _animController.Initialize(this, ControllerTransform); Transform val = DroidHelpers.FindChildByName(((Component)this).transform, "code_head_top"); if ((Object)(object)val != (Object)null) { _animController.SetupTalking(val); } SetupEyelidsForAnimController(); } private void SetupEyelidsForAnimController() { try { Transform val = DroidHelpers.FindChildByName(((Component)this).transform, "ANIM EYE LEFT"); Transform val2 = DroidHelpers.FindChildByName(((Component)this).transform, "ANIM EYE RIGHT"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { LOG.Warning("ANIM EYE LEFT/RIGHT not found for angry eyes effect"); return; } Transform val3 = FindEyelidSource(); if ((Object)(object)val3 == (Object)null) { LOG.Warning("No PlayerAvatar found to copy eyelid structure"); return; } Transform droidEye = DroidHelpers.FindChildByName(((Component)this).transform, "code_eye_left") ?? val; Transform droidEye2 = DroidHelpers.FindChildByName(((Component)this).transform, "code_eye_right") ?? val2; Transform upperRotationX; Transform upperRotationZ; Transform lowerRotationX; GameObject val4 = SetupEyeFromPlayer(droidEye, val3, "LEFT", out upperRotationX, out upperRotationZ, out lowerRotationX); Transform upperRotationX2; Transform upperRotationZ2; Transform lowerRotationX2; GameObject val5 = SetupEyeFromPlayer(droidEye2, val3, "RIGHT", out upperRotationX2, out upperRotationZ2, out lowerRotationX2); if ((Object)(object)val4 != (Object)null) { val4.SetActive(false); } if ((Object)(object)val5 != (Object)null) { val5.SetActive(false); } _animController.SetupEyelids(val4, val5, upperRotationX, upperRotationZ, lowerRotationX, upperRotationX2, upperRotationZ2, lowerRotationX2); LOG.Info($"Angry eyes setup: left={(Object)(object)val4 != (Object)null}, right={(Object)(object)val5 != (Object)null}"); } catch (Exception ex) { LOG.Error("SetupEyelidsForAnimController: Exception - " + ex.Message + "\n" + ex.StackTrace); } } private void LateUpdate() { _nameplateController.UpdateNameplate(); _animController.UpdateAnimations(); } private void OnDestroy() { if ((Object)(object)Movement != (Object)null) { Movement.OnNavMeshError -= HandleNavMeshError; } } private Material? GetDroidBodyMaterial() { MeshRenderer[] componentsInChildren = ((Component)this).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val in componentsInChildren) { string text = ((Object)((Component)val).gameObject).name.ToLower(); if (!text.Contains("eye") && !text.Contains("pupil") && !text.Contains("eyelid") && (Object)(object)((Renderer)val).material != (Object)null) { return ((Renderer)val).material; } } return null; } private Transform? FindEyelidSource() { PlayerAvatarVisuals[] array = Object.FindObjectsOfType<PlayerAvatarVisuals>(); PlayerAvatarVisuals[] array2 = array; foreach (PlayerAvatarVisuals val in array2) { Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (((Object)val2).name == "EYELIDS LEFT") { return ((Component)val).transform; } } } LOG.Warning("No PlayerAvatarVisuals with EYELIDS LEFT found"); return null; } private GameObject? SetupEyeFromPlayer(Transform droidEye, Transform playerSource, string side, out Transform? upperRotationX, out Transform? upperRotationZ, out Transform? lowerRotationX) { //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) upperRotationX = null; upperRotationZ = null; lowerRotationX = null; string text = "EYELIDS " + side; Transform val = null; Transform[] componentsInChildren = ((Component)playerSource).GetComponentsInChildren<Transform>(true); foreach (Transform val2 in componentsInChildren) { if (((Object)val2).name == text) { val = val2; break; } } if ((Object)(object)val == (Object)null) { LOG.Warning(text + " not found on player source"); return null; } Transform val3 = null; foreach (Transform item in droidEye) { Transform val4 = item; if (((Object)val4).name == text) { val3 = val4; break; } } if ((Object)(object)val3 == (Object)null) { val3 = CopyTransformHierarchy(val, droidEye); val3.localScale = Vector3.one * 1.3f; Material droidBodyMaterial = GetDroidBodyMaterial(); if ((Object)(object)droidBodyMaterial != (Object)null) { MeshRenderer[] componentsInChildren2 = ((Component)val3).GetComponentsInChildren<MeshRenderer>(true); foreach (MeshRenderer val5 in componentsInChildren2) { ((Renderer)val5).material = droidBodyMaterial; } } } Transform[] componentsInChildren3 = ((Component)val3).GetComponentsInChildren<Transform>(true); foreach (Transform val6 in componentsInChildren3) { switch (((Object)val6).name) { case "eyelid_upper": upperRotationX = val6; break; case "eyelid_upper_rotation": upperRotationZ = val6; break; case "eyelid_lower": lowerRotationX = val6; break; } } return ((Component)val3).gameObject; } private Transform CopyTransformHierarchy(Transform source, Transform newParent) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Expected O, but got Unknown GameObject val = new GameObject(((Object)source).name); val.transform.SetParent(newParent, false); val.transform.localPosition = source.localPosition; val.transform.localRotation = source.localRotation; val.transform.localScale = source.localScale; MeshFilter component = ((Component)source).GetComponent<MeshFilter>(); MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { MeshFilter val2 = val.AddComponent<MeshFilter>(); MeshRenderer val3 = val.AddComponent<MeshRenderer>(); val2.sharedMesh = component.sharedMesh; ((Renderer)val3).sharedMaterials = ((Renderer)component2).sharedMaterials; ((Renderer)val3).shadowCastingMode = ((Renderer)component2).shadowCastingMode; ((Renderer)val3).receiveShadows = ((Renderer)component2).receiveShadows; } foreach (Transform item in source) { Transform source2 = item; CopyTransformHierarchy(source2, val.transform); } return val.transform; } public void PlayMediumFootstep() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ControllerTransform == (Object)null)) { Vector3 val = ControllerTransform.position + Vector3.up * 0.1f; Materials.Instance.Impulse(val, Vector3.down, (SoundType)1, true, true, _materialTrigger, (HostType)1); } } private void SetupNameplate() { _nameplateController = ((Component)this).gameObject.AddComponent<DroidNameplate>(); _nameplateController.Initialize(ControllerTransform, SourcePlayer); } private void ApplyPlayerColor() { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)SourcePlayer == (Object)null) { return; } int playerColor = StatsManager.instance.GetPlayerColor(SourcePlayer.steamID); if (playerColor < 0 || playerColor >= AssetManager.instance.playerColors.Count) { return; } Color val = AssetManager.instance.playerColors[playerColor]; Transform val2 = ((Component)this).transform.Find("Rigidbody/Cube") ?? ((Component)this).transform.Find("Cube"); if ((Object)(object)val2 == (Object)null) { Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(); foreach (Transform val3 in componentsInChildren) { if (((Object)val3).name == "Cube") { val2 = val3; break; } } } if ((Object)(object)val2 == (Object)null) { LOG.Warning("Cube transform not found for color application"); return; } Renderer[] componentsInChildren2 = ((Component)val2).GetComponentsInChildren<Renderer>(); foreach (Renderer val4 in componentsInChildren2) { string name = ((Object)((Component)val4).gameObject).name; if (!name.Contains("eye") && !name.Contains("pupil") && !name.Contains("mesh_health")) { Material[] materials = val4.materials; foreach (Material val5 in materials) { val5.SetColor(AlbedoColorKey, val); } } } } private void InitializeFsm() { Fsm = new StateMachineComponent<DroidController, StateId>.StateMachine(this, DefaultState); Fsm.AddState(StateId.Idle, new IdleState()); Fsm.AddState(StateId.Wander, new WanderState()); Fsm.AddState(StateId.Sprint, new SprintState()); Fsm.AddState(StateId.CheckMap, new CheckMapState()); Fsm.AddState(StateId.StalkApproach, new StalkApproachState()); Fsm.AddState(StateId.StalkStare, new StalkStareState()); Fsm.AddState(StateId.StalkFlee, new StalkFleeState()); } private void FindCriticalTransforms() { //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) ControllerTransform = ((Component)this).transform.Find("Controller"); if ((Object)(object)ControllerTransform == (Object)null) { Transform[] componentsInChildren = ((Component)this).GetComponentsInChildren<Transform>(); foreach (Transform val in componentsInChildren) { if (((Object)val).name == "Controller") { ControllerTransform = val; break; } } } if ((Object)(object)ControllerTransform == (Object)null) { LOG.Warning("Controller transform not found, creating one"); GameObject val2 = new GameObject("Controller"); val2.transform.SetParent(((Component)this).transform); val2.transform.localPosition = Vector3.zero; ControllerTransform = val2.transform; } _rigidbodyTransform = ((Component)this).transform.Find("Rigidbody"); if ((Object)(object)_rigidbodyTransform == (Object)null) { Transform[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Transform>(); foreach (Transform val3 in componentsInChildren2) { if (((Object)val3).name == "Rigidbody") { _rigidbodyTransform = val3; break; } } } if ((Object)(object)_rigidbodyTransform == (Object)null) { LOG.Warning("Rigidbody transform not found"); } } private void SaveNavMeshSettings() { NavMeshAgent val = null; if ((Object)(object)ControllerTransform != (Object)null) { val = ((Component)ControllerTransform).GetComponent<NavMeshAgent>(); } if ((Object)(object)val == (Object)null) { val = ((Component)this).GetComponentInChildren<NavMeshAgent>(); } if ((Object)(object)val != (Object)null) { _savedAgentTypeID = val.agentTypeID; _savedAreaMask = val.areaMask; } else { _savedAgentTypeID = -334000983; _savedAreaMask = 1; } } private void DisableEnemyComponents() { //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) List<Component> list = new List<Component>(); List<MonoBehaviour> list2 = new List<MonoBehaviour>(); Component[] componentsInChildren = ((Component)this).GetComponentsInChildren<Component>(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)this) { continue; } string name = ((object)val).GetType().Name; string text = ((object)val).GetType().FullName ?? ""; if (val is Transform || val is Animator || val is Renderer || val is MeshFilter || val is SkinnedMeshRenderer || val is NavMeshAgent) { continue; } if (text.Contains("Photon") || name.Contains("Photon") || text.Contains("Enemy") || text.Contains("LostDroid") || name.Contains("Enemy") || name.Contains("LostDroid")) { list.Add(val); continue; } MonoBehaviour val2 = (MonoBehaviour)(object)((val is MonoBehaviour) ? val : null); if (val2 != null) { list2.Add(val2); } } for (int j = 0; j < 5; j++) { int num = 0; foreach (Component item in list) { if ((Object)(object)item != (Object)null) { try { Object.DestroyImmediate((Object)(object)item); num++; } catch { } } } if (num == 0) { break; } } foreach (MonoBehaviour item2 in list2) { if ((Object)(object)item2 != (Object)null && (Object)(object)item2 != (Object)(object)this) { ((Behaviour)item2).enabled = false; } } Rigidbody[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<Rigidbody>(); foreach (Rigidbody val3 in componentsInChildren2) { val3.isKinematic = true; val3.useGravity = false; val3.velocity = Vector3.zero; val3.angularVelocity = Vector3.zero; } Collider[] componentsInChildren3 = ((Component)this).GetComponentsInChildren<Collider>(); foreach (Collider val4 in componentsInChildren3) { val4.isTrigger = true; } } private void SetupAnimator() { Animator = ((Component)this).GetComponentInChildren<Animator>(); if ((Object)(object)Animator != (Object)null) { ((Behaviour)Animator).enabled = true; Animator.applyRootMotion = false; ParentConstraint component = ((Component)Animator).GetComponent<ParentConstraint>(); if ((Object)(object)component != (Object)null && !component.constraintActive) { component.constraintActive = true; } DroidFootstepsEventReceiver orAddComponent = ComponentHolderProtocol.GetOrAddComponent<DroidFootstepsEventReceiver>((Object)(object)Animator); orAddComponent.Initialize(this); } else { LOG.Warning("No Animator found on prefab"); } } private void SetupNavigation() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ControllerTransform == (Object)null) { LOG.Error("Cannot setup navigation: Controller is null"); return; } _navAgent = ((Component)ControllerTransform).GetComponent<NavMeshAgent>(); if ((Object)(object)_navAgent == (Object)null) { _navAgent = ((Component)ControllerTransform).gameObject.AddComponent<NavMeshAgent>(); } Vector3 position = ControllerTransform.position; Vector3 val = position; bool flag = false; NavMeshQueryFilter val2 = default(NavMeshQueryFilter); ((NavMeshQueryFilter)(ref val2)).agentTypeID = _savedAgentTypeID; ((NavMeshQueryFilter)(ref val2)).areaMask = _savedAreaMask; NavMeshQueryFilter val3 = val2; float[] array = new float[4] { 5f, 10f, 20f, 50f }; float[] array2 = array; NavMeshHit val4 = default(NavMeshHit); foreach (float num in array2) { if (NavMesh.SamplePosition(position, ref val4, num, val3)) { val = ((NavMeshHit)(ref val4)).position; flag = true; break; } } if (!flag) { LOG.Error($"No NavMesh found near {position}"); return; } ((Behaviour)_navAgent).enabled = false; _navAgent.agentTypeID = _savedAgentTypeID; _navAgent.areaMask = _savedAreaMask; _navAgent.baseOffset = 0f; _navAgent.speed = 2f; _navAgent.angularSpeed = 999f; _navAgent.acceleration = 15f; _navAgent.stoppingDistance = 0f; _navAgent.autoBraking = true; _navAgent.updatePosition = false; _navAgent.updateRotation = false; _navAgent.radius = 0.7f; _navAgent.height = 2f; _navAgent.obstacleAvoidanceType = (ObstacleAvoidanceType)4; _navAgent.avoidancePriority = 10; _navAgent.autoTraverseOffMeshLink = true; _navAgent.autoRepath = true; ControllerTransform.position = val; _navAgent.Warp(val); ((Behaviour)_navAgent).enabled = true; SetupCharacterController(); } private void SetupCharacterController() { //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)ControllerTransform == (Object)null)) { CharacterController component = ((Component)ControllerTransform).GetComponent<CharacterController>(); if ((Object)(object)component != (Object)null) { Object.DestroyImmediate((Object)(object)component); } _charController = ((Component)ControllerTransform).gameObject.AddComponent<CharacterController>(); _charController.height = 2f; _charController.radius = 0.5f; _charController.center = new Vector3(0f, 1f, 0f); _charController.slopeLimit = 45f; _charController.stepOffset = 0.3f; _charController.skinWidth = 0.08f; _charController.minMoveDistance = 0.001f; } } } public sealed class DroidDebuff : MonoBehaviour { private static readonly VepLogger LOG = VepLogger.Create<DroidDebuff>(); private readonly Dictionary<PlayerAvatar, DroidController> _droids = new Dictionary<PlayerAvatar, DroidController>(); private WhispralDebuffManager _debuffManager; private InvisiblePlayerDebuff _invisiblePlayerDebuff; public bool IsActive { get; private set; } private void Update() { if (IsActive && !((Object)(object)_invisiblePlayerDebuff == (Object)null)) { SyncHallucinations(); } } private void OnDestroy() { DestroyAllHallucinations(); } public void ApplyDebuff(bool active, InvisiblePlayerDebuff sourcePlayerDebuff) { if (!SemiFunc.IsMultiplayer()) { LOG.Debug("Singleplayer mode detected, skipping hallucinations."); return; } IsActive = active; _invisiblePlayerDebuff = sourcePlayerDebuff; _debuffManager = ((Component)this).GetComponent<WhispralDebuffManager>(); if (active) { CreateHallucinations(); } else { DestroyAllHallucinations(); } } public DroidController? GetDroidByPlayerName(string playerName) { foreach (KeyValuePair<PlayerAvatar, DroidController> droid in _droids) { if (Object.op_Implicit((Object)(object)droid.Key) && Object.op_Implicit((Object)(object)droid.Value) && droid.Key.playerName == playerName) { return droid.Value; } } return null; } private void CreateHallucination(PlayerAvatar sourcePlayer) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) LOG.Debug("Creating hallucination for player " + sourcePlayer.playerName); if (!DroidPrefabLoader.IsAvailable) { LOG.Warning("LostDroid prefab not available - cannot create hallucination"); return; } Vector3? val = FindSpawnPosition(); if (!val.HasValue) { LOG.Warning("Could not find spawn position for hallucination of " + sourcePlayer.playerName); return; } DroidController droidController = DroidController.Create(sourcePlayer, val.Value); if ((Object)(object)droidController == (Object)null) { LOG.Warning("Hallucination for " + sourcePlayer.playerName + " failed to create"); return; } _droids[sourcePlayer] = droidController; LOG.Debug($"Hallucination created at {((Component)droidController).transform.position}"); } private void CreateHallucinations() { if ((Object)(object)_invisiblePlayerDebuff == (Object)null) { return; } LOG.Debug("Creating hallucinations for hidden players."); foreach (PlayerAvatar hiddenPlayer in _invisiblePlayerDebuff.HiddenPlayers) { if (Object.op_Implicit((Object)(object)hiddenPlayer) && !_droids.ContainsKey(hiddenPlayer)) { CreateHallucination(hiddenPlayer); } } } private void DestroyAllHallucinations() { LOG.Debug("Destroying all hallucinations."); foreach (KeyValuePair<PlayerAvatar, DroidController> droid in _droids) { if (Object.op_Implicit((Object)(object)droid.Value)) { Object.Destroy((Object)(object)((Component)droid.Value).gameObject); } } _droids.Clear(); } private void DestroyHallucination(PlayerAvatar? player) { if (!((Object)(object)player == (Object)null) && _droids.TryGetValue(player, out DroidController value)) { LOG.Debug("Destroying hallucination for player " + player.playerName); if (Object.op_Implicit((Object)(object)value)) { Object.Destroy((Object)(object)((Component)value).gameObject); } _droids.Remove(player); } } private Vector3? FindSpawnPosition() { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_debuffManager != (Object)null) { Vector3? precomputedSpawnPosition = _debuffManager.GetPrecomputedSpawnPosition(); if (precomputedSpawnPosition.HasValue) { LOG.Debug($"Using precomputed spawn position: {precomputedSpawnPosition.Value}"); return precomputedSpawnPosition.Value; } } LOG.Warning("No precomputed position available, falling back to sync search"); Vector3 position = ((Component)PlayerAvatar.instance).transform.position; LevelPoint val = SemiFunc.LevelPointGet(position, 5f, 15f) ?? SemiFunc.LevelPointGet(position, 0f, 999f); if (!Object.op_Implicit((Object)(object)val)) { LOG.Warning("No LevelPoint found for hallucination spawn"); return null; } return ((Component)val).transform.position; } private void SyncHallucinations() { IReadOnlyList<PlayerAvatar> hiddenPlayers = _invisiblePlayerDebuff.HiddenPlayers; foreach (PlayerAvatar item in hiddenPlayers) { if (Object.op_Implicit((Object)(object)item) && !_droids.ContainsKey(item)) { CreateHallucination(item); } } List<PlayerAvatar> list = new List<PlayerAvatar>(); foreach (KeyValuePair<PlayerAvatar, DroidController> droid in _droids) { if (!Object.op_Implicit((Object)(object)droid.Key) || !Object.op_Implicit((Object)(object)droid.Value) || !hiddenPlayers.Contains(droid.Key)) { list.Add(droid.Key); } } foreach (PlayerAvatar item2 in list) { DestroyHallucination(item2); } } } public sealed class DroidFaceAnimationController : MonoBehaviour { private static class AngryExpression { public const float UpperLidAngleLeft = -34f; public const float UpperLidAngleRight = 34f; public const float UpperLidClosed = 83f; public const float LowerLidClosed = -83f; } private const float LookAtAngle = 50f; private const float LookAtMaxDistance = 30f; private const float AngryEyesCooldown = 0.3f; private const float TalkRotationMaxAngle = 25f; private const int SampleDataLength = 256; private const float StalkStareBeforeFlee = 3.030303f; private static readonly VepLogger LOG = VepLogger.Create<DroidFaceAnimationController>(); private float _angryTimer; private Transform _controllerTransform; private DroidController _droidController; private GameObject? _eyelidsLeft; private GameObject? _eyelidsRight; private Transform? _headTopTransform; private bool _isAngry; private Transform? _leftLowerEyelidRotationX; private Transform? _leftUpperEyelidRotationX; private Transform? _leftUpperEyelidRotationZ; private Transform? _rightLowerEyelidRotationX; private Transform? _rightUpperEyelidRotationX; private Transform? _rightUpperEyelidRotationZ; private float[]? _sampleData; private AudioSource? _talkingAudioSource; private bool _wasPlayerLooking; public bool IsPlayerLookingAtMe { get; private set; } public void Initialize(DroidController droidController, Transform controllerTransform) { _droidController = droidController; _controllerTransform = droidController.ControllerTransform; } public void SetupEyelids(GameObject? eyelidsLeft, GameObject? eyelidsRight, Transform? leftUpperX, Transform? leftUpperZ, Transform? leftLowerX, Transform? rightUpperX, Transform? rightUpperZ, Transform? rightLowerX) { _eyelidsLeft = eyelidsLeft; _eyelidsRight = eyelidsRight; _leftUpperEyelidRotationX = leftUpperX; _leftUpperEyelidRotationZ = leftUpperZ; _leftLowerEyelidRotationX = leftLowerX; _rightUpperEyelidRotationX = rightUpperX; _rightUpperEyelidRotationZ = rightUpperZ; _rightLowerEyelidRotationX = rightLowerX; } public void SetupTalking(Transform headTopTransform) { _headTopTransform = headTopTransform; } public void UpdateAnimations() { UpdatePlayerLookDetection(); UpdateAngryEyes(); UpdateTalkingAnimation(); } private void UpdateAngryEyes() { //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01f9: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_026f: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_eyelidsLeft == (Object)null || (Object)(object)_eyelidsRight == (Object)null || (Object)(object)_leftUpperEyelidRotationX == (Object)null || (Object)(object)_rightUpperEyelidRotationX == (Object)null) { return; } if (IsPlayerLookingAtMe && !_wasPlayerLooking) { _angryTimer = (_droidController.IsStalking ? 3.030303f : 0.3f); } _wasPlayerLooking = IsPlayerLookingAtMe; if (IsPlayerLookingAtMe) { _angryTimer -= Time.deltaTime; if (_angryTimer <= 0f) { _isAngry = false; } } else { _isAngry = true; } if (_isAngry && !_eyelidsLeft.activeSelf) { _eyelidsLeft.SetActive(true); _eyelidsRight.SetActive(true); } float num = (_isAngry ? 83f : 0f); float num2 = (_isAngry ? (-83f) : 0f); float num3 = (_isAngry ? (-34f) : 0f); float num4 = (_isAngry ? 34f : 0f); float num5 = Time.deltaTime * 8f; _leftUpperEyelidRotationX.localRotation = Quaternion.Slerp(_leftUpperEyelidRotationX.localRotation, Quaternion.Euler(num, 0f, 0f), num5); _rightUpperEyelidRotationX.localRotation = Quaternion.Slerp(_rightUpperEyelidRotationX.localRotation, Quaternion.Euler(num, 0f, 0f), num5); if ((Object)(object)_leftUpperEyelidRotationZ != (Object)null) { _leftUpperEyelidRotationZ.localRotation = Quaternion.Slerp(_leftUpperEyelidRotationZ.localRotation, Quaternion.Euler(0f, 0f, num3), num5); } if ((Object)(object)_rightUpperEyelidRotationZ != (Object)null) { _rightUpperEyelidRotationZ.localRotation = Quaternion.Slerp(_rightUpperEyelidRotationZ.localRotation, Quaternion.Euler(0f, 0f, num4), num5); } if ((Object)(object)_leftLowerEyelidRotationX != (Object)null) { _leftLowerEyelidRotationX.localRotation = Quaternion.Slerp(_leftLowerEyelidRotationX.localRotation, Quaternion.Euler(num2, 0f, 0f), num5); } if ((Object)(object)_rightLowerEyelidRotationX != (Object)null) { _rightLowerEyelidRotationX.localRotation = Quaternion.Slerp(_rightLowerEyelidRotationX.localRotation, Quaternion.Euler(num2, 0f, 0f), num5); } if (!_isAngry && _eyelidsLeft.activeSelf) { float num6 = Mathf.Abs(_leftUpperEyelidRotationX.localEulerAngles.x); if ((num6 < 10f || num6 > 350f) ? true : false) { _eyelidsLeft.SetActive(false); _eyelidsRight.SetActive(false); } } } private void UpdatePlayerLookDetection() { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) Camera main = Camera.main; if ((Object)(object)main == (Object)null || (Object)(object)_controllerTransform == (Object)null) { IsPlayerLookingAtMe = false; return; } Vector3 val = _controllerTransform.position + Vector3.up; Vector3 position = ((Component)main).transform.position; float num = Vector3.Distance(position, val); if (num > 30f) { IsPlayerLookingAtMe = false; return; } Vector3 val2 = val - position; Vector3 normalized = ((Vector3)(ref val2)).normalized; float num2 = Vector3.Dot(((Component)main).transform.forward, normalized); float num3 = Mathf.Cos(0.87266463f); IsPlayerLookingAtMe = num2 >= num3; } private void UpdateTalkingAnimation() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_headTopTransform == (Object)null) { return; } float num = 0f; if ((Object)(object)_talkingAudioSource == (Object)null && (Object)(object)_controllerTransform != (Object)null) { _talkingAudioSource = ((Component)_controllerTransform).GetComponent<AudioSource>(); } if ((Object)(object)_talkingAudioSource != (Object)null && _talkingAudioSource.isPlaying) { if (_sampleData == null) { _sampleData = new float[256]; } _talkingAudioSource.GetOutputData(_sampleData, 0); float num2 = 0f; float[] sampleData = _sampleData; foreach (float num3 in sampleData) { num2 += Mathf.Abs(num3); } num2 /= 256f; if (num2 > 0.01f) { num = Mathf.Lerp(0f, -25f, num2 * 10f); } } else { _talkingAudioSource = null; } _headTopTransform.localRotation = Quaternion.Slerp(_headTopTransform.localRotation, Quaternion.Euler(num, 0f, 0f), Time.deltaTime * 20f); } } public sealed class DroidFootstepsEventReceiver : MonoBehaviour { private static readonly VepLogger LOG = VepLogger.Create<DroidFootstepsEventReceiver>(); private DroidController _droid; public void Initialize(DroidController droidController) { _droid = droidController; } public void PlayMediumFootstep() { _droid.PlayMediumFootstep(); } } public static class DroidHelpers { public static bool IsMovementState(DroidController.StateId state) { if ((uint)(state - 1) <= 1u || (uint)(state - 4) <= 2u) { return true; } return false; } public static Transform? FindChildByName(Transform? root, string name, bool includeInactive = true) { if ((Object)(object)root == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(includeInactive); foreach (Transform val in componentsInChildren) { if (((Object)val).name == name) { return val; } } return null; } public static void FindChildrenByNames(Transform root, bool includeInactive, params (string name, Action<Transform> onFound)[] searches) { if ((Object)(object)root == (Object)null) { return; } int num = searches.Length; Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren<Transform>(includeInactive); foreach (Transform val in componentsInChildren) { for (int j = 0; j < searches.Length; j++) { var (text, action) = searches[j]; if (((Object)val).name == text) { action(val); num--; if (num == 0) { return; } } } } } public static bool TryGetNavMeshPosition(Vector3 position, out Vector3 result, int areaMask, float maxDistance = 5f) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val, maxDistance, areaMask)) { result = ((NavMeshHit)(ref val)).position; return true; } result = position; return false; } public static AnimationClip? GetAnimationClip(Animator animator, string clipName) { if ((Object)(object)animator == (Object)null || (Object)(object)animator.runtimeAnimatorController == (Object)null) { return null; } AnimationClip[] animationClips = animator.runtimeAnimatorController.animationClips; foreach (AnimationClip val in animationClips) { if (((Object)val).name == clipName) { return val; } } return null; } public static bool IsNavAgentValid(NavMeshAgent agent) { if ((Object)(object)agent != (Object)null) { return agent.isOnNavMesh; } return false; } public static Vector3? GetLocalPlayerPosition() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar instance = PlayerAvatar.instance; if (!((Object)(object)instance != (Object)null)) { return null; } return ((Component)instance).transform.position; } } public static class DroidMaterialFixer { private const string HurtableShaderName = "Hurtable/Hurtable"; private static readonly VepLogger LOG = VepLogger.Create("DroidMaterialFixer"); private static Shader? _cachedShader; public static int FixMaterials(GameObject target) { Shader hurtableShader = GetHurtableShader(); if ((Object)(object)hurtableShader == (Object)null) { LOG.Warning("Shader 'Hurtable/Hurtable' not found - materials may not display correctly"); return 0; } return ApplyShader(target, hurtableShader); } private static int ApplyShader(GameObject target, Shader shader) { int num = 0; Renderer[] componentsInChildren = target.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { Material[] materials = val.materials; foreach (Material val2 in materials) { if (NeedsShaderFix(val2)) { val2.shader = shader; num++; } } } if (num > 0) { LOG.Info(string.Format("Fixed {0} materials with shader '{1}'", num, "Hurtable/Hurtable")); } return num; } public static void ClearCache() { _cachedShader = null; } private static bool NeedsShaderFix(Material material) { if ((Object)(object)material == (Object)null) { return false; } if ((Object)(object)material.shader == (Object)null) { return true; } if (((Object)material.shader).name == "Hidden/InternalErrorShader") { return true; } if (((Object)material.shader).name != "Hurtable/Hurtable") { return true; } return false; } private static Shader? GetHurtableShader() { if ((Object)(object)_cachedShader != (Object)null) { return _cachedShader; } _cachedShader = Shader.Find("Hurtable/Hurtable"); if ((Object)(object)_cachedShader != (Object)null) { return _cachedShader; } _cachedShader = FindShaderInPlayerAvatars("Hurtable/Hurtable"); return _cachedShader; } private static Shader? FindShaderInPlayerAvatars(string shaderName) { PlayerAvatarVisuals[] array = Object.FindObjectsOfType<PlayerAvatarVisuals>(true); PlayerAvatarVisuals[] array2 = array; foreach (PlayerAvatarVisuals val in array2) { Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true); foreach (Renderer val2 in componentsInChildren) { Material[] sharedMaterials = val2.sharedMaterials; foreach (Material val3 in sharedMaterials) { if ((Object)(object)val3 != (Object)null && (Object)(object)val3.shader != (Object)null && ((Object)val3.shader).name == shaderName) { return val3.shader; } } } } return null; } } public sealed class DroidMovementController : MonoBehaviour { [CompilerGenerated] private sealed class <PrecomputeDestinationCoroutine>d__46 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DroidMovementController <>4__this; private LevelPoint <levelPoint>5__2; private NavMeshHit <hit>5__3; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PrecomputeDestinationCoroutine>d__46(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <levelPoint>5__2 = null; <>1__state = -2; } private bool MoveNext() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; DroidMovementController droidMovementController = <>4__this; switch (num) { default: return false; case 0: { <>1__state = -1; droidMovementController._isPrecomputingDestination = true; Vector3 val2 = (((Object)(object)droidMovementController._controllerTransform != (Object)null) ? droidMovementController._controllerTransform.position : ((Component)droidMovementController).transform.position); <levelPoint>5__2 = SemiFunc.LevelPointGet(val2, 5f, 15f) ?? SemiFunc.LevelPointGet(val2, 0f, 20f); if ((Object)(object)<levelPoint>5__2 == (Object)null) { droidMovementController._isPrecomputingDestination = false; return false; } <>2__current = null; <>1__state = 1; return true; } case 1: { <>1__state = -1; Vector3 position = ((Component)<levelPoint>5__2).transform.position; if (!NavMesh.SamplePosition(position, ref <hit>5__3, 5f, droidMovementController._savedAreaMask)) { droidMovementController._isPrecomputingDestination = false; return false; } <>2__current = null; <>1__state = 2; return true; } case 2: { <>1__state = -1; if (!Physics.Raycast(((NavMeshHit)(ref <hit>5__3)).position + Vector3.up, Vector3.down, 5f, LayerMask.GetMask(new string[1] { "Default" }))) { droidMovementController._isPrecomputingDestination = false; return false; } NavMeshPath val = new NavMeshPath(); if (DroidHelpers.IsNavAgentValid(droidMovementController._navAgent) && droidMovementController._navAgent.CalculatePath(((NavMeshHit)(ref <hit>5__3)).position, val) && (int)val.status == 0) { droidMovementController._precomputedDestination = ((NavMeshHit)(ref <hit>5__3)).position; } droidMovementController._isPrecomputingDestination = false; return false; } } } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } [CompilerGenerated] private sealed class <PrecomputeForwardDestinationCoroutine>d__49 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public DroidMovementController <>4__this; public float maxAngleDeviation; public float minDistance; public float maxDistance; private Vector3 <direction>5__2; private string <directionSource>5__3; private Vector3 <targetPos>5__4; private NavMeshHit <hit>5__5; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <PrecomputeForwardDestinationCoroutine>d__49(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <directionSource>5__3 = null; <>1__state = -2; } private bool MoveNext() { //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016c: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0222: Expected O, but got Unknown //IL_022e: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_0255: Unknown result type (might be due to invalid IL or missing references) //IL_023e: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) int num = <>1__state; DroidMovementController droidMovementController = <>4__this; switch (num) { default: return false; case 0: <>1__state = -1; droidMovementController._isPrecomputingForward = true; LOG.Debug("PrecomputeForward: Starting coroutine"); if ((Object)(object)droidMovementController._controllerTransform == (Object)null || !DroidHelpers.IsNavAgentValid(droidMovementController._navAgent)) { LOG.Debug("PrecomputeForward: Invalid controller or NavAgent"); droidMovementController._isPrecomputingForward = false; return false; } <direction>5__2 = ((Vector3)(ref droidMovementController._currentVelocity)).normalized; <directionSource>5__3 = "velocity"; if (((Vector3)(ref <direction>5__2)).sqrMagnitude < 0.01f) { Vector3 val2 = droidMovementController._destination - droidMovementController._controllerTransform.position; <direction>5__2 = ((Vector3)(ref val2)).normalized; <directionSource>5__3 = "destination"; } if (((Vector3)(ref <direction>5__2)).sqrMagnitude < 0.01f) { LOG.Debug("PrecomputeForward: No valid direction found"); droidMovementController._isPrecomputingForward = false; return false; } <>2__current = null; <>1__state = 1; return true; case 1: { <>1__state = -1; float num2 = Random.Range(0f - maxAngleDeviation, maxAngleDeviation); <direction>5__2 = Quaternion.Euler(0f, num2, 0f) * <direction>5__2; float num3 = Random.Range(minDistance, maxDistance); Vector3 position = droidMovementController._controllerTransform.position; <targetPos>5__4 = position + <direction>5__2 * num3; LOG.Debug($"PrecomputeForward: source={<directionSource>5__3}, angle={num2:F1}°, dist={num3:F1}m"); <>2__current = null; <>1__state = 2; return true; } case 2: <>1__state = -1; if (!NavMesh.SamplePosition(<targetPos>5__4, ref <hit>5__5, 10f, droidMovementController._savedAreaMask)) { LOG.Debug($"PrecomputeForward: No NavMesh position found near {<targetPos>5__4}"); droidMovementController._isPrecomputingForward = false; return false; } <>2__current = null; <>1__state = 3; return true; case 3: { <>1__state = -1; NavMeshPath val = new NavMeshPath(); if (!droidMovementController._navAgent.CalculatePath(((NavMeshHit)(ref <hit>5__5)).position, val) || (int)val.status != 0) { LOG.Debug($"PrecomputeForward: Path calculation failed to {((NavMeshHit)(ref <hit>5__5)).position}"); droidMovementController._isPrecomputingForward = false; return false; } droidMovementController._precomputedForwardDestination = ((NavMeshHit)(ref <hit>5__5)).position; LOG.Debug($"PrecomputeForward: SUCCESS - precomputed destination at {((NavMeshHit)(ref <hit>5__5)).position}"); droidMovementController._isPrecomputingForward = false; return false; }