using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text.Json;
using BoneLib.BoneMenu;
using MelonLoader;
using Microsoft.CodeAnalysis;
using MimicMod;
using UnityEngine;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "Mimic Mod", "0.6.0", "GoldenNull", null)]
[assembly: MelonGame("Stress Level Zero", "BONELAB")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("MimicMod")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MimicMod")]
[assembly: AssemblyTitle("MimicMod")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[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 MimicMod
{
internal sealed class MimicAI : IDisposable
{
private sealed class BotRuntime
{
public float NextAttackAt;
public float AttackModeUntil;
public float AttackWindupUntil;
public bool AttackPending;
public float NextCoverAt;
public Vector3 LastGoal;
public bool HasGoal;
public bool EncounterRecorded;
public float NextRushRecordAt;
public MimicBehavior Behavior = new MimicBehavior();
public float RestoreVisualAt;
public Renderer[] FlickerRenderers;
public bool[] RendererStates;
public Vector3 NavigationTarget;
public Vector3 CurrentWaypoint;
public bool HasNavigationTarget;
public bool HasCurrentWaypoint;
public float NextPathUpdateAt;
public Vector3 LastKnownPlayerPosition;
public float LastSeenPlayerAt = -1000f;
public float NextInvestigationAt;
public bool HasLastKnownPlayerPosition;
}
private readonly Instance _log;
private MimicSettings _settings = new MimicSettings();
private MimicLearning _learning;
private MimicEncounters _encounters;
private float _nextJumpscareAt;
private float _nextLearningSampleAt;
private readonly ArrayList _bots = new ArrayList();
private readonly Dictionary<object, BotRuntime> _runtime = new Dictionary<object, BotRuntime>();
private readonly List<GameObject> _goalObjects = new List<GameObject>();
private readonly Dictionary<object, GameObject> _goalMarkers = new Dictionary<object, GameObject>();
private Type _managerType;
private PropertyInfo _allProperty;
private bool _enabled;
private bool _selfAware;
private bool _coverEnabled = true;
private bool _attacksEnabled = true;
private bool _visualGlitches;
private bool _disposed;
private bool _coverWarningLogged;
private bool _pathfindingEnabled = true;
private float _pathRefreshInterval = 0.8f;
private float _obstacleClearance = 1.4f;
private float _waypointReachDistance = 1.1f;
private float _nextRefresh;
private float _nextDecision;
private float _nextGlitch;
private float _sceneRefreshUntil;
private int _decision;
private const BindingFlags Flags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
private const float AttackRange = 2.15f;
private const float AttackWindup = 0.55f;
private const float CoverRadius = 5.5f;
public MimicAI(Instance logger)
{
_log = logger;
ResolveDoppel();
}
public void NotifySceneLoaded(string sceneName)
{
_bots.Clear();
_runtime.Clear();
_goalMarkers.Clear();
for (int i = 0; i < _goalObjects.Count; i++)
{
try
{
if ((Object)(object)_goalObjects[i] != (Object)null)
{
Object.Destroy((Object)(object)_goalObjects[i]);
}
}
catch
{
}
}
_goalObjects.Clear();
_managerType = null;
_allProperty = null;
_nextRefresh = 0f;
_nextDecision = 0f;
_nextLearningSampleAt = 0f;
_sceneRefreshUntil = Time.time + 30f;
_log.Msg("Mimic detected level load/reload ('" + (sceneName ?? "unknown") + "'); refreshing Doppel bots.");
}
public void Configure(MimicSettings settings, MimicLearning learning, MimicEncounters encounters)
{
_settings = settings ?? new MimicSettings();
_settings.ClampValues();
_learning = learning;
_encounters = encounters;
_selfAware = _settings.selfAwareEnabled;
_coverEnabled = _settings.stalkingEnabled;
_attacksEnabled = _settings.attacksEnabled && _settings.behaviorMode != MimicBehaviorMode.NonHostile && _settings.behaviorMode != MimicBehaviorMode.Jumpscare;
_visualGlitches = _settings.visualGlitchesEnabled || _settings.behaviorMode == MimicBehaviorMode.Jumpscare;
_pathfindingEnabled = _settings.pathfindingEnabled;
_pathRefreshInterval = _settings.pathRefreshInterval;
_obstacleClearance = _settings.obstacleClearance;
_waypointReachDistance = _settings.waypointReachDistance;
}
public void SetEnabled(bool enabled)
{
if (_enabled != enabled)
{
_enabled = enabled;
if (!enabled)
{
RestoreBots();
}
else
{
_nextRefresh = 0f;
_sceneRefreshUntil = Time.time + 30f;
RefreshBots();
_nextDecision = Time.time + 0.5f;
}
_log.Msg("Mimic AI " + (enabled ? "enabled." : "disabled.") + ".");
}
}
public void SetSelfAware(bool enabled)
{
_selfAware = enabled;
_log.Msg("Experimental self-aware behavior " + (enabled ? "enabled." : "disabled.") + ".");
}
public void SetCoverEnabled(bool enabled)
{
_coverEnabled = enabled;
_log.Msg("Cover seeking and stalking " + (enabled ? "enabled." : "disabled.") + ".");
}
public void SetAttacksEnabled(bool enabled)
{
_attacksEnabled = enabled;
_log.Msg("Close-range attacks " + (enabled ? "enabled." : "disabled.") + ".");
}
public void SetVisualGlitches(bool enabled)
{
_visualGlitches = enabled;
if (!enabled)
{
RestoreAllFlickers();
}
_log.Msg("Visual glitches " + (enabled ? "enabled." : "disabled.") + ".");
}
public void RefreshBots()
{
RefreshBots(logResult: true);
}
private void RefreshBots(bool logResult)
{
ResolveDoppel();
_bots.Clear();
if (_allProperty == null)
{
if (logResult)
{
_log.Warning("Doppel BotManager.All was not found. Ensure Doppel is installed and loaded.");
}
return;
}
try
{
if (_allProperty.GetValue(null, null) is IEnumerable enumerable)
{
foreach (object item in enumerable)
{
if (item != null)
{
_bots.Add(item);
if (!_runtime.ContainsKey(item))
{
_runtime[item] = new BotRuntime();
}
}
}
}
List<object> list = null;
foreach (object key in _runtime.Keys)
{
bool flag = false;
for (int i = 0; i < _bots.Count; i++)
{
if (key == _bots[i] || object.Equals(key, _bots[i]))
{
flag = true;
break;
}
}
if (!flag)
{
if (list == null)
{
list = new List<object>();
}
list.Add(key);
}
}
if (list != null)
{
for (int j = 0; j < list.Count; j++)
{
_runtime.Remove(list[j]);
}
}
if (logResult)
{
_log.Msg("Mimic found " + _bots.Count + " existing Doppel bot(s).");
}
}
catch (Exception ex)
{
if (logResult)
{
_log.Error("Doppel bot refresh failed: " + ex.Message);
}
}
}
private void ResolveDoppel()
{
if (_managerType != null && _allProperty != null)
{
return;
}
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
try
{
Type type = assembly.GetType("ThirdEyeBonelabMod.Bots.BotManager", throwOnError: false);
if (type == null)
{
continue;
}
_managerType = type;
_allProperty = type.GetProperty("All", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
break;
}
catch
{
}
}
}
public void Update()
{
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_0219: Unknown result type (might be due to invalid IL or missing references)
//IL_022f: 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_02c3: Unknown result type (might be due to invalid IL or missing references)
//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
//IL_04aa: Unknown result type (might be due to invalid IL or missing references)
//IL_07ed: Unknown result type (might be due to invalid IL or missing references)
//IL_07f3: Unknown result type (might be due to invalid IL or missing references)
//IL_0588: Unknown result type (might be due to invalid IL or missing references)
//IL_0804: Unknown result type (might be due to invalid IL or missing references)
//IL_05ca: Unknown result type (might be due to invalid IL or missing references)
//IL_05d0: Unknown result type (might be due to invalid IL or missing references)
//IL_080f: Unknown result type (might be due to invalid IL or missing references)
//IL_0811: Unknown result type (might be due to invalid IL or missing references)
//IL_05e1: Unknown result type (might be due to invalid IL or missing references)
//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
//IL_05ee: Unknown result type (might be due to invalid IL or missing references)
if (_disposed)
{
return;
}
UpdateFlickerRestores();
if (!_enabled)
{
return;
}
if (Time.time >= _nextRefresh)
{
bool flag = Time.time < _sceneRefreshUntil;
_nextRefresh = Time.time + (flag ? 1f : 8f);
RefreshBots(logResult: false);
if (_bots.Count > 0)
{
_sceneRefreshUntil = 0f;
_nextRefresh = Time.time + 8f;
}
}
if (_visualGlitches && Time.time >= _nextGlitch)
{
_nextGlitch = Time.time + Random.Range(8f, 18f);
TryStartRandomFlicker();
}
if (Time.time < _nextDecision || _bots.Count == 0)
{
return;
}
_nextDecision = Time.time + 0.35f;
Transform val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform : null);
if ((Object)(object)val == (Object)null)
{
return;
}
MimicLearning mimicLearning = (_settings.learningEnabled ? _learning : null);
if (mimicLearning != null && Time.time >= _nextLearningSampleAt)
{
_nextLearningSampleAt = Time.time + 0.4f;
mimicLearning.Observe(val.position, val.forward, Time.time);
}
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
for (int num5 = _bots.Count - 1; num5 >= 0; num5--)
{
object obj = _bots[num5];
if (obj == null)
{
_bots.RemoveAt(num5);
continue;
}
BotRuntime runtime = GetRuntime(obj);
Transform botTransform = GetBotTransform(obj);
if ((Object)(object)botTransform == (Object)null)
{
SetModeIfDifferent(obj, "Brain");
continue;
}
UpdatePathfinding(obj, botTransform, runtime);
float num6 = Vector3.Distance(botTransform.position, val.position);
bool flag2 = IsPlayerLookingAt(val, botTransform.position, num6, _settings.selfAwareDistance, _settings.selfAwareLookDot) && HasLineOfSight(val.position, botTransform.position);
if (flag2)
{
runtime.LastKnownPlayerPosition = val.position;
runtime.LastSeenPlayerAt = Time.time;
runtime.HasLastKnownPlayerPosition = true;
}
if (_selfAware && !flag2 && runtime.HasLastKnownPlayerPosition && Time.time - runtime.LastSeenPlayerAt <= _settings.selfAwareMemorySeconds && num6 > 2.15f && Time.time >= runtime.NextInvestigationAt)
{
runtime.NextInvestigationAt = Time.time + Mathf.Max(0.5f, _settings.pathRefreshInterval);
if (TrySetGoal(obj, runtime.LastKnownPlayerPosition))
{
SetModeIfDifferent(obj, "Brain");
}
else
{
SetModeIfDifferent(obj, "Follow");
}
continue;
}
if (_encounters != null && num6 < 20f && !runtime.EncounterRecorded)
{
_encounters.Record("encounter", "Mimic entered player proximity; distance=" + num6.ToString("F1"));
runtime.EncounterRecorded = true;
}
if (num6 > 25f)
{
runtime.EncounterRecorded = false;
}
if (_settings.behaviorMode == MimicBehaviorMode.Jumpscare)
{
if (num6 <= 5f && flag2 && Time.time >= _nextJumpscareAt)
{
_nextJumpscareAt = Time.time + _settings.jumpscareCooldown;
if (_visualGlitches)
{
TryStartFlickerForBot(obj);
}
if (_encounters != null)
{
_encounters.Record("jumpscare", "Close-range jumpscare trigger; recorded audio feature is disabled.");
}
}
if (num6 > 2.15f)
{
if (!TrySetRushMode(obj))
{
SetModeIfDifferent(obj, "Follow");
}
}
else
{
SetModeIfDifferent(obj, "Stand");
}
continue;
}
if (_settings.behaviorMode == MimicBehaviorMode.NonHostile)
{
runtime.AttackPending = false;
runtime.AttackModeUntil = 0f;
if (!SetModeIfDifferent(obj, "Wander"))
{
SetModeIfDifferent(obj, "Stand");
}
continue;
}
if (_settings.behaviorMode == MimicBehaviorMode.RuthlessAttacker && num6 > 2.15f)
{
if (!TrySetRushMode(obj))
{
SetModeIfDifferent(obj, "Follow");
}
continue;
}
if (_settings.behaviorMode == MimicBehaviorMode.AdaptiveStalker)
{
MimicAction mimicAction = runtime.Behavior.Decide(_settings, mimicLearning, Time.time, num6, flag2, HasLineOfSight(val.position, botTransform.position), mimicLearning != null && mimicLearning.AverageSpeed() > 0.12f, num6 <= 2.15f, Time.time >= _nextJumpscareAt);
if (_coverEnabled && mimicAction == MimicAction.Rush)
{
if (!TrySetRushMode(obj))
{
SetModeIfDifferent(obj, "Follow");
}
if (_encounters != null && Time.time >= runtime.NextRushRecordAt)
{
_encounters.Record("rush", "Adaptive behavior selected a rush.");
runtime.NextRushRecordAt = Time.time + 5f;
}
continue;
}
if (_coverEnabled && mimicAction == MimicAction.Stalk)
{
SetModeIfDifferent(obj, "Follow");
continue;
}
if (_coverEnabled && mimicAction == MimicAction.Investigate)
{
if (TrySetGoal(obj, val.position))
{
SetModeIfDifferent(obj, "Brain");
}
else
{
SetModeIfDifferent(obj, "Follow");
}
continue;
}
if (mimicAction == MimicAction.TakeCover && _coverEnabled && TryFindCover(botTransform.position, val.position, out var result) && TrySetGoal(obj, result))
{
runtime.LastGoal = result;
runtime.HasGoal = true;
SetModeIfDifferent(obj, "Brain");
continue;
}
}
if (_selfAware && flag2 && num6 < 20f)
{
SetModeIfDifferent(obj, "Stand");
num4++;
continue;
}
if (_attacksEnabled && num6 <= 2.15f)
{
if (runtime.AttackPending)
{
if (Time.time < runtime.AttackWindupUntil)
{
SetModeIfDifferent(obj, "Stand");
continue;
}
runtime.AttackPending = false;
runtime.AttackModeUntil = Time.time + 0.8f;
SetModeIfDifferent(obj, "Fists");
if (_encounters != null)
{
_encounters.Record("attack", "Doppel Fists mode entered after wind-up.");
}
num++;
}
else if (runtime.AttackModeUntil > Time.time)
{
SetModeIfDifferent(obj, "Fists");
num++;
}
else if (Time.time >= runtime.NextAttackAt)
{
runtime.AttackPending = true;
runtime.AttackWindupUntil = Time.time + 0.55f;
runtime.NextAttackAt = Time.time + Mathf.Max(0.5f, _settings.attackCooldown);
SetModeIfDifferent(obj, "Stand");
}
else
{
SetModeIfDifferent(obj, "Brain");
}
continue;
}
if (runtime.AttackModeUntil > 0f && runtime.AttackModeUntil <= Time.time)
{
runtime.AttackModeUntil = 0f;
SetModeIfDifferent(obj, "Brain");
}
if (num6 > 2.15f && runtime.AttackPending)
{
runtime.AttackPending = false;
}
bool flag3 = false;
if (_coverEnabled && Time.time >= runtime.NextCoverAt)
{
runtime.NextCoverAt = Time.time + Random.Range(2.8f, 4.8f);
if (TryFindCover(botTransform.position, val.position, out var result2) && TrySetGoal(obj, result2))
{
runtime.LastGoal = result2;
runtime.HasGoal = true;
if (_encounters != null)
{
_encounters.Record("cover", "Assigned cover goal.");
}
SetModeIfDifferent(obj, "Brain");
num2++;
flag3 = true;
}
}
if (!flag3)
{
int num7 = (_decision + num5) % 9;
string modeName = ((!_coverEnabled) ? "Brain" : (num7 switch
{
5 => "Follow",
0 => "Wander",
_ => "Brain",
}));
SetModeIfDifferent(obj, modeName);
num3++;
}
}
_decision++;
if (num > 0)
{
_log.Msg("Mimic: close-range Doppel combat active for " + num + " bot(s).");
}
else if (num2 > 0)
{
_log.Msg("Mimic: assigned physics-tested cover goal to " + num2 + " bot(s).");
}
else if (num4 > 0)
{
_log.Msg("Mimic self-aware behavior: pausing while observed.");
}
}
private BotRuntime GetRuntime(object bot)
{
if (!_runtime.TryGetValue(bot, out var value))
{
value = new BotRuntime();
_runtime[bot] = value;
}
return value;
}
private bool TryFindCover(Vector3 botPosition, Vector3 playerPosition, out Vector3 result)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_0009: 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_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: 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_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: 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_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
//IL_00ac: 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_00c0: Unknown result type (might be due to invalid IL or missing references)
//IL_00da: 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)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010b: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: 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_0118: Unknown result type (might be due to invalid IL or missing references)
//IL_011d: Unknown result type (might be due to invalid IL or missing references)
//IL_0122: Unknown result type (might be due to invalid IL or missing references)
//IL_0124: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_013d: 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_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0155: Unknown result type (might be due to invalid IL or missing references)
//IL_0157: 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_0179: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: 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)
result = botPosition;
Vector3 val = botPosition - playerPosition;
val.y = 0f;
if (((Vector3)(ref val)).sqrMagnitude < 0.1f)
{
val = Vector3.back;
}
((Vector3)(ref val)).Normalize();
Vector3 val2 = Vector3.Cross(Vector3.up, val);
Vector3 normalized = ((Vector3)(ref val2)).normalized;
float[] array = new float[4] { 2f, 3.2f, 4.5f, 5.5f };
float[] array2 = new float[5] { 0f, 1.3f, -1.3f, 2.4f, -2.4f };
float num = float.MaxValue;
bool result2 = false;
RaycastHit val4 = default(RaycastHit);
RaycastHit val7 = default(RaycastHit);
for (int i = 0; i < array.Length; i++)
{
for (int j = 0; j < array2.Length; j++)
{
Vector3 val3 = playerPosition + val * array[i] + normalized * array2[j];
if (!Physics.Raycast(val3 + Vector3.up * 2.2f, Vector3.down, ref val4, 5f, -1, (QueryTriggerInteraction)1))
{
continue;
}
val3 = ((RaycastHit)(ref val4)).point + Vector3.up * 0.1f;
Vector3 val5 = val3 + Vector3.up * 1.1f;
Vector3 val6 = playerPosition + Vector3.up * 1f - val5;
float magnitude = ((Vector3)(ref val6)).magnitude;
if (!(magnitude < 0.2f) && Physics.Raycast(val5, val6 / magnitude, ref val7, magnitude, -1, (QueryTriggerInteraction)1) && !Physics.CheckSphere(val3 + Vector3.up * 0.7f, 0.28f, -1, (QueryTriggerInteraction)1))
{
float num2 = Vector3.Distance(botPosition, val3) + Vector3.Distance(playerPosition, val3) * 0.25f;
if (num2 < num && Vector3.Distance(botPosition, val3) > 1f)
{
num = num2;
result = val3;
result2 = true;
}
}
}
}
return result2;
}
private static bool HasLineOfSight(Vector3 from, Vector3 to)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_001b: 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)
Vector3 val = to - from;
float magnitude = ((Vector3)(ref val)).magnitude;
if (magnitude < 0.1f)
{
return true;
}
RaycastHit val2 = default(RaycastHit);
return !Physics.Raycast(from, val / magnitude, ref val2, magnitude, -1, (QueryTriggerInteraction)1);
}
private static bool IsPlayerLookingAt(Transform player, Vector3 target, float distance, float maxDistance, float lookDot)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: 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_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
if (distance > maxDistance)
{
return false;
}
Vector3 val = target + Vector3.up * 0.8f - player.position;
if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
{
return true;
}
return Vector3.Dot(player.forward, ((Vector3)(ref val)).normalized) > lookDot;
}
private bool TrySetGoal(object bot, Vector3 goal)
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: 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_007e: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
Transform botTransform = GetBotTransform(bot);
if ((Object)(object)botTransform == (Object)null)
{
return TrySetGoalRaw(bot, goal);
}
BotRuntime runtime = GetRuntime(bot);
runtime.NavigationTarget = goal;
runtime.HasNavigationTarget = _pathfindingEnabled;
runtime.NextPathUpdateAt = 0f;
Vector3 waypoint = goal;
if (_pathfindingEnabled)
{
MimicPathfinder.TryFindWaypoint(botTransform.position, goal, _obstacleClearance, out waypoint);
}
runtime.CurrentWaypoint = waypoint;
runtime.HasCurrentWaypoint = true;
runtime.NextPathUpdateAt = Time.time + _pathRefreshInterval;
return TrySetGoalRaw(bot, waypoint);
}
private void UpdatePathfinding(object bot, Transform botTransform, BotRuntime state)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_0078: Unknown result type (might be due to invalid IL or missing references)
//IL_007a: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
if (_pathfindingEnabled && state.HasNavigationTarget && !((Object)(object)botTransform == (Object)null))
{
if (Vector3.Distance(botTransform.position, state.NavigationTarget) <= _waypointReachDistance)
{
state.HasNavigationTarget = false;
}
else if ((state.HasCurrentWaypoint && Vector3.Distance(botTransform.position, state.CurrentWaypoint) <= _waypointReachDistance) || !(Time.time < state.NextPathUpdateAt))
{
Vector3 waypoint = state.NavigationTarget;
MimicPathfinder.TryFindWaypoint(botTransform.position, state.NavigationTarget, _obstacleClearance, out waypoint);
state.CurrentWaypoint = waypoint;
state.HasCurrentWaypoint = true;
state.NextPathUpdateAt = Time.time + _pathRefreshInterval;
TrySetGoalRaw(bot, waypoint);
}
}
}
private bool TrySetGoalRaw(object bot, Vector3 goal)
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
try
{
Type type = bot.GetType();
FieldInfo field = type.GetField("goal", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && TryConvertGoal(bot, field.FieldType, goal, out var value))
{
field.SetValue(bot, value);
return true;
}
PropertyInfo property = type.GetProperty("goal", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null && property.CanWrite && TryConvertGoal(bot, property.PropertyType, goal, out var value2))
{
property.SetValue(bot, value2, null);
return true;
}
}
catch (Exception ex)
{
if (!_coverWarningLogged)
{
_log.Warning("Doppel goal assignment failed; using built-in AI modes instead. " + ex.Message);
_coverWarningLogged = true;
}
}
if (!_coverWarningLogged)
{
_log.Warning("This Doppel build does not expose a writable compatible 'goal' member. Custom waypoint navigation is unavailable; using Doppel Brain/Wander instead.");
_coverWarningLogged = true;
}
return false;
}
private bool TryConvertGoal(object bot, Type targetType, Vector3 goal, out object value)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: Unknown result type (might be due to invalid IL or missing references)
//IL_0069: Expected O, but got Unknown
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
value = null;
if (targetType == typeof(Vector3))
{
value = goal;
return true;
}
if (targetType == typeof(Transform) || targetType == typeof(GameObject))
{
if (!_goalMarkers.TryGetValue(bot, out var value2) || (Object)(object)value2 == (Object)null)
{
value2 = new GameObject("MimicMod_CoverGoal");
((Object)value2).hideFlags = (HideFlags)61;
_goalMarkers[bot] = value2;
_goalObjects.Add(value2);
}
value2.transform.position = goal;
value = ((targetType == typeof(Transform)) ? ((object)value2.transform) : ((object)value2));
return true;
}
return false;
}
private static Transform GetBotTransform(object bot)
{
try
{
Component val = (Component)((bot is Component) ? bot : null);
if (val != null)
{
return val.transform;
}
GameObject val2 = (GameObject)((bot is GameObject) ? bot : null);
if (val2 != null)
{
return val2.transform;
}
Type type = bot.GetType();
string[] array = new string[3] { "rig", "transform", "gameObject" };
foreach (string name in array)
{
object obj = ReadMember(type, bot, name);
Transform val3 = AsTransform(obj);
if ((Object)(object)val3 != (Object)null)
{
return val3;
}
if (obj != null)
{
Transform val4 = AsTransform(ReadMember(obj.GetType(), obj, "transform"));
if ((Object)(object)val4 != (Object)null)
{
return val4;
}
}
}
}
catch
{
}
return null;
}
private static object ReadMember(Type type, object instance, string name)
{
FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null)
{
return field.GetValue(instance);
}
PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (property != null && property.GetIndexParameters().Length == 0)
{
return property.GetValue(instance, null);
}
return null;
}
private static Transform AsTransform(object value)
{
Transform val = (Transform)((value is Transform) ? value : null);
if (val != null)
{
return val;
}
Component val2 = (Component)((value is Component) ? value : null);
if (val2 != null)
{
return val2.transform;
}
GameObject val3 = (GameObject)((value is GameObject) ? value : null);
if (val3 != null)
{
return val3.transform;
}
return null;
}
private bool SetModeIfDifferent(object bot, string modeName)
{
try
{
Type type = bot.GetType();
MethodInfo method = type.GetMethod("SetMode", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
if (method == null)
{
return false;
}
ParameterInfo[] parameters = method.GetParameters();
if (parameters.Length != 1 || !parameters[0].ParameterType.IsEnum)
{
return false;
}
object obj = Enum.Parse(parameters[0].ParameterType, modeName, ignoreCase: true);
object obj2 = ReadMember(type, bot, "mode");
if (obj2 != null && obj2.Equals(obj))
{
return true;
}
method.Invoke(bot, new object[1] { obj });
return true;
}
catch
{
return false;
}
}
private bool TrySetRushMode(object bot)
{
if (!SetModeIfDifferent(bot, "Run") && !SetModeIfDifferent(bot, "Sprint") && !SetModeIfDifferent(bot, "Chase"))
{
return SetModeIfDifferent(bot, "Follow");
}
return true;
}
private void TryStartFlickerForBot(object bot)
{
Transform val = ((bot == null) ? null : GetBotTransform(bot));
if ((Object)(object)val == (Object)null)
{
return;
}
Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
return;
}
BotRuntime runtime = GetRuntime(bot);
if (runtime.RestoreVisualAt > Time.time)
{
return;
}
runtime.FlickerRenderers = componentsInChildren;
runtime.RendererStates = new bool[componentsInChildren.Length];
for (int i = 0; i < componentsInChildren.Length; i++)
{
runtime.RendererStates[i] = (Object)(object)componentsInChildren[i] != (Object)null && componentsInChildren[i].enabled;
if ((Object)(object)componentsInChildren[i] != (Object)null)
{
componentsInChildren[i].enabled = false;
}
}
runtime.RestoreVisualAt = Time.time + Random.Range(0.08f, 0.16f);
}
private void TryStartRandomFlicker()
{
if (_bots.Count == 0)
{
return;
}
for (int i = 0; i < _bots.Count; i++)
{
object obj = _bots[Random.Range(0, _bots.Count)];
Transform val = ((obj == null) ? null : GetBotTransform(obj));
if ((Object)(object)val == (Object)null)
{
continue;
}
Renderer[] componentsInChildren = ((Component)val).GetComponentsInChildren<Renderer>(true);
if (componentsInChildren == null || componentsInChildren.Length == 0)
{
break;
}
BotRuntime runtime = GetRuntime(obj);
if (runtime.RestoreVisualAt > Time.time)
{
break;
}
runtime.FlickerRenderers = componentsInChildren;
runtime.RendererStates = new bool[componentsInChildren.Length];
for (int j = 0; j < componentsInChildren.Length; j++)
{
runtime.RendererStates[j] = (Object)(object)componentsInChildren[j] != (Object)null && componentsInChildren[j].enabled;
if ((Object)(object)componentsInChildren[j] != (Object)null)
{
componentsInChildren[j].enabled = false;
}
}
runtime.RestoreVisualAt = Time.time + Random.Range(0.07f, 0.14f);
break;
}
}
private void UpdateFlickerRestores()
{
foreach (KeyValuePair<object, BotRuntime> item in _runtime)
{
BotRuntime value = item.Value;
if (!(value.RestoreVisualAt <= 0f) && !(Time.time < value.RestoreVisualAt))
{
RestoreFlicker(value);
}
}
}
private void RestoreFlicker(BotRuntime state)
{
if (state.FlickerRenderers != null && state.RendererStates != null)
{
for (int i = 0; i < state.FlickerRenderers.Length && i < state.RendererStates.Length; i++)
{
if ((Object)(object)state.FlickerRenderers[i] != (Object)null)
{
state.FlickerRenderers[i].enabled = state.RendererStates[i];
}
}
}
state.FlickerRenderers = null;
state.RendererStates = null;
state.RestoreVisualAt = 0f;
}
private void RestoreAllFlickers()
{
foreach (BotRuntime value in _runtime.Values)
{
RestoreFlicker(value);
}
}
private void RestoreBots()
{
RestoreAllFlickers();
foreach (object bot in _bots)
{
if (bot != null)
{
SetModeIfDifferent(bot, "Stand");
}
}
}
public void Dispose()
{
if (_disposed)
{
return;
}
_disposed = true;
RestoreBots();
_bots.Clear();
foreach (GameObject goalObject in _goalObjects)
{
if ((Object)(object)goalObject != (Object)null)
{
Object.Destroy((Object)(object)goalObject);
}
}
_goalObjects.Clear();
_goalMarkers.Clear();
_runtime.Clear();
_log.Msg("Mimic AI disposed.");
}
}
internal enum MimicAction
{
Observe,
Stalk,
TakeCover,
Investigate,
Rush,
Attack,
Jumpscare,
Ignore
}
internal sealed class MimicBehavior
{
private float _nextDecisionAt;
private float _lastJumpscareAt = -99999f;
private float _lastAttackAt = -99999f;
public MimicAction Decide(MimicSettings settings, MimicLearning learning, float now, float distanceToPlayer, bool playerLookingAtMimic, bool lineOfSight, bool playerMoving, bool canAttack, bool jumpscareAvailable)
{
if (settings == null || !settings.enabled)
{
return MimicAction.Observe;
}
if (settings.behaviorMode == MimicBehaviorMode.NonHostile)
{
if (!lineOfSight)
{
return MimicAction.Investigate;
}
return MimicAction.Observe;
}
if (settings.behaviorMode == MimicBehaviorMode.Jumpscare && jumpscareAvailable && now - _lastJumpscareAt >= settings.jumpscareCooldown && distanceToPlayer < 5f && lineOfSight)
{
_lastJumpscareAt = now;
return MimicAction.Jumpscare;
}
if (settings.behaviorMode == MimicBehaviorMode.RuthlessAttacker)
{
if (settings.attacksEnabled && canAttack && now - _lastAttackAt >= settings.attackCooldown)
{
_lastAttackAt = now;
return MimicAction.Attack;
}
if (!(distanceToPlayer > 2.2f))
{
return MimicAction.Attack;
}
return MimicAction.Rush;
}
if (now < _nextDecisionAt)
{
return MimicAction.Observe;
}
_nextDecisionAt = now + Random.Range(0.65f, 1.8f);
if (settings.attacksEnabled && canAttack && distanceToPlayer < 2.15f && now - _lastAttackAt >= settings.attackCooldown && Random.value < 0.25f)
{
_lastAttackAt = now;
return MimicAction.Attack;
}
if (playerLookingAtMimic && distanceToPlayer > 3f)
{
return MimicAction.TakeCover;
}
if (!lineOfSight)
{
return MimicAction.Investigate;
}
if (distanceToPlayer > settings.stalkDistance)
{
if (!(Random.value < settings.rushChance))
{
return MimicAction.Stalk;
}
return MimicAction.Rush;
}
if (learning != null && learning.AveragePause() > 2.5f && Random.value < settings.rushChance * 0.5f)
{
return MimicAction.Rush;
}
if (!playerMoving)
{
if (!(Random.value < 0.35f))
{
return MimicAction.Observe;
}
return MimicAction.TakeCover;
}
return MimicAction.Stalk;
}
}
internal sealed class MimicDataManager
{
private readonly Instance _log;
private readonly JsonSerializerOptions _options = new JsonSerializerOptions
{
WriteIndented = true,
IncludeFields = true
};
public MimicSettings Settings { get; private set; }
public MimicLearning Learning { get; private set; }
public MimicEncounters Encounters { get; private set; }
public string DirectoryPath { get; private set; }
public MimicDataManager(Instance logger, string rootDirectory = null)
{
_log = logger;
DirectoryPath = Path.Combine(string.IsNullOrWhiteSpace(rootDirectory) ? Environment.CurrentDirectory : rootDirectory, "Userdata", "Mimic");
Settings = new MimicSettings();
Learning = new MimicLearning();
Encounters = new MimicEncounters();
}
public void Load()
{
Directory.CreateDirectory(DirectoryPath);
Settings = LoadFile("MimicSettings.json", Settings);
Learning = LoadFile("MimicLearning.json", Learning);
Encounters = LoadFile("MimicEncounters.json", Encounters);
if (Settings == null)
{
Settings = new MimicSettings();
}
if (Learning == null)
{
Learning = new MimicLearning();
}
if (Encounters == null)
{
Encounters = new MimicEncounters();
}
Settings.ClampValues();
SaveAll();
_log.Msg("Mimic data directory: " + DirectoryPath);
}
public void SaveAll()
{
SaveFile("MimicSettings.json", Settings);
SaveFile("MimicLearning.json", Learning);
SaveFile("MimicEncounters.json", Encounters);
SaveBrain(JsonSerializer.Serialize(new
{
version = 1,
behaviorMode = Settings.behaviorMode.ToString(),
enabled = Settings.enabled,
learningEnabled = Settings.learningEnabled,
sessions = Learning.sessions,
averageSpeed = Learning.AverageSpeed(),
averagePause = Learning.AveragePause(),
averageTurn = Learning.AverageTurn(),
savedUtc = DateTime.UtcNow.ToString("o")
}, _options));
}
public void SaveBrain(string json)
{
try
{
WriteAtomically(Path.Combine(DirectoryPath, "MimicBrain.json"), json ?? "{}");
}
catch (Exception ex)
{
_log.Error("Could not save MimicBrain.json: " + ex.Message);
}
}
private T LoadFile<T>(string name, T fallback) where T : class
{
string path = Path.Combine(DirectoryPath, name);
if (!File.Exists(path))
{
return fallback;
}
try
{
return JsonSerializer.Deserialize<T>(File.ReadAllText(path), _options) ?? fallback;
}
catch (Exception ex)
{
_log.Warning("Could not load " + name + ": " + ex.Message + ". Keeping defaults.");
return fallback;
}
}
private void SaveFile<T>(string name, T value)
{
try
{
string content = JsonSerializer.Serialize(value, _options);
WriteAtomically(Path.Combine(DirectoryPath, name), content);
}
catch (Exception ex)
{
_log.Error("Could not save " + name + ": " + ex.Message);
}
}
private static void WriteAtomically(string path, string content)
{
Directory.CreateDirectory(Path.GetDirectoryName(path));
string text = path + ".tmp";
File.WriteAllText(text, content);
if (File.Exists(path))
{
string destinationBackupFileName = path + ".bak";
try
{
File.Replace(text, path, destinationBackupFileName, ignoreMetadataErrors: true);
return;
}
catch
{
File.Copy(text, path, overwrite: true);
File.Delete(text);
return;
}
}
File.Move(text, path);
}
}
[Serializable]
public sealed class MimicEncounterRecord
{
public string utc;
public string eventType;
public string note;
}
[Serializable]
public sealed class MimicEncounters
{
public int version = 1;
public int totalEncounters;
public int totalRushes;
public int totalAttacks;
public int totalJumpscares;
public string lastEncounterUtc = "";
public List<MimicEncounterRecord> history = new List<MimicEncounterRecord>();
public void Record(string eventType, string note = "")
{
string text = (eventType ?? "event").Trim().ToLowerInvariant();
string utc = (lastEncounterUtc = DateTime.UtcNow.ToString("o"));
if (text.Contains("encounter"))
{
totalEncounters++;
}
if (text.Contains("rush"))
{
totalRushes++;
}
if (text.Contains("attack"))
{
totalAttacks++;
}
if (text.Contains("jumpscare"))
{
totalJumpscares++;
}
history.Add(new MimicEncounterRecord
{
utc = utc,
eventType = text,
note = (note ?? "")
});
if (history.Count > 250)
{
history.RemoveAt(0);
}
}
}
[Serializable]
public sealed class MimicLearning
{
public int version = 1;
public int sessions;
public List<float> movementGaps = new List<float>();
public List<float> walkingBursts = new List<float>();
public List<float> pauses = new List<float>();
public List<float> turns = new List<float>();
public List<float> directionChanges = new List<float>();
public List<string> observations = new List<string>();
[NonSerialized]
private Vector3 _lastPosition;
[NonSerialized]
private Vector3 _lastForward;
[NonSerialized]
private float _lastSampleAt;
[NonSerialized]
private float _lastMovingAt;
[NonSerialized]
private bool _initialized;
[NonSerialized]
private bool _wasMoving;
public void BeginSession()
{
sessions++;
_initialized = false;
}
public void Observe(Vector3 position, Vector3 forward, float now)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_011c: Unknown result type (might be due to invalid IL or missing references)
//IL_0139: 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_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: 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_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_018d: Unknown result type (might be due to invalid IL or missing references)
//IL_018e: Unknown result type (might be due to invalid IL or missing references)
//IL_0194: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
if (!_initialized)
{
_lastPosition = position;
_lastForward = forward;
_lastSampleAt = now;
_lastMovingAt = now;
_initialized = true;
return;
}
float num = Mathf.Clamp(now - _lastSampleAt, 0f, 5f);
if (!(num <= 0.001f))
{
float num2 = Vector3.Distance(position, _lastPosition) / num;
bool flag = num2 > 0.12f;
Add(movementGaps, num, 80);
if (flag)
{
Add(walkingBursts, num2, 80);
}
if (_wasMoving && !flag)
{
Add(pauses, Mathf.Max(0f, now - _lastMovingAt), 80);
Add(observations, "pause:" + (now - _lastMovingAt).ToString("F2"), 150);
}
if (flag && !_wasMoving)
{
_lastMovingAt = now;
Add(observations, "move-start:" + now.ToString("F2"), 150);
}
float num3 = Vector3.Angle(_lastForward, forward);
if (num3 >= 12f)
{
Add(turns, num3, 80);
}
Vector3 val = position - _lastPosition;
if (((Vector3)(ref val)).sqrMagnitude > 0.02f && flag && Vector3.Dot(((Vector3)(ref val)).normalized, forward) < -0.1f)
{
Add(directionChanges, num3, 80);
}
if (flag)
{
_lastMovingAt = now;
}
_wasMoving = flag;
_lastPosition = position;
_lastForward = forward;
_lastSampleAt = now;
}
}
public float AverageSpeed()
{
return Average(walkingBursts);
}
public float AveragePause()
{
return Average(pauses);
}
public float AverageTurn()
{
return Average(turns);
}
private static void Add(List<float> list, float value, int max)
{
list.Add(value);
if (list.Count > max)
{
list.RemoveAt(0);
}
}
private static void Add(List<string> list, string value, int max)
{
list.Add(value);
if (list.Count > max)
{
list.RemoveAt(0);
}
}
private static float Average(List<float> list)
{
if (list == null || list.Count == 0)
{
return 0f;
}
float num = 0f;
foreach (float item in list)
{
num += item;
}
return num / (float)list.Count;
}
}
internal static class MimicPathfinder
{
public static bool TryFindWaypoint(Vector3 start, Vector3 target, float clearance, out Vector3 waypoint)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: 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_0009: 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_002d: 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_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)
//IL_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: 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_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004b: 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_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_005b: 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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0063: 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_0066: Unknown result type (might be due to invalid IL or missing references)
//IL_006b: 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_0076: 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_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
//IL_00c2: 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)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: 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)
//IL_00db: 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)
//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0101: Unknown result type (might be due to invalid IL or missing references)
//IL_0106: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_010f: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: 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_015c: 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_0163: Unknown result type (might be due to invalid IL or missing references)
//IL_0165: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0174: 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)
//IL_0193: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
//IL_01ac: 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_01af: Unknown result type (might be due to invalid IL or missing references)
//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
//IL_01c2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
//IL_01de: Unknown result type (might be due to invalid IL or missing references)
//IL_01e3: 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_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_0204: Unknown result type (might be due to invalid IL or missing references)
//IL_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0210: Unknown result type (might be due to invalid IL or missing references)
//IL_0212: Unknown result type (might be due to invalid IL or missing references)
//IL_021c: Unknown result type (might be due to invalid IL or missing references)
//IL_0221: Unknown result type (might be due to invalid IL or missing references)
//IL_0226: Unknown result type (might be due to invalid IL or missing references)
//IL_0228: Unknown result type (might be due to invalid IL or missing references)
//IL_022a: Unknown result type (might be due to invalid IL or missing references)
//IL_022c: Unknown result type (might be due to invalid IL or missing references)
//IL_022e: Unknown result type (might be due to invalid IL or missing references)
//IL_0233: Unknown result type (might be due to invalid IL or missing references)
//IL_0237: 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_0240: Unknown result type (might be due to invalid IL or missing references)
//IL_0253: Unknown result type (might be due to invalid IL or missing references)
//IL_0254: Unknown result type (might be due to invalid IL or missing references)
//IL_0259: Unknown result type (might be due to invalid IL or missing references)
//IL_025e: Unknown result type (might be due to invalid IL or missing references)
//IL_0260: Unknown result type (might be due to invalid IL or missing references)
//IL_0265: Unknown result type (might be due to invalid IL or missing references)
//IL_026a: 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_0283: Unknown result type (might be due to invalid IL or missing references)
//IL_0285: Unknown result type (might be due to invalid IL or missing references)
//IL_028a: Unknown result type (might be due to invalid IL or missing references)
//IL_0291: Unknown result type (might be due to invalid IL or missing references)
//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
//IL_02b3: Unknown result type (might be due to invalid IL or missing references)
//IL_02d8: Unknown result type (might be due to invalid IL or missing references)
//IL_02da: Unknown result type (might be due to invalid IL or missing references)
waypoint = target;
Vector3 val = target - start;
val.y = 0f;
float magnitude = ((Vector3)(ref val)).magnitude;
if (magnitude < 1.25f)
{
return false;
}
Vector3 val2 = val / magnitude;
Vector3 val3 = start + Vector3.up * 1.15f;
Vector3 val4 = target + Vector3.up * 1f;
Vector3 val5 = val4 - val3;
RaycastHit val6 = default(RaycastHit);
if (!Physics.Raycast(val3, ((Vector3)(ref val5)).normalized, ref val6, Vector3.Distance(val3, val4), -1, (QueryTriggerInteraction)1))
{
return false;
}
val5 = Vector3.Cross(Vector3.up, val2);
Vector3 normalized = ((Vector3)(ref val5)).normalized;
float num = Mathf.Clamp(clearance, 0.65f, 3.5f);
Vector3 point = ((RaycastHit)(ref val6)).point;
Vector3[] array = (Vector3[])(object)new Vector3[5]
{
point + normalized * num,
point - normalized * num,
point + normalized * (num * 1.65f),
point - normalized * (num * 1.65f),
point + ((RaycastHit)(ref val6)).normal * num
};
float num2 = float.MaxValue;
bool result = false;
RaycastHit val8 = default(RaycastHit);
RaycastHit val11 = default(RaycastHit);
for (int i = 0; i < array.Length; i++)
{
Vector3 val7 = array[i];
if (!Physics.Raycast(val7 + Vector3.up * 2.2f, Vector3.down, ref val8, 5f, -1, (QueryTriggerInteraction)1))
{
continue;
}
val7 = ((RaycastHit)(ref val8)).point + Vector3.up * 0.08f;
if (Vector3.Distance(start, val7) < 0.8f || Vector3.Distance(val7, target) < 0.8f || Physics.CheckSphere(val7 + Vector3.up * 0.75f, 0.28f, -1, (QueryTriggerInteraction)1))
{
continue;
}
Vector3 val9 = start + Vector3.up * 1f;
Vector3 val10 = val7 + Vector3.up * 1f;
val5 = val10 - val9;
if (!Physics.Raycast(val9, ((Vector3)(ref val5)).normalized, ref val11, Vector3.Distance(val9, val10), -1, (QueryTriggerInteraction)1))
{
Vector3 val12 = target + Vector3.up - (val7 + Vector3.up);
float magnitude2 = ((Vector3)(ref val12)).magnitude;
bool flag = magnitude2 < 0.2f || !Physics.Raycast(val7 + Vector3.up, ((Vector3)(ref val12)).normalized, ref val11, magnitude2, -1, (QueryTriggerInteraction)1);
float num3 = Vector3.Distance(start, val7) + Vector3.Distance(val7, target) * (flag ? 0.18f : 0.45f);
if (num3 < num2)
{
num2 = num3;
waypoint = val7;
result = true;
}
}
}
return result;
}
}
public enum MimicBehaviorMode
{
AdaptiveStalker,
Jumpscare,
RuthlessAttacker,
NonHostile
}
[Serializable]
public sealed class MimicSettings
{
public int version = 1;
public MimicBehaviorMode behaviorMode;
public bool enabled;
public bool stalkingEnabled = true;
public bool attacksEnabled = true;
public bool visualGlitchesEnabled;
public bool learningEnabled = true;
public bool selfAwareEnabled;
public float selfAwareMemorySeconds = 7f;
public float selfAwareDistance = 20f;
public float selfAwareLookDot = 0.84f;
public bool pathfindingEnabled = true;
public float pathRefreshInterval = 0.8f;
public float obstacleClearance = 1.4f;
public float waypointReachDistance = 1.1f;
public float stalkDistance = 7f;
public float rushChance = 0.22f;
public float attackCooldown = 4f;
public float jumpscareCooldown = 30f;
public void ClampValues()
{
stalkDistance = Clamp(stalkDistance, 2f, 25f);
rushChance = Clamp(rushChance, 0f, 1f);
attackCooldown = Clamp(attackCooldown, 0.5f, 60f);
jumpscareCooldown = Clamp(jumpscareCooldown, 1f, 300f);
pathRefreshInterval = Clamp(pathRefreshInterval, 0.25f, 3f);
obstacleClearance = Clamp(obstacleClearance, 0.65f, 3.5f);
waypointReachDistance = Clamp(waypointReachDistance, 0.5f, 2.5f);
selfAwareMemorySeconds = Clamp(selfAwareMemorySeconds, 1f, 30f);
selfAwareDistance = Clamp(selfAwareDistance, 5f, 35f);
selfAwareLookDot = Clamp(selfAwareLookDot, 0.5f, 0.98f);
}
private static float Clamp(float v, float min, float max)
{
if (!(v < min))
{
if (!(v > max))
{
return v;
}
return max;
}
return min;
}
}
public sealed class Mod : MelonMod
{
private MimicAI _ai;
private MimicDataManager _data;
private float _nextSaveAt;
private bool _menuCreated;
public override void OnInitializeMelon()
{
_data = new MimicDataManager(((MelonBase)this).LoggerInstance);
_data.Load();
if (_data.Learning != null)
{
_data.Learning.BeginSession();
}
_ai = new MimicAI(((MelonBase)this).LoggerInstance);
ApplySettingsToAI();
((MelonBase)this).LoggerInstance.Msg("Mimic 0.6.0 merged build initialized. Microphone features are not included.");
}
public override void OnLateInitializeMelon()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
if (!_menuCreated && _data != null)
{
_menuCreated = true;
Page root = Page.Root.CreatePage("Mimic", Color.cyan, 0, true);
BuildMainPage(root);
BuildBehaviorPages(root);
BuildPathfindingPage(root);
BuildLearningPage(root);
BuildDiagnosticsPage(root);
((MelonBase)this).LoggerInstance.Msg("Mimic 0.6.0 merged BoneMenu created: AI, behavior, pathfinding, learning, diagnostics. Voice/TTS and microphone features are removed.");
}
}
private void BuildMainPage(Page root)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0077: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: 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_00cd: 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)
//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0152: Unknown result type (might be due to invalid IL or missing references)
Page obj = root.CreatePage("AI Control", Color.cyan, 0, true);
obj.CreateBool("Mimic AI Enabled", Color.cyan, _data.Settings.enabled, (Action<bool>)delegate(bool value)
{
_data.Settings.enabled = value;
ApplySettingsToAI();
Save();
});
obj.CreateEnum("Behavior Mode", Color.cyan, (Enum)_data.Settings.behaviorMode, (Action<Enum>)delegate(Enum value)
{
_data.Settings.behaviorMode = (MimicBehaviorMode)(object)value;
ApplySettingsToAI();
Save();
});
obj.CreateFunction("Refresh Existing Doppel Bots", Color.white, (Action)delegate
{
_ai?.RefreshBots();
((MelonBase)this).LoggerInstance.Msg("Requested a refresh of existing Doppel bots.");
});
obj.CreateFunction("Reapply Settings", Color.white, (Action)delegate
{
ApplySettingsToAI();
Save();
((MelonBase)this).LoggerInstance.Msg("Mimic settings reapplied.");
});
obj.CreateFunction("Save All Data Now", Color.green, (Action)Save);
Page obj2 = obj.CreatePage("Quick Profiles", Color.cyan, 0, true);
obj2.CreateFunction("Balanced Stalker", Color.cyan, (Action)delegate
{
ApplyProfile(MimicBehaviorMode.AdaptiveStalker, stalking: true, attacks: true, glitches: false, learning: true, 7f, 0.22f, 4f, 30f);
});
obj2.CreateFunction("Patient / Less Aggressive", Color.cyan, (Action)delegate
{
ApplyProfile(MimicBehaviorMode.AdaptiveStalker, stalking: true, attacks: false, glitches: false, learning: true, 10f, 0.08f, 7f, 45f);
});
obj2.CreateFunction("Aggressive Pursuer", Color.red, (Action)delegate
{
ApplyProfile(MimicBehaviorMode.RuthlessAttacker, stalking: true, attacks: true, glitches: false, learning: true, 5f, 0.55f, 2f, 20f);
});
obj2.CreateFunction("Jumpscare Focus", Color.magenta, (Action)delegate
{
ApplyProfile(MimicBehaviorMode.Jumpscare, stalking: true, attacks: false, glitches: true, learning: true, 7f, 0.15f, 4f, 18f);
});
obj2.CreateFunction("Non-Hostile Observer", Color.white, (Action)delegate
{
ApplyProfile(MimicBehaviorMode.NonHostile, stalking: false, attacks: true, glitches: false, learning: true, 9f, 0f, 4f, 30f);
});
}
private void BuildBehaviorPages(Page root)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_0143: Unknown result type (might be due to invalid IL or missing references)
//IL_0160: Unknown result type (might be due to invalid IL or missing references)
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
//IL_01c7: Unknown result type (might be due to invalid IL or missing references)
//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
//IL_0220: Unknown result type (might be due to invalid IL or missing references)
Page obj = root.CreatePage("Behavior Tuning", Color.cyan, 0, true);
Page obj2 = obj.CreatePage("Stalking & Movement", Color.cyan, 0, true);
obj2.CreateBool("Stalking / Cover Enabled", Color.cyan, _data.Settings.stalkingEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.stalkingEnabled = value;
ApplySettingsToAI();
Save();
});
obj2.CreateFunction("Increase Stalk Distance (+1m)", Color.cyan, (Action)delegate
{
ChangeFloat("stalk distance", 1f, 2f, 25f, delegate(float value)
{
_data.Settings.stalkDistance = value;
}, () => _data.Settings.stalkDistance);
});
obj2.CreateFunction("Decrease Stalk Distance (-1m)", Color.cyan, (Action)delegate
{
ChangeFloat("stalk distance", -1f, 2f, 25f, delegate(float value)
{
_data.Settings.stalkDistance = value;
}, () => _data.Settings.stalkDistance);
});
obj2.CreateFunction("Increase Rush Chance (+5%)", Color.cyan, (Action)delegate
{
ChangeFloat("rush chance", 0.05f, 0f, 1f, delegate(float value)
{
_data.Settings.rushChance = value;
}, () => _data.Settings.rushChance, percent: true);
});
obj2.CreateFunction("Decrease Rush Chance (-5%)", Color.cyan, (Action)delegate
{
ChangeFloat("rush chance", -0.05f, 0f, 1f, delegate(float value)
{
_data.Settings.rushChance = value;
}, () => _data.Settings.rushChance, percent: true);
});
obj2.CreateFunction("Show Movement Tuning", Color.white, (Action)delegate
{
((MelonBase)this).LoggerInstance.Msg("Stalk distance=" + _data.Settings.stalkDistance.ToString("F1") + "m; rush chance=" + (_data.Settings.rushChance * 100f).ToString("F0") + "%.");
});
Page obj3 = obj.CreatePage("Combat & Cooldowns", Color.red, 0, true);
obj3.CreateBool("Close-Range Attacks Enabled", Color.red, _data.Settings.attacksEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.attacksEnabled = value;
ApplySettingsToAI();
Save();
});
obj3.CreateFunction("Faster Attacks (-0.5s cooldown)", Color.red, (Action)delegate
{
ChangeFloat("attack cooldown", -0.5f, 0.5f, 60f, delegate(float value)
{
_data.Settings.attackCooldown = value;
}, () => _data.Settings.attackCooldown);
});
obj3.CreateFunction("Slower Attacks (+0.5s cooldown)", Color.red, (Action)delegate
{
ChangeFloat("attack cooldown", 0.5f, 0.5f, 60f, delegate(float value)
{
_data.Settings.attackCooldown = value;
}, () => _data.Settings.attackCooldown);
});
obj3.CreateFunction("Shorter Jumpscare Cooldown (-5s)", Color.magenta, (Action)delegate
{
ChangeFloat("jumpscare cooldown", -5f, 1f, 300f, delegate(float value)
{
_data.Settings.jumpscareCooldown = value;
}, () => _data.Settings.jumpscareCooldown);
});
obj3.CreateFunction("Longer Jumpscare Cooldown (+5s)", Color.magenta, (Action)delegate
{
ChangeFloat("jumpscare cooldown", 5f, 1f, 300f, delegate(float value)
{
_data.Settings.jumpscareCooldown = value;
}, () => _data.Settings.jumpscareCooldown);
});
obj3.CreateFunction("Show Combat Tuning", Color.white, (Action)delegate
{
((MelonBase)this).LoggerInstance.Msg("Attacks=" + _data.Settings.attacksEnabled + "; attack cooldown=" + _data.Settings.attackCooldown.ToString("F1") + "s; jumpscare cooldown=" + _data.Settings.jumpscareCooldown.ToString("F1") + "s.");
});
Page obj4 = obj.CreatePage("Experimental", Color.magenta, 0, true);
obj4.CreateBool("Self-Aware Mode", Color.magenta, _data.Settings.selfAwareEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.selfAwareEnabled = value;
ApplySettingsToAI();
Save();
});
obj4.CreateBool("Visual Glitches", Color.magenta, _data.Settings.visualGlitchesEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.visualGlitchesEnabled = value;
ApplySettingsToAI();
Save();
});
obj4.CreateFunction("Reset Experimental Toggles", Color.white, (Action)delegate
{
_data.Settings.selfAwareEnabled = false;
_data.Settings.visualGlitchesEnabled = false;
ApplySettingsToAI();
Save();
((MelonBase)this).LoggerInstance.Msg("Self-aware mode and visual glitches disabled.");
});
}
private void BuildPathfindingPage(Page root)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
Page obj = root.CreatePage("Pathfinding & Navigation", Color.cyan, 0, true);
obj.CreateBool("Obstacle Waypoint Pathfinding", Color.cyan, _data.Settings.pathfindingEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.pathfindingEnabled = value;
ApplySettingsToAI();
Save();
((MelonBase)this).LoggerInstance.Msg("Mimic waypoint pathfinding " + (value ? "enabled" : "disabled") + ".");
});
obj.CreateFunction("Faster Path Updates (-0.1s)", Color.cyan, (Action)delegate
{
ChangeFloat("path refresh interval", -0.1f, 0.25f, 3f, delegate(float value)
{
_data.Settings.pathRefreshInterval = value;
}, () => _data.Settings.pathRefreshInterval);
});
obj.CreateFunction("Slower Path Updates (+0.1s)", Color.cyan, (Action)delegate
{
ChangeFloat("path refresh interval", 0.1f, 0.25f, 3f, delegate(float value)
{
_data.Settings.pathRefreshInterval = value;
}, () => _data.Settings.pathRefreshInterval);
});
obj.CreateFunction("Increase Obstacle Clearance (+0.2m)", Color.cyan, (Action)delegate
{
ChangeFloat("obstacle clearance", 0.2f, 0.65f, 3.5f, delegate(float value)
{
_data.Settings.obstacleClearance = value;
}, () => _data.Settings.obstacleClearance);
});
obj.CreateFunction("Decrease Obstacle Clearance (-0.2m)", Color.cyan, (Action)delegate
{
ChangeFloat("obstacle clearance", -0.2f, 0.65f, 3.5f, delegate(float value)
{
_data.Settings.obstacleClearance = value;
}, () => _data.Settings.obstacleClearance);
});
obj.CreateFunction("Increase Waypoint Reach Radius (+0.2m)", Color.cyan, (Action)delegate
{
ChangeFloat("waypoint reach distance", 0.2f, 0.5f, 2.5f, delegate(float value)
{
_data.Settings.waypointReachDistance = value;
}, () => _data.Settings.waypointReachDistance);
});
obj.CreateFunction("Decrease Waypoint Reach Radius (-0.2m)", Color.cyan, (Action)delegate
{
ChangeFloat("waypoint reach distance", -0.2f, 0.5f, 2.5f, delegate(float value)
{
_data.Settings.waypointReachDistance = value;
}, () => _data.Settings.waypointReachDistance);
});
obj.CreateFunction("Show Navigation Settings", Color.white, (Action)delegate
{
((MelonBase)this).LoggerInstance.Msg("Pathfinding=" + _data.Settings.pathfindingEnabled + "; refresh=" + _data.Settings.pathRefreshInterval.ToString("F2") + "s; clearance=" + _data.Settings.obstacleClearance.ToString("F1") + "m; waypoint reach=" + _data.Settings.waypointReachDistance.ToString("F1") + "m.");
});
}
private void BuildLearningPage(Page root)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_007f: Unknown result type (might be due to invalid IL or missing references)
//IL_009b: Unknown result type (might be due to invalid IL or missing references)
Page obj = root.CreatePage("Learning & Memory", Color.cyan, 0, true);
obj.CreateBool("Player Learning Enabled", Color.cyan, _data.Settings.learningEnabled, (Action<bool>)delegate(bool value)
{
_data.Settings.learningEnabled = value;
ApplySettingsToAI();
Save();
});
obj.CreateFunction("Show Learning Statistics", Color.white, (Action)PrintLearningStats);
obj.CreateFunction("Save Learning & Settings", Color.green, (Action)Save);
obj.CreateFunction("Forget Learned Movement History", Color.red, (Action)delegate
{
_data.Learning.movementGaps.Clear();
_data.Learning.walkingBursts.Clear();
_data.Learning.pauses.Clear();
_data.Learning.turns.Clear();
_data.Learning.directionChanges.Clear();
_data.Learning.observations.Clear();
_data.Learning.sessions = 0;
Save();
((MelonBase)this).LoggerInstance.Msg("Mimic movement history cleared. Encounter history was preserved.");
});
obj.CreateFunction("Forget Encounter History", Color.red, (Action)delegate
{
_data.Encounters.history.Clear();
_data.Encounters.totalEncounters = 0;
_data.Encounters.totalRushes = 0;
_data.Encounters.totalAttacks = 0;
_data.Encounters.totalJumpscares = 0;
_data.Encounters.lastEncounterUtc = string.Empty;
Save();
((MelonBase)this).LoggerInstance.Msg("Mimic encounter history cleared. Movement learning was preserved.");
});
}
private void BuildDiagnosticsPage(Page root)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0018: 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_0052: 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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
Page obj = root.CreatePage("Diagnostics & Tools", Color.white, 0, true);
obj.CreateFunction("Refresh Existing Doppel Bots", Color.white, (Action)delegate
{
_ai?.RefreshBots();
});
obj.CreateFunction("Show Encounter Counts", Color.white, (Action)delegate
{
((MelonBase)this).LoggerInstance.Msg("Encounters=" + _data.Encounters.totalEncounters + ", rushes=" + _data.Encounters.totalRushes + ", attacks=" + _data.Encounters.totalAttacks + ", jumpscares=" + _data.Encounters.totalJumpscares);
});
obj.CreateFunction("Print Data Directory", Color.white, (Action)delegate
{
((MelonBase)this).LoggerInstance.Msg("Mimic data path: " + _data.DirectoryPath);
});
obj.CreateFunction("Print Current Settings", Color.white, (Action)PrintSettings);
obj.CreateFunction("Save All JSON Files", Color.green, (Action)Save);
obj.CreateFunction("Reapply Settings to AI", Color.cyan, (Action)ApplySettingsToAI);
}
private void ApplyProfile(MimicBehaviorMode mode, bool stalking, bool attacks, bool glitches, bool learning, float stalkDistance, float rushChance, float attackCooldown, float jumpscareCooldown)
{
MimicSettings settings = _data.Settings;
settings.behaviorMode = mode;
settings.enabled = true;
settings.stalkingEnabled = stalking;
settings.attacksEnabled = attacks;
settings.visualGlitchesEnabled = glitches;
settings.learningEnabled = learning;
settings.stalkDistance = stalkDistance;
settings.rushChance = rushChance;
settings.attackCooldown = attackCooldown;
settings.jumpscareCooldown = jumpscareCooldown;
ApplySettingsToAI();
Save();
((MelonBase)this).LoggerInstance.Msg("Applied Mimic profile: " + mode.ToString() + ". Review the Behavior Tuning pages to customize it.");
}
private void ChangeFloat(string label, float delta, float min, float max, Action<float> setter, Func<float> getter, bool percent = false)
{
if (_data != null)
{
float num = Mathf.Clamp(getter() + delta, min, max);
setter(num);
_data.Settings.ClampValues();
ApplySettingsToAI();
Save();
((MelonBase)this).LoggerInstance.Msg("Mimic " + label + " set to " + (percent ? ((num * 100f).ToString("F0") + "%") : num.ToString("F2")) + ".");
}
}
private void PrintLearningStats()
{
MimicLearning learning = _data.Learning;
((MelonBase)this).LoggerInstance.Msg("Mimic learning: sessions=" + learning.sessions + ", average movement speed=" + learning.AverageSpeed().ToString("F2") + ", average pause=" + learning.AveragePause().ToString("F2") + "s, average turn=" + learning.AverageTurn().ToString("F1") + " degrees, movement samples=" + learning.walkingBursts.Count + ", observations=" + learning.observations.Count + ". Data: " + _data.DirectoryPath);
}
private void PrintSettings()
{
MimicSettings settings = _data.Settings;
((MelonBase)this).LoggerInstance.Msg("Mimic settings: enabled=" + settings.enabled + ", mode=" + settings.behaviorMode.ToString() + ", stalking=" + settings.stalkingEnabled + ", attacks=" + settings.attacksEnabled + ", selfAware=" + settings.selfAwareEnabled + ", visualGlitches=" + settings.visualGlitchesEnabled + ", learning=" + settings.learningEnabled + ", stalkDistance=" + settings.stalkDistance.ToString("F1") + ", rushChance=" + (settings.rushChance * 100f).ToString("F0") + "%, attackCooldown=" + settings.attackCooldown.ToString("F1") + "s, jumpscareCooldown=" + settings.jumpscareCooldown.ToString("F1") + "s.");
}
private void ApplySettingsToAI()
{
if (_ai != null && _data != null)
{
MimicSettings settings = _data.Settings;
settings.ClampValues();
_ai.Configure(settings, _data.Learning, _data.Encounters);
bool attacksEnabled = settings.attacksEnabled && settings.behaviorMode != MimicBehaviorMode.NonHostile && settings.behaviorMode != MimicBehaviorMode.Jumpscare;
bool coverEnabled = settings.stalkingEnabled && settings.behaviorMode != MimicBehaviorMode.RuthlessAttacker;
_ai.SetEnabled(settings.enabled);
_ai.SetCoverEnabled(coverEnabled);
_ai.SetAttacksEnabled(attacksEnabled);
_ai.SetSelfAware(settings.selfAwareEnabled);
_ai.SetVisualGlitches(settings.visualGlitchesEnabled);
}
}
private void Save()
{
if (_data != null)
{
_data.Settings.ClampValues();
_data.SaveAll();
}
}
public override void OnSceneWasLoaded(int buildIndex, string sceneName)
{
_ai?.NotifySceneLoaded(sceneName);
}
public override void OnUpdate()
{
_ai?.Update();
if (_data != null && Time.unscaledTime >= _nextSaveAt)
{
_nextSaveAt = Time.unscaledTime + 30f;
Save();
}
}
public override void OnDeinitializeMelon()
{
Save();
_ai?.Dispose();
_ai = null;
_data = null;
((MelonBase)this).LoggerInstance.Msg("Mimic Mod shut down.");
}
}
}