Decompiled source of DoppelExtras v2.6.1
Mods/DoppelExtras.dll
Decompiled 13 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BoneLib; using BoneLib.BoneMenu; using DoppelExtras; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppSLZ.Marrow; using Il2CppSLZ.Marrow.Combat; using Il2CppSLZ.Marrow.Pool; using Il2CppSLZ.Marrow.Warehouse; using Il2CppSLZ.VRMK; using Il2CppSystem.Collections.Generic; using LabFusion.Data; using LabFusion.Entities; using LabFusion.Extensions; using LabFusion.Grabbables; using LabFusion.Marrow.Extenders; using LabFusion.Network; using LabFusion.Network.Serialization; using LabFusion.Patching; using LabFusion.Player; using LabFusion.Preferences; using LabFusion.Representation; using LabFusion.Scene; using LabFusion.UI; using LabFusion.Utilities; using LabFusion.Voice; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using ThirdEyeBonelabMod; using ThirdEyeBonelabMod.Bots; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(Extras), "DoppelExtras", "2.6.1", "YourName", null)] [assembly: MelonGame("Stress Level Zero", "BONELAB")] [assembly: MelonAdditionalDependencies(new string[] { "Doppel", "BoneLib", "LabFusion" })] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("DoppelExtras")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("DoppelExtras")] [assembly: AssemblyTitle("DoppelExtras")] [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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NativeIntegerAttribute : Attribute { public readonly bool[] TransformFlags; public NativeIntegerAttribute() { TransformFlags = new bool[1] { true }; } public NativeIntegerAttribute(bool[] P_0) { TransformFlags = P_0; } } [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 DoppelExtras { public class Extras : MelonMod { private class State { public string Name; public RigHeadUI HeadUI; public RigNameTag Tag; public float Height = 1.7f; public float NextVoice; public AudioSource Audio; public float NextClimb; public bool Fleeing; public float NextPlayerTalk; public float NextGreet; public float BrainAt; public bool BrainDone; public Vector3 ThreatPos; public string ThreatName; public float LastThreat = -99f; public float NextPush; public bool Switched; public Mode PrevMode; public bool Shouted; public PlayerID Fake; public int NameKey = -1; public bool WasAlive; public Vector3 LastPos; public bool LastEnemy; public float LastY; public float LastVy; public float NextSay; public float NextTaunt; public float NextConvo; public float LastLen = 1.5f; public Convo InConvo; public float BornAt = Time.time; public string TagText; public Color TagColor; } private struct Entity { public Transform Head; public float Height; public bool IsPlayer; public Bot Bot; public string Name; } internal class Convo { public Bot A; public Bot B; public int Turn; public int Turns; public float Next; public float Started; public bool Approaching; } private sealed class Talker { public float Start; public float Last; public bool Active; } private struct Listener { public int Key; public Vector3 Pos; public float Amp; } private static MelonPreferences_Category _cat; internal static MelonPreferences_Entry<bool> NamesOn; internal static MelonPreferences_Entry<bool> TagsOn; internal static MelonPreferences_Entry<bool> TagShowGoal; internal static MelonPreferences_Entry<bool> TagShowHeight; internal static MelonPreferences_Entry<float> TagHeight; internal static MelonPreferences_Entry<float> TagSize; internal static MelonPreferences_Entry<float> TagFadeStart; internal static MelonPreferences_Entry<float> TagFadeEnd; internal static MelonPreferences_Entry<bool> TagNoFade; internal static MelonPreferences_Entry<bool> TraitDesc; internal static MelonPreferences_Entry<bool> JoinGreet; internal static MelonPreferences_Entry<bool> SlzAvatar; internal static MelonPreferences_Entry<bool> MeleeUpright; internal static MelonPreferences_Entry<bool> PlayerTalk; internal static MelonPreferences_Entry<bool> PitchVary; internal static MelonPreferences_Entry<bool> BrainAuto; internal static MelonPreferences_Entry<bool> VoiceOn; internal static MelonPreferences_Entry<bool> VoiceNet; internal static MelonPreferences_Entry<bool> VoiceAvatar; internal static MelonPreferences_Entry<bool> VoiceWav; internal static MelonPreferences_Entry<bool> SitOn; internal static MelonPreferences_Entry<bool> ConvoOn; internal static MelonPreferences_Entry<bool> ConvoWalk; internal static MelonPreferences_Entry<float> SitChance; internal static MelonPreferences_Entry<float> SitCooldown; internal static MelonPreferences_Entry<float> ConvoChance; internal static MelonPreferences_Entry<float> ConvoRange; internal static MelonPreferences_Entry<float> VoiceChance; internal static MelonPreferences_Entry<float> VoiceMinGap; internal static MelonPreferences_Entry<float> VoiceMaxGap; internal static MelonPreferences_Entry<float> VoiceVolume; internal static MelonPreferences_Entry<float> PitchRange; internal static MelonPreferences_Entry<bool> FleeOn; internal static MelonPreferences_Entry<bool> FleePlayer; internal static MelonPreferences_Entry<bool> FleeBots; internal static MelonPreferences_Entry<bool> FleeEnemies; internal static MelonPreferences_Entry<bool> FleeShout; internal static MelonPreferences_Entry<bool> FleeSwitchMode; internal static MelonPreferences_Entry<float> FleeRatio; internal static MelonPreferences_Entry<float> FleeRange; internal static MelonPreferences_Entry<float> FleeBoost; internal static MelonPreferences_Entry<bool> MapSpawnOn; internal static MelonPreferences_Entry<bool> AutoPopulate; internal static MelonPreferences_Entry<bool> SpawnEnemies; internal static MelonPreferences_Entry<int> AutoCount; internal static MelonPreferences_Entry<int> EnemyPercent; internal static MelonPreferences_Entry<bool> ClimbOn; internal static MelonPreferences_Entry<bool> ClimbOnPlayer; internal static MelonPreferences_Entry<bool> ClimbOnBots; internal static MelonPreferences_Entry<float> ClimbCooldown; internal static MelonPreferences_Entry<float> ClimbReach; internal static MelonPreferences_Entry<bool> RandomSizes; internal static MelonPreferences_Entry<bool> FusionList; internal static MelonPreferences_Entry<bool> JawOwn; internal static MelonPreferences_Entry<bool> RedTags; internal static MelonPreferences_Entry<bool> FleeBrain; internal static MelonPreferences_Entry<float> VehicleUse; internal static MelonPreferences_Entry<float> CrouchUse; internal static MelonPreferences_Entry<float> SizeMin; internal static MelonPreferences_Entry<float> SizeMax; private static FieldInfo _fName; private static FieldInfo _fNav; private static FieldInfo _fBots; private static FieldInfo _fNetId; private static FieldInfo _fNetOwner; private static MethodInfo _mHeight; private static MethodInfo _mClimb; private static MethodInfo _mSpawnAt; private static FieldInfo _fTuningValues; private static FieldInfo _fTuningKnown; private static FieldInfo _fTuningUnwritten; private static MethodInfo _mTuningWrite; private static readonly Dictionary<Bot, State> _state = new Dictionary<Bot, State>(); private static readonly List<Entity> _entities = new List<Entity>(); private static float _nextThink; private static float _sceneAt; private static readonly List<string> _names = new List<string>(); private static readonly Random _rng = new Random(); private static readonly Dictionary<string, List<AudioClip>> _clipsBy = new Dictionary<string, List<AudioClip>>(); private static readonly string[] _cats = new string[10] { "idle", "assist", "death", "fall", "kill", "laugh", "panic", "taunt", "witness", "convo" }; private static readonly Dictionary<string, string> _fallback = new Dictionary<string, string> { { "idle", "clear" }, { "assist", "clear" }, { "death", "effort" }, { "fall", "effort" }, { "kill", "clear" }, { "panic", "spot" }, { "witness", "spot" }, { "convo", "clear" } }; private static readonly string[] _vocals = new string[5] { "spot", "clear", "effort", "heave", "up" }; private static MethodInfo _mIsMelee; private static MethodInfo _mBotOf; private static readonly HashSet<string> _logged = new HashSet<string>(); private static readonly HashSet<string> _usedNames = new HashSet<string>(); private static FieldInfo _fLayout; private static Il2CppStructArray<float> _sampleBuf; private static readonly Dictionary<string, AudioClip> _lastClip = new Dictionary<string, AudioClip>(); private static readonly List<KeyValuePair<float, Action>> _later = new List<KeyValuePair<float, Action>>(); private static float _playerY; private static float _playerVy; private static readonly List<Convo> _convos = new List<Convo>(); private static readonly Dictionary<int, Talker> _talkers = new Dictionary<int, Talker>(); private static readonly List<Transform> _spawnPoints = new List<Transform>(); private static bool _spawnScanned; private static readonly Queue<KeyValuePair<Vector3, bool>> _queue = new Queue<KeyValuePair<Vector3, bool>>(); private static bool _busy; private static readonly List<KeyValuePair<Bot, float>> _resize = new List<KeyValuePair<Bot, float>>(); private static float _busyUntil; private static float _nextSpawn; private static float _autoAt = -1f; private static readonly string[] _reject = new string[16] { "enemy", "npc", "item", "crate", "gun", "ammo", "pool", "zombie", "mob", "loot", "vehicle", "prop", "particle", "fx", "audio", "ai" }; private static bool _clientNoticeShown; private static List<string> _slzAvatars; private static float _forceCleanupAt = -1f; private static readonly (string key, float def)[] TuningTable = new(string, float)[322] { ("apart.push", 0.8f), ("apart.room", 1.4f), ("assist.after", 1.5f), ("assist.close", 2.3f), ("assist.close.off", 20f), ("assist.for", 7f), ("assist.within", 14f), ("bot.bigpain", 0.2f), ("bot.calls", 1f), ("bot.hurt", 1f), ("bot.knock.most", 0.3f), ("bot.mend", 0.1f), ("bot.mend.after", 8f), ("bot.voice", 0.9f), ("bot.voice.gap", 0.5f), ("brain.dwell", 1.6f), ("brain.hold", 1.8f), ("brain.nogun", 20f), ("brain.sight", 1.3f), ("brain.tooclose", 2.2f), ("bullet.head", 2f), ("bullet.hurt", 2.5f), ("chase.above", 1.1f), ("chase.from", 3.2f), ("climb.apart", 1.8f), ("climb.close", 0.45f), ("climb.extra", 0.12f), ("climb.glide", 1f), ("climb.glide.step", 0.03f), ("climb.grab", 0.3f), ("climb.head.least", 0.78f), ("climb.max", 2.5f), ("climb.min", 1.2f), ("climb.near", 0.45f), ("climb.onto", 0.45f), ("climb.over.lead", 0.22f), ("climb.over.time", 0.7f), ("climb.pull", 8f), ("climb.reach", 0.5f), ("climb.roam.chance", 0.3f), ("climb.roam.most", 5f), ("climb.speed", 0.7f), ("climb.step", 0.35f), ("climb.top", 0.3f), ("climb.touch", 0.1f), ("climb.tuck", -0.25f), ("climb.wait", 0.3f), ("climbafter.near", 12f), ("climbafter.up", 1.2f), ("clone.pull", 14f), ("clone.push", 18f), ("clone.snap", 2.5f), ("clone.vertical", 1.2f), ("curious.explore", 0.35f), ("curious.near", 3f), ("curious.news", 40f), ("curious.theirway.hold", 4f), ("curious.tries", 5f), ("curious.watch", 1.3f), ("drive.about", 3.5f), ("drive.about.road", 120f), ("drive.apart", 4f), ("drive.arrive", 3.5f), ("drive.back", 1.7f), ("drive.back.fast", 2.5f), ("drive.backs", 5f), ("drive.careful", 3.5f), ("drive.every", 150f), ("drive.feel.up", 0.35f), ("drive.follow", 10f), ("drive.follow.seek", 35f), ("drive.hands", 1.6f), ("drive.litter", 5f), ("drive.live", 4f), ("drive.longest", 150f), ("drive.look", 70f), ("drive.lost", 8f), ("drive.near", 6f), ("drive.past", 0.25f), ("drive.seek", 60f), ("drive.spare", 5f), ("drive.theirs", 5f), ("drive.theirway", 0.7f), ("drive.trim", 0.9f), ("drive.turn", 1.45f), ("drive.wall", 1.5f), ("drive.want", 1.3f), ("drive.want.map", 2.6f), ("drive.yours", 5f), ("drive.yours.map", 1.6f), ("drop.max", 5f), ("enemy.gone", 6f), ("enemy.hunt", 90f), ("enemy.hurt", 1f), ("enemy.mend.after", 30f), ("explore.far", 60f), ("explore.near", 20f), ("fidget.every", 0f), ("fight.cover", 1f), ("fight.dodge.every", 0.8f), ("fight.dodge.wide", 0.55f), ("fight.duck.hit", 0.7f), ("fight.duck.least", 0.45f), ("fight.duck.most", 0.85f), ("fight.duck.moving", 0.32f), ("fight.duck.still", 0.75f), ("fight.move", 1f), ("fight.reload.move", 1f), ("fight.spread", 5f), ("fight.still", 0.35f), ("fire.burst.most", 1.2f), ("fire.byplayer.apart", 0.35f), ("fire.byplayer.clear", 0.5f), ("fire.byplayer.far", 9f), ("fire.ready", 3f), ("flesh.blood", 1f), ("flesh.mpa", 1f), ("flesh.resist", 0.6f), ("flinch.calm", 6f), ("flinch.range", 14f), ("flinch.size", 1f), ("flinch.squat", 0.55f), ("follow.above", 1f), ("follow.below", 1f), ("follow.regoal", 1.5f), ("follow.side", 1f), ("follow.yourun", 2.8f), ("foot.knock.fall", 3f), ("gaze.drift", 1.5f), ("gaze.every.most", 3.5f), ("gaze.quick", 9f), ("grab.longest", 12f), ("grab.offset", 0.6f), ("grab.open", 0.35f), ("grab.pull", 12f), ("grab.reach", 0.25f), ("grab.shut", 0.6f), ("grab.slip", 1.5f), ("grab.step", 2.5f), ("grab.throw", 1.4f), ("guard.rise", 3.2f), ("guard.rise.clear", 1.6f), ("guard.rise.drop", 1f), ("guard.rise.for", 0.3f), ("guard.rise.free", 0.4f), ("guard.rise.slow", 1.2f), ("guard.speed", 9.5f), ("guard.up", 9f), ("gun.kick", 4f), ("gun.kick.time", 0.07f), ("gun.kind.long", 0.46f), ("gun.kind.smg", 0.3f), ("gun.lock", 1f), ("gun.lock.most", 0.35f), ("gun.lock.pull", 0.55f), ("gun.seek", 45f), ("gun.settle", 1.5f), ("head.max", 0.99f), ("hold.ease", 6f), ("hold.ease.getting", 3f), ("hold.fix.afterShot", 0.4f), ("hold.fix.degrees", 120f), ("hold.fix.most", 0.5f), ("hold.fix.rate", 1.5f), ("hold.fix.within", 35f), ("hold.left.pull", 0.35f), ("hold.onehand.most", 1.4f), ("hold.onehand.time", 0.7f), ("hold.reach.grab", 0.08f), ("hold.reach.time", 0.7f), ("hold.rifle.roll", 0f), ("hold.settle.time", 0.45f), ("hold.steady.speed", 0.8f), ("hold.steady.spin", 1.5f), ("hurt.punch", 0.06f), ("hurt.punch.speed", 2.5f), ("jump.longest", 1.6f), ("lab.chatty", 0f), ("land.arms", 1f), ("land.dip", 0.32f), ("land.falling", 2.6f), ("land.from", 0.7f), ("land.full", 3f), ("learn.context", 3f), ("learned.aimfix.most", 25f), ("learned.aimfix.rate", 2.5f), ("learned.grab", 0.12f), ("learned.hold", 1f), ("learned.look.ease", 8f), ("learned.reload", 1f), ("learned.reload.speed", 1f), ("lesson.big", 1.1f), ("lesson.every", 90f), ("lesson.front", 1.5f), ("lesson.litter", 30f), ("lesson.reach", 0.4f), ("lesson.spot", 60f), ("lesson.spot.chance", 0.6f), ("life.go", 4f), ("life.sneak", 0.22f), ("life.squat", 0.5f), ("life.stroll", 0.45f), ("life.tinker", 1.7f), ("life.use", 0.8f), ("lying.speed", 1.5f), ("meet.chance", 0.6f), ("meet.every", 40f), ("meet.far", 6f), ("meet.near", 1.7f), ("meet.on", 1f), ("melee.fix", 0.12f), ("melee.keep", 12f), ("melee.seek", 22f), ("move.byhead", 1f), ("move.curve", 2.6f), ("move.swing", 360f), ("move.turn.fast", 110f), ("move.turn.slow", 200f), ("moves.longest", 30f), ("nav.again", 2.5f), ("nav.ahead", 1.3f), ("nav.corner", 0.8f), ("nav.keep.end", 5f), ("nav.keep.shorter", 0.75f), ("nav.regoal", 1.5f), ("nav.side.keep", 2.5f), ("nav.slide.on", 0.35f), ("nav.stray", 2f), ("nav.swerve", 40f), ("nav.turn", 170f), ("net.pull", 14f), ("net.push", 18f), ("net.snap", 2.5f), ("net.vertical", 1.2f), ("own.thing.room", 0.5f), ("people.alarm.squat", 0.5f), ("people.brace", 1f), ("people.far", 18f), ("people.on", 1f), ("people.run", 3f), ("people.runner.every", 7f), ("people.runner.follow", 0.3f), ("people.rush.step", 1f), ("people.rush.time", 1.3f), ("point.arm", 0.45f), ("point.far", 14f), ("point.go", 0.7f), ("point.hold", 0.6f), ("point.thing", 0.9f), ("point.thing.far", 40f), ("portal.follow", 30f), ("portal.patience", 3.5f), ("portal.reach", 0.9f), ("portal.worth", 0.7f), ("punch.line", 0f), ("punch.line.from", 1.2f), ("punch.speed", 1.2f), ("relax.arms", 0.85f), ("relax.drop", 0.22f), ("reload.rest", 6f), ("roam.bend", 0.13f), ("roam.bend.round", 4.5f), ("roam.high", 0.45f), ("roam.pause", 0.4f), ("roam.take", 0.9f), ("roam.tall", 0.6f), ("roam.thing", 2.6f), ("roam.thing.far", 40f), ("seat.off", 0.45f), ("smooth.auto", 0f), ("smooth.jump", 0.07f), ("smooth.speed", 6.5f), ("smooth.time", 0.32f), ("smooth.turn", 22f), ("sprint.again", 0.7f), ("sprint.gait", 2.6f), ("sprint.speed", 2.9f), ("sprint.times", 2.1f), ("squat.on", 1f), ("stare.cone", 9f), ("stare.every", 14f), ("stare.hold", 1.3f), ("stow.after", 7f), ("teach.imitate", 0.6f), ("teach.punch.forward", 1.8f), ("teach.punch.speed", 3f), ("tinker.seek", 25f), ("tool.climb.most", 30f), ("tool.climb.onto", 0.9f), ("tool.climb.press", 0f), ("tool.climb.stand", 0.45f), ("tool.every", 14f), ("trip.damage", 0.3f), ("trip.fall", 4.5f), ("trip.impulse", 30f), ("trip.least", 1.6f), ("trip.leg.chance", 0.6f), ("trip.legs", 0.6f), ("trip.limp", 1f), ("trip.low", 0.38f), ("trip.most", 4.5f), ("trip.on", 1f), ("trip.pull", 2.4f), ("trip.rest", 1.5f), ("trip.rise", 1.7f), ("trip.shove", 1f), ("trip.speed", 2.2f), ("walk.most", 2.6f), ("wall.arm", 0.85f), ("wall.finish", 1.55f), ("wall.off", 0.06f), ("wallgrab", 1f), ("wallgrab.reach", 0.1f), ("wallgrab.wait", 0.08f), ("wave.cone", 35f), ("wave.far", 25f), ("wave.hello.after", 45f), ("wave.hello.chance", 0.5f), ("wave.see.height", -0.15f), ("wave.see.speed", 0.5f), ("you.still", 50f), ("you.still.every", 150f) }; private static string Dir => Path.Combine(MelonEnvironment.UserDataDirectory, "DoppelExtras"); private static string NamesFile => Path.Combine(Dir, "names.txt"); private static string VoiceDir => Path.Combine(Dir, "Voices"); private static int ClipCount() { int num = 0; foreach (List<AudioClip> value in _clipsBy.Values) { num += value.Count; } return num; } public override void OnInitializeMelon() { _cat = MelonPreferences.CreateCategory("DoppelExtras"); NamesOn = _cat.CreateEntry<bool>("CustomNames", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagsOn = _cat.CreateEntry<bool>("NameTags", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagShowGoal = _cat.CreateEntry<bool>("TagShowGoal", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagShowHeight = _cat.CreateEntry<bool>("TagShowHeight", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagHeight = _cat.CreateEntry<float>("TagHeight", 0.3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagSize = _cat.CreateEntry<float>("TagSize", 1.2f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagFadeStart = _cat.CreateEntry<float>("TagFadeStart", 12f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagFadeEnd = _cat.CreateEntry<float>("TagFadeEnd", 25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TagNoFade = _cat.CreateEntry<bool>("TagNeverFade", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); TraitDesc = _cat.CreateEntry<bool>("TraitDescriptions", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceOn = _cat.CreateEntry<bool>("VoiceChat", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceAvatar = _cat.CreateEntry<bool>("VoiceAvatarVocals", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceNet = _cat.CreateEntry<bool>("BotVoiceToFusion", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); JoinGreet = _cat.CreateEntry<bool>("BotGreetsOnJoin", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceWav = _cat.CreateEntry<bool>("VoiceCustomWavs", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceChance = _cat.CreateEntry<float>("VoiceChance", 35f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceMinGap = _cat.CreateEntry<float>("VoiceMinGap", 8f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceMaxGap = _cat.CreateEntry<float>("VoiceMaxGap", 30f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VoiceVolume = _cat.CreateEntry<float>("VoiceVolume", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SitOn = _cat.CreateEntry<bool>("SituationalVoice", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SitChance = _cat.CreateEntry<float>("SituationalChance", 60f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SitCooldown = _cat.CreateEntry<float>("SituationalCooldown", 4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ConvoOn = _cat.CreateEntry<bool>("Conversations", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ConvoChance = _cat.CreateEntry<float>("ConversationChance", 40f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ConvoWalk = _cat.CreateEntry<bool>("ConversationWalkUp", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ConvoRange = _cat.CreateEntry<float>("ConversationRange", 5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeOn = _cat.CreateEntry<bool>("FleeFromBigger", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleePlayer = _cat.CreateEntry<bool>("FleeFromPlayers", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeBots = _cat.CreateEntry<bool>("FleeFromBots", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeEnemies = _cat.CreateEntry<bool>("EnemiesFleeToo", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeShout = _cat.CreateEntry<bool>("ShoutWhenFleeing", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeSwitchMode = _cat.CreateEntry<bool>("SwitchToBrainToFlee", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeRatio = _cat.CreateEntry<float>("FleeSizeRatio", 1.25f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeRange = _cat.CreateEntry<float>("FleeRange", 12f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeBoost = _cat.CreateEntry<float>("FleeBoost", 5f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MapSpawnOn = _cat.CreateEntry<bool>("MapSpawning", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AutoPopulate = _cat.CreateEntry<bool>("AutoPopulateOnLoad", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); AutoCount = _cat.CreateEntry<int>("AutoPopulateCount", 4, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SpawnEnemies = _cat.CreateEntry<bool>("SpawnEnemies", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); EnemyPercent = _cat.CreateEntry<int>("EnemyPercent", 25, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ClimbOn = _cat.CreateEntry<bool>("ClimbOnEntities", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ClimbOnPlayer = _cat.CreateEntry<bool>("ClimbOnPlayer", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ClimbOnBots = _cat.CreateEntry<bool>("ClimbOnBots", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ClimbCooldown = _cat.CreateEntry<float>("ClimbCooldown", 4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); ClimbReach = _cat.CreateEntry<float>("ClimbReach", 1.3f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); RandomSizes = _cat.CreateEntry<bool>("RandomSizes", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SlzAvatar = _cat.CreateEntry<bool>("RandomSlzAvatar", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); MeleeUpright = _cat.CreateEntry<bool>("MeleeGrabUpright", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); PlayerTalk = _cat.CreateEntry<bool>("BotsTalkToPlayers", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); PitchVary = _cat.CreateEntry<bool>("VaryVoicePitch", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); BrainAuto = _cat.CreateEntry<bool>("BotsUseBrainAutomatically", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); PitchRange = _cat.CreateEntry<float>("VoicePitchSemitones", 1f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FusionList = _cat.CreateEntry<bool>("ShowAsFusionPlayers", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); JawOwn = _cat.CreateEntry<bool>("BotOwnJaw", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); FleeBrain = _cat.CreateEntry<bool>("BrainBotsFlee", false, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); RedTags = _cat.CreateEntry<bool>("EnemyRedTags", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); VehicleUse = _cat.CreateEntry<float>("VehicleUse", 1.4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); CrouchUse = _cat.CreateEntry<float>("CrouchUse", 1.4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SizeMin = _cat.CreateEntry<float>("SizeMin", 0.7f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); SizeMax = _cat.CreateEntry<float>("SizeMax", 1.4f, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); Directory.CreateDirectory(VoiceDir); EnsureNames(); LoadNames(); LoadClips(); BindReflection(); PatchDoppel(); PatchGrab(); NativeBots.Initialize(((MelonBase)this).HarmonyInstance); try { ApplyVehicleCrouch(log: false); } catch (Exception e) { LogOnce("tuning-init", e); } BuildMenu(); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { _sceneAt = Time.time; _later.Clear(); _convos.Clear(); _spawnPoints.Clear(); _spawnScanned = false; _queue.Clear(); _resize.Clear(); _busy = false; _autoAt = (AutoPopulate.Value ? (Time.time + 10f) : (-1f)); NativeBots.Clear(); DestroyAllTags(); _state.Clear(); } public override void OnApplicationQuit() { MelonPreferences.Save(); } private static void BindReflection() { try { _fName = AccessTools.Field(typeof(Bot), "nameIs"); _fNav = AccessTools.Field(typeof(Bot), "nav"); _mHeight = AccessTools.PropertyGetter(typeof(Bot), "standingHeight"); _mClimb = AccessTools.Method(typeof(Bot), "TryStartClimb", new Type[1] { typeof(Vector3) }, (Type[])null); _fBots = AccessTools.Field(typeof(BotManager), "bots"); _mSpawnAt = AccessTools.Method(typeof(BotManager), "SpawnAt", new Type[4] { typeof(bool), typeof(Vector3), typeof(Vector3), typeof(Action<Bot>) }, (Type[])null); _fNetId = AccessTools.Field(typeof(Bot), "netId"); _fNetOwner = AccessTools.Field(typeof(Bot), "netOwner"); _fTuningValues = AccessTools.Field(typeof(Tuning), "values"); _fTuningKnown = AccessTools.Field(typeof(Tuning), "known"); _fTuningUnwritten = AccessTools.Field(typeof(Tuning), "unwritten"); _mTuningWrite = AccessTools.Method(typeof(Tuning), "Write", (Type[])null, (Type[])null); } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] reflection bind failed: " + ex.Message); } if (_fName == null) { MelonLogger.Warning("[DoppelExtras] Bot.nameIs not found - custom names disabled."); } if (_fNav == null) { MelonLogger.Warning("[DoppelExtras] Bot.nav not found - flee destination push disabled."); } if (_mClimb == null) { MelonLogger.Warning("[DoppelExtras] Bot.TryStartClimb not found - climb-on-entity disabled."); } if (_fBots == null) { MelonLogger.Warning("[DoppelExtras] BotManager.bots not found - map spawning disabled."); } } private static void PatchDoppel() { //IL_0037: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Bot), "Fit", (Type[])null, (Type[])null); if (methodInfo == null) { MelonLogger.Warning("[DoppelExtras] Bot.Fit not found - fleeing only uses the nav push."); return; } new Harmony("DoppelExtras").Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Extras), "FitPostfix", (Type[])null) { priority = 0 }, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] Fit patch failed: " + ex.Message); } } private static void PatchGrab() { //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown try { _mIsMelee = AccessTools.Method(typeof(Bot), "IsMelee", (Type[])null, (Type[])null); _mBotOf = AccessTools.Method(typeof(BotManager), "Of", (Type[])null, (Type[])null); MethodInfo methodInfo = AccessTools.Method(typeof(Bot), "Grab", new Type[3] { typeof(Hand), typeof(Grip), typeof(Quaternion?) }, (Type[])null); if (methodInfo == null || _mIsMelee == null) { MelonLogger.Warning("[DoppelExtras] Bot.Grab / IsMelee not found - upright melee grabs disabled."); return; } Harmony val = new Harmony("DoppelExtras.Grab"); val.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Extras), "GrabPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Bot), "HandleOf", (Type[])null, (Type[])null); if (methodInfo2 != null) { val.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, new HarmonyMethod(typeof(Extras), "HandleOfPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] Grab patch failed: " + ex.Message); } } private static bool BladeName(string n) { return n.Contains("blade") || n.Contains("head") || n.Contains("rim") || n.Contains("pan"); } private static bool HandleName(string n) { return n.Contains("handle") || n.Contains("hilt") || n.Contains("grip") || n.Contains("primary"); } public static void HandleOfPostfix(Rigidbody __0, ref Grip __result) { try { if (!MeleeUpright.Value || (Object)(object)__result == (Object)null || (Object)(object)__0 == (Object)null || !BladeName(((Object)__result).name.ToLowerInvariant())) { return; } Poolee componentInParent = ((Component)__0).GetComponentInParent<Poolee>(); Transform val = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).transform : ((Component)__0).transform); foreach (Grip componentsInChild in ((Component)val).GetComponentsInChildren<Grip>(false)) { if (!((Object)(object)componentsInChild == (Object)null) && ((Behaviour)componentsInChild).enabled && !componentsInChild.IsInteractionDisabled && !componentsInChild.HasAttachedHands()) { string n = ((Object)componentsInChild).name.ToLowerInvariant(); if (HandleName(n) && !BladeName(n)) { __result = componentsInChild; break; } } } } catch (Exception e) { LogOnce("handleof", e); } } public static void GrabPrefix(Hand __0, Grip __1) { //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0114: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Invalid comparison between Unknown and I4 //IL_020f: 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_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Invalid comparison between Unknown and I4 //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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Invalid comparison between Unknown and I4 //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Invalid comparison between Unknown and I4 //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: 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_0258: Unknown result type (might be due to invalid IL or missing references) //IL_025a: Unknown result type (might be due to invalid IL or missing references) //IL_025b: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_027a: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0296: Unknown result type (might be due to invalid IL or missing references) //IL_029f: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: 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_02bd: 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_016c: 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_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: 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_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) try { if (!MeleeUpright.Value || (Object)(object)__0 == (Object)null || (Object)(object)__1 == (Object)null || __1.HasAttachedHands()) { return; } Rigidbody componentInParent = ((Component)__1).GetComponentInParent<Rigidbody>(); if ((Object)(object)componentInParent == (Object)null || componentInParent.isKinematic || !(bool)_mIsMelee.Invoke(null, new object[1] { componentInParent })) { return; } if (_mBotOf != null) { RigManager componentInParent2 = ((Component)__0).GetComponentInParent<RigManager>(); Bot val = (Bot)(((Object)(object)componentInParent2 != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if (val == null) { return; } Mode mode = val.mode; if ((int)mode == 6 || (int)mode == 7 || (int)mode == 8 || (int)mode == 9) { return; } } Vector3 position = ((Component)__1).transform.position; float num = 0f; Vector3 val2 = position; foreach (Collider componentsInChild in ((Component)componentInParent).GetComponentsInChildren<Collider>()) { if ((Object)(object)componentsInChild == (Object)null || componentsInChild.isTrigger) { continue; } Bounds bounds = componentsInChild.bounds; for (int i = 0; i < 8; i++) { Vector3 val3 = ((Bounds)(ref bounds)).center + Vector3.Scale(((Bounds)(ref bounds)).extents, new Vector3(((i & 1) == 0) ? (-1f) : 1f, ((i & 2) == 0) ? (-1f) : 1f, ((i & 4) == 0) ? (-1f) : 1f)); Vector3 val4 = val3 - position; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude > num) { num = sqrMagnitude; val2 = val3; } } } Vector3 val5 = val2 - position; if (!(((Vector3)(ref val5)).magnitude < 0.15f) && !(Vector3.Angle(val5, Vector3.up) < 15f)) { Quaternion val6 = Quaternion.FromToRotation(((Vector3)(ref val5)).normalized, Vector3.up); Vector3 val7 = position + val6 * (((Component)componentInParent).transform.position - position); Quaternion val8 = val6 * ((Component)componentInParent).transform.rotation; ((Component)componentInParent).transform.SetPositionAndRotation(val7, val8); componentInParent.position = val7; componentInParent.rotation = val8; componentInParent.velocity = Vector3.zero; componentInParent.angularVelocity = Vector3.zero; } } catch (Exception e) { LogOnce("gripup", e); } } public static void FitPostfix(Bot __instance, object g, ref float __result) { try { if (!FleeOn.Value || !_state.TryGetValue(__instance, out var value) || !value.Fleeing) { return; } string text = g.ToString(); switch (text) { case "Retreat": __result += FleeBoost.Value; break; default: if (!(text == "Practice")) { break; } goto case "Fight"; case "Fight": case "Brawl": case "ArmUp": case "Guard": case "Play": __result = Mathf.Min(__result, 0f); break; } } catch (Exception) { } } public override void OnUpdate() { try { float time = Time.time; if (time >= _nextThink) { _nextThink = time + 0.25f; Think(time); } SpawnTick(time); } catch (Exception e) { LogOnce("update", e); } } public override void OnLateUpdate() { try { NativeBots.Update(); } catch (Exception e) { LogOnce("nativebots", e); } try { UpdateTags(); } catch (Exception e2) { LogOnce("tags", e2); } try { FixesTick(); } catch (Exception e3) { LogOnce("fixes", e3); } } private static void LogOnce(string where, Exception e) { if (_logged.Add(where)) { MelonLogger.Warning("[DoppelExtras] " + where + ": " + e); } } private static List<Bot> Bots() { List<Bot> list = new List<Bot>(); try { foreach (Bot item in BotManager.All) { if (item != null) { list.Add(item); } } } catch (Exception) { } return list; } private static void Think(float now) { //IL_01ef: 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_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Invalid comparison between Unknown and I4 List<Bot> bots = Bots(); List<Bot> list = _state.Keys.Where((Bot b) => !bots.Contains(b)).ToList(); foreach (Bot item in list) { if (list.Count <= 2 && _state.TryGetValue(item, out var value) && value.WasAlive && now - _sceneAt > 4f) { OnDeath(null, value, value.LastPos, value.LastEnemy, bots, now); } DropState(item); } RunLater(now); for (int num = _resize.Count - 1; num >= 0; num--) { if (!(now < _resize[num].Value)) { Bot key = _resize[num].Key; _resize.RemoveAt(num); try { if (key != null && key.Alive) { ApplyRandomSize(key.rig); } } catch (Exception) { } } } if (bots.Count == 0) { return; } RefreshEntities(bots, now); foreach (Bot item2 in bots) { bool flag; try { flag = item2.Alive; } catch (Exception) { flag = false; } if (!flag) { if (_state.TryGetValue(item2, out var value2) && value2.WasAlive) { value2.WasAlive = false; OnDeath(item2, value2, value2.LastPos, value2.LastEnemy, bots, now); } continue; } if (!_state.TryGetValue(item2, out var value3)) { value3 = new State { NextVoice = now + Rand(VoiceMinGap.Value, VoiceMaxGap.Value), BrainAt = now + 1.5f }; _state[item2] = value3; AssignName(item2, value3); } value3.Height = HeightOf(item2); SyncName(item2, value3); SyncFusion(item2, value3); if (!value3.BrainDone && now >= value3.BrainAt) { value3.BrainDone = true; try { if (BrainAuto.Value && (int)item2.mode == 0) { item2.SetMode((Mode)4); } } catch (Exception e) { LogOnce("brainauto", e); } } TickFlee(item2, value3, now); TickVoice(item2, value3, now); TickClimb(item2, value3, now); TickSituation(item2, value3, bots, now); } TickPlayerFall(bots, now); TickConversations(bots, now); TickPlayerTalk(bots, now); } private static float Rand(float a, float b) { if (b < a) { b = a; } return a + (float)_rng.NextDouble() * (b - a); } private static void RefreshEntities(List<Bot> bots, float now) { _entities.Clear(); try { RigManager rigManager = Player.RigManager; if ((Object)(object)rigManager != (Object)null && (Object)(object)Player.Head != (Object)null) { _entities.Add(new Entity { Head = Player.Head, Height = HeightOfRig(rigManager, Player.Head), IsPlayer = true, Name = "you" }); } } catch (Exception) { } try { List<RigManager> list = NetBots.OtherPlayers(); if (list != null) { foreach (RigManager item in list) { if (!((Object)(object)item == (Object)null)) { Transform val = RigHead(item); if ((Object)(object)val != (Object)null) { _entities.Add(new Entity { Head = val, Height = HeightOfRig(item, val), IsPlayer = true, Name = "player" }); } } } } } catch (Exception) { } foreach (Bot bot in bots) { try { if (bot.Alive && !((Object)(object)bot.Head == (Object)null)) { _entities.Add(new Entity { Head = bot.Head, Height = HeightOf(bot), Bot = bot, Name = NameOf(bot) }); } } catch (Exception) { } } } private static Transform RigHead(RigManager rm) { try { return ((Rig)rm.physicsRig).m_head; } catch (Exception) { return null; } } private static bool Sane(float h) { return !float.IsNaN(h) && !float.IsInfinity(h) && h >= 0.3f && h <= 8f; } private static float HeightOfRig(RigManager rm, Transform head) { float num = HeightOfRigRaw(rm, head); return Sane(num) ? num : 1.7f; } private static float HeightOfRigRaw(RigManager rm, Transform head) { //IL_0043: 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) try { Avatar avatar = rm._avatar; if ((Object)(object)avatar != (Object)null && avatar.height > 0.2f) { return avatar.height; } } catch (Exception) { } try { RaycastHit val = default(RaycastHit); if ((Object)(object)head != (Object)null && Physics.Raycast(head.position, Vector3.down, ref val, 4f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).distance + 0.1f; } } catch (Exception) { } return 1.7f; } private static float HeightOf(Bot bot) { try { if (_mHeight != null) { float num = (float)_mHeight.Invoke(bot, null); if (Sane(num)) { return num; } } } catch (Exception) { } return HeightOfRig(bot.rig, bot.Head); } private static string NameOf(Bot b) { try { return b.Name; } catch (Exception) { return "bot"; } } private static void EnsureNames() { if (!File.Exists(NamesFile)) { File.WriteAllLines(NamesFile, new string[100] { "Michael", "Sasquatch", "Sharpol", "Xago", "MellowFellow", "Sean Madden", "Karma", "Mushroom", "LKroxas", "ARDI", "west745", "BacBean", "A Chef", "A nice lad", "Bazinga", "ChazMan", "stutz", "Skefil", "Oddity", "Robot3sixty", "Lilith", "M1sfit", "tealar80", "geeks4lease", "Anderanged", "aquantic", "lenn", "Cosmic Meatball", "STICKER", "Geoff", "Gavin", "Garry", "Jack", "Ray", "Jeff", "Oliver", "Gordon", "Bigs", "Human", "Somebody", "Bill", "BigBoi", "Dragon Curve", "Jackson", "ThatCat", "God", "Dat Gamer", "DaJuan", "Anonymous", "Anon", "Lapis Lazuli", "George Patton", "Finger", "Omega", "Studs", "J7", "GreenSquirrel", "doug", "Bread", "hog", "Moyai", "Cyber1738", "Benbot20", "Plague doc", "Physics Prop", "scotty900", "MrViking8", "Morphine", "FarPlay333", "Osiya21", "fantaymer88", "IDK", "aguyonpc", "MFW", "TNT", "PeterPancake", "Muscles", "Mee6", "Bridge", "Future", "Badger", "Timmy", "Major", "Minor", "ZooWeeMama", "Robert", "Past", "Beep", "That Cat", "Bearman_56", "Davidb45", "Somewhere", "Stuggs", "Barney Calhoun", "Blocks", "Frogurt", "Chaz", "Spiral", "Six", "sniper" }); } } private static void LoadNames() { _names.Clear(); try { string[] array = File.ReadAllLines(NamesFile); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length > 0 && !text2.StartsWith("#")) { _names.Add(text2); } } } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] names.txt: " + ex.Message); } } private static int NetKey(Bot bot) { try { if (_fNetId == null) { return -1; } int num = Convert.ToInt32(_fNetId.GetValue(bot)); if (num == 0) { return -1; } int num2 = ((_fNetOwner != null) ? Convert.ToInt32(_fNetOwner.GetValue(bot)) : 0); if (num2 == 0) { num2 = NetBots.Me?.Invoke() ?? 0; } return num2 * 256 + num; } catch (Exception) { return -1; } } private static void SyncName(Bot bot, State s) { if (!NamesOn.Value || _fName == null || _names.Count == 0) { return; } int num = NetKey(bot); if (num >= 0 && num != s.NameKey) { s.NameKey = num; uint num2 = (uint)(num * -1640531535); string text = _names[(int)((num2 >> 8) % (uint)_names.Count)]; if (s.Name != null) { _usedNames.Remove(s.Name); } try { _fName.SetValue(bot, text); } catch (Exception) { } s.Name = text; } } private static void AssignName(Bot bot, State s) { if (!NamesOn.Value || _fName == null || _names.Count == 0) { s.Name = NameOf(bot); return; } string text = null; for (int i = 0; i < 20; i++) { string text2 = _names[_rng.Next(_names.Count)]; if (!_usedNames.Contains(text2)) { text = text2; break; } } if (text == null) { text = _names[_rng.Next(_names.Count)] + _rng.Next(2, 99); } _usedNames.Add(text); try { _fName.SetValue(bot, text); } catch (Exception) { } s.Name = text; } private static void UpdateTags() { //IL_0304: Unknown result type (might be due to invalid IL or missing references) //IL_0324: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_035c: Unknown result type (might be due to invalid IL or missing references) //IL_035e: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Expected O, but got Unknown //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Expected O, but got Unknown bool value = TagsOn.Value; Camera main = Camera.main; foreach (KeyValuePair<Bot, State> item in _state) { Bot key = item.Key; State value2 = item.Value; try { Transform head; bool alive; try { head = key.Head; alive = key.Alive; } catch (Exception) { goto end_IL_003e; } float num = 1f; bool flag = value && alive && (Object)(object)head != (Object)null && (Object)(object)main != (Object)null; if (flag && NetworkInfo.HasServer) { flag = CommonPreferences.NameTags; } if (flag && !TagNoFade.Value) { Vector3 val = head.position - ((Component)main).transform.position; float magnitude = ((Vector3)(ref val)).magnitude; float num2 = Mathf.Max(3f, TagFadeEnd.Value); float num3 = Mathf.Min(TagFadeStart.Value, num2 - 0.5f); flag = magnitude <= num2; num = (flag ? (1f - Mathf.Clamp01((magnitude - num3) / (num2 - num3))) : 0f); } if (!flag) { if (value2.HeadUI != null) { value2.HeadUI.Visible = false; } } else { if ((Object)(object)key.rig == (Object)null || (Object)(object)key.rig.avatar == (Object)null) { continue; } if (value2.HeadUI == null) { value2.HeadUI = new RigHeadUI(); value2.Tag = new RigNameTag(); value2.HeadUI.RegisterElement((IPopupLayoutElement)(object)value2.Tag); value2.HeadUI.Spawn(); } value2.HeadUI.Visible = true; string text = value2.Name ?? NameOf(key); if (TagShowHeight.Value) { text = text + "\n" + value2.Height.ToString("0.00") + " m"; } if (TagShowGoal.Value) { string text2 = ""; try { text2 = ((object)Unsafe.As<Mode, Mode>(ref key.mode)/*cast due to .constrained prefix*/).ToString() + " / " + ((object)Unsafe.As<Goal, Goal>(ref key.goal)/*cast due to .constrained prefix*/).ToString(); } catch (Exception) { } if (value2.Fleeing) { text2 = "FLEEING"; } text = text + "\n" + text2; } if (value2.TagText != text) { value2.TagText = text; value2.Tag.Username = text; } bool flag2 = false; try { flag2 = key.enemy; } catch (Exception) { } Color val2 = (Color)((flag2 && RedTags.Value) ? new Color(1f, 0.35f, 0.3f, 1f) : Color.white); val2.a = Mathf.Round(Mathf.Clamp01(num) * 20f) / 20f; if (value2.TagColor != val2) { value2.TagColor = val2; value2.Tag.Color = val2; } value2.HeadUI.UpdateScale(key.rig); value2.HeadUI.UpdateTransform(key.rig); ApplyTagLook(value2.HeadUI); continue; } end_IL_003e:; } catch (Exception e) { LogOnce("tags", e); } } } private static void ApplyTagLook(RigHeadUI ui) { //IL_005c: 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_0078: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00a1: Unknown result type (might be due to invalid IL or missing references) try { if (_fLayout == null) { _fLayout = typeof(RigHeadUI).GetField("_layoutTransform", BindingFlags.Instance | BindingFlags.NonPublic); } Transform val = (Transform)((_fLayout != null) ? /*isinst with value type is only supported in some contexts*/: null); if (!((Object)(object)val == (Object)null)) { val.localScale *= TagSize.Value; val.position += Vector3.up * TagHeight.Value * val.localScale.y; } } catch (Exception e) { LogOnce("taglook", e); } } private static void DropState(Bot b) { if (_state.TryGetValue(b, out var value)) { try { if (value.HeadUI != null) { value.HeadUI.Despawn(); } } catch (Exception) { } try { if ((Object)(object)value.Audio != (Object)null) { Object.Destroy((Object)(object)((Component)value.Audio).gameObject); } } catch (Exception) { } if (value.Name != null) { _usedNames.Remove(value.Name); } RemoveFake(value); } _state.Remove(b); } private static void DestroyAllTags() { foreach (State value in _state.Values) { RemoveFake(value); try { if (value.HeadUI != null) { value.HeadUI.Despawn(); } } catch (Exception) { } try { if ((Object)(object)value.Audio != (Object)null) { Object.Destroy((Object)(object)((Component)value.Audio).gameObject); } } catch (Exception) { } } _usedNames.Clear(); } private static void SyncFusion(Bot bot, State s) { if (!FusionList.Value || !NetworkInfo.IsHost) { RemoveFake(s); return; } try { s.Fake = NativeBots.Sync(bot, s.Name ?? NameOf(bot)); } catch (Exception e) { LogOnce("fusionlist", e); } } private static void RemoveFake(State s) { if (s.Fake != null) { try { NativeBots.Remove(s.Fake); } catch (Exception e) { LogOnce("fusionremove", e); } s.Fake = null; } } internal static string TraitText(Bot bot) { try { string text = bot.personality.Describe(); if (!string.IsNullOrEmpty(text)) { text = text.Trim().TrimStart(',', ' '); bool flag = false; try { flag = bot.enemy; } catch (Exception) { } return (flag ? "Enemy, " : "") + text; } } catch (Exception e) { LogOnce("traits", e); } return "Doppel bot"; } internal static float BotAmplitude(Bot bot) { float num = 0f; try { if (_state.TryGetValue(bot, out var value) && (Object)(object)value.Audio != (Object)null && value.Audio.isPlaying) { num = Mathf.Max(num, Loudness(value.Audio)); } } catch (Exception) { } try { AudioSource mouthSrc = bot.rig.physicsRig.headSfx.mouthSrc; if ((Object)(object)mouthSrc != (Object)null && mouthSrc.isPlaying) { num = Mathf.Max(num, Loudness(mouthSrc)); } } catch (Exception) { } return num; } private static float Loudness(AudioSource src) { if (_sampleBuf == null) { _sampleBuf = new Il2CppStructArray<float>(128L); } src.GetOutputData(_sampleBuf, 0); float num = 0f; for (int i = 0; i < ((Il2CppArrayBase<float>)(object)_sampleBuf).Length; i++) { num += Mathf.Abs(((Il2CppArrayBase<float>)(object)_sampleBuf)[i]); } return Mathf.Clamp01(num / (float)((Il2CppArrayBase<float>)(object)_sampleBuf).Length * 2f); } private static void LoadClips() { _clipsBy.Clear(); try { string[] cats = _cats; foreach (string path in cats) { Directory.CreateDirectory(Path.Combine(VoiceDir, path)); } string[] files = Directory.GetFiles(VoiceDir, "*.wav"); foreach (string file in files) { AddClip("idle", file); } string[] cats2 = _cats; foreach (string text in cats2) { string[] files2 = Directory.GetFiles(Path.Combine(VoiceDir, text), "*.wav"); foreach (string file2 in files2) { AddClip(text, file2); } } MelonLogger.Msg("[DoppelExtras] Loaded " + ClipCount() + " voice clip(s) in " + _clipsBy.Count + " categories from " + VoiceDir); } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] voice clips: " + ex.Message); } } private static void AddClip(string cat, string file) { AudioClip val = LoadWav(file); if (!((Object)(object)val == (Object)null)) { if (!_clipsBy.TryGetValue(cat, out var value)) { value = (_clipsBy[cat] = new List<AudioClip>()); } value.Add(val); } } private static AudioClip Pick(string cat) { if (!_clipsBy.TryGetValue(cat, out var value) || value.Count == 0) { return null; } AudioClip val = value[_rng.Next(value.Count)]; if (value.Count > 1 && _lastClip.TryGetValue(cat, out var value2) && (Object)(object)value2 == (Object)(object)val) { val = value[_rng.Next(value.Count)]; } _lastClip[cat] = val; return val; } private static AudioClip LoadWav(string path) { try { byte[] array = File.ReadAllBytes(path); if (array.Length < 44 || array[0] != 82 || array[1] != 73 || array[2] != 70 || array[3] != 70) { return null; } int i = 12; int num = 1; int num2 = 44100; int num3 = 16; int num4 = -1; int num5 = 0; int num6; for (; i + 8 <= array.Length; i += 8 + num6 + (num6 & 1)) { string text = Encoding.ASCII.GetString(array, i, 4); num6 = BitConverter.ToInt32(array, i + 4); if (text == "fmt ") { int num7 = BitConverter.ToInt16(array, i + 8); num = BitConverter.ToInt16(array, i + 10); num2 = BitConverter.ToInt32(array, i + 12); num3 = BitConverter.ToInt16(array, i + 22); if (num7 != 1 && num7 != 65534) { return null; } } else if (text == "data") { num4 = i + 8; num5 = Math.Min(num6, array.Length - num4); break; } } if (num4 < 0 || num3 != 16 || num < 1) { return null; } int num8 = num5 / (2 * num); float[] array2 = new float[num8]; for (int j = 0; j < num8; j++) { float num9 = 0f; for (int k = 0; k < num; k++) { num9 += (float)BitConverter.ToInt16(array, num4 + (j * num + k) * 2) / 32768f; } array2[j] = num9 / (float)num; } AudioClip val = AudioClip.Create(Path.GetFileNameWithoutExtension(path), num8, 1, num2, false); val.SetData(Il2CppStructArray<float>.op_Implicit(array2), 0); return val; } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] bad wav " + Path.GetFileName(path) + ": " + ex.Message); return null; } } private static void TickVoice(Bot bot, State s, float now) { if (VoiceOn.Value && !(now < s.NextVoice)) { s.NextVoice = now + Rand(VoiceMinGap.Value, VoiceMaxGap.Value); if (!(_rng.NextDouble() * 100.0 > (double)VoiceChance.Value)) { Speak(bot, s); } } } private static void Speak(Bot bot, State s) { Say(bot, s, "idle", force: true); } internal static void GreetOnJoin(Bot bot) { if (!JoinGreet.Value) { return; } Later(2f, delegate { try { if (bot.Alive && _state.TryGetValue(bot, out var value) && VoiceOn.Value) { Say(bot, value, "idle", force: true); } } catch (Exception e) { LogOnce("greet", e); } }); } private static bool Say(Bot bot, State s, string cat, bool force) { if (!VoiceOn.Value) { return false; } float time = Time.time; if (!force && time < s.NextSay) { return false; } AudioClip val = (VoiceWav.Value ? Pick(cat) : null); if ((Object)(object)val != (Object)null) { PlayClip(bot, s, val); s.NextSay = time + SitCooldown.Value; return true; } if (VoiceAvatar.Value && _fallback.TryGetValue(cat, out var value)) { try { bot.LabVoice(value); s.LastLen = 1.2f; s.NextSay = time + SitCooldown.Value; return true; } catch (Exception e) { LogOnce("voice", e); } } return false; } private static float RollPitch() { if (!PitchVary.Value) { return 1f; } float num = Rand(0f - Mathf.Abs(PitchRange.Value), Mathf.Abs(PitchRange.Value)); return Mathf.Pow(2f, num / 12f); } private static void PlayAt(Vector3 pos, AudioClip clip) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) try { GameObject val = new GameObject("DoppelExtras_VoiceAt"); val.transform.position = pos; AudioSource val2 = val.AddComponent<AudioSource>(); val2.spatialBlend = 1f; val2.rolloffMode = (AudioRolloffMode)1; val2.minDistance = 1.5f; val2.maxDistance = 25f; val2.pitch = RollPitch(); val2.PlayOneShot(clip, VoiceVolume.Value); Object.Destroy((Object)(object)val, clip.length / Mathf.Max(0.5f, val2.pitch) + 0.5f); } catch (Exception e) { LogOnce("playat", e); } } private static void PlayClip(Bot bot, State s, AudioClip clip) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown try { Transform head = bot.Head; if (!((Object)(object)head == (Object)null)) { if ((Object)(object)s.Audio == (Object)null) { GameObject val = new GameObject("DoppelExtras_Voice"); val.transform.SetParent(head, false); s.Audio = val.AddComponent<AudioSource>(); s.Audio.spatialBlend = 1f; s.Audio.rolloffMode = (AudioRolloffMode)1; s.Audio.minDistance = 1.5f; s.Audio.maxDistance = 25f; s.Audio.playOnAwake = false; } float num = RollPitch(); s.Audio.pitch = num; s.Audio.PlayOneShot(clip, VoiceVolume.Value); s.LastLen = clip.length / num; if (VoiceNet.Value) { NativeBots.StartVoice(bot, clip, 0f, num); } } } catch (Exception e) { LogOnce("playclip", e); } } private static void Later(float delay, Action a) { _later.Add(new KeyValuePair<float, Action>(Time.time + delay, a)); } private static void RunLater(float now) { for (int num = _later.Count - 1; num >= 0; num--) { if (!(now < _later[num].Key)) { Action value = _later[num].Value; _later.RemoveAt(num); try { value(); } catch (Exception e) { LogOnce("later", e); } } } } private static bool Roll() { return _rng.NextDouble() * 100.0 < (double)SitChance.Value; } private static string GoalName(Bot b) { try { return ((object)Unsafe.As<Goal, Goal>(ref b.goal)/*cast due to .constrained prefix*/).ToString(); } catch (Exception) { return ""; } } private static bool Fighting(Bot b) { string text = GoalName(b); int result; switch (text) { default: result = ((text == "Retreat") ? 1 : 0); break; case "Fight": case "Brawl": case "TakeCover": result = 1; break; } return (byte)result != 0; } private static bool CanSee(Vector3 from, Vector3 to) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) try { RaycastHit val = default(RaycastHit); if (!Physics.Linecast(from, to, ref val, -1, (QueryTriggerInteraction)1)) { return true; } Vector3 val2 = ((RaycastHit)(ref val)).point - to; return ((Vector3)(ref val2)).magnitude < 1.5f; } catch (Exception) { return true; } } private static bool IsEnemy(Bot b) { try { return b.enemy; } catch (Exception) { return false; } } private static void TickSituation(Bot bot, State s, List<Bot> bots, float now) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) Vector3 position; try { position = bot.Head.position; } catch (Exception) { return; } s.WasAlive = true; s.LastPos = position; s.LastEnemy = IsEnemy(bot); float num = (position.y - s.LastY) / 0.25f; bool flag = s.LastY != 0f && s.LastVy < -4.5f && num > -1.5f; s.LastY = position.y; s.LastVy = num; if (!SitOn.Value) { return; } if (flag) { if (Roll()) { Say(bot, s, "fall", force: false); } OnFall(bot, position, bots, now); } if (Fighting(bot) && !s.Fleeing && now >= s.NextTaunt) { s.NextTaunt = now + Rand(10f, 25f); if (Roll()) { Say(bot, s, "taunt", force: false); } } } private static void OnFall(Bot who, Vector3 pos, List<Bot> bots, float now) { //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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_0063: 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_0074: Unknown result type (might be due to invalid IL or missing references) foreach (Bot bot in bots) { if (bot == who || !_state.TryGetValue(bot, out var bs) || !bs.WasAlive) { continue; } Vector3 lastPos = bs.LastPos; Vector3 val = lastPos - pos; if (!(((Vector3)(ref val)).magnitude > 12f) && CanSee(lastPos, pos) && Roll()) { bool friendly = who == null || IsEnemy(bot) == IsEnemy(who); Bot bb = bot; Later(Rand(0.4f, 1.2f), delegate { Say(bb, bs, friendly ? "laugh" : "witness", force: false); }); } } } private static void TickPlayerFall(List<Bot> bots, float now) { //IL_0018: 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) try { if (!((Object)(object)Player.Head == (Object)null)) { float y = Player.Head.position.y; float num = (y - _playerY) / 0.25f; bool flag = _playerY != 0f && _playerVy < -4.5f && num > -1.5f; _playerY = y; _playerVy = num; if (flag && SitOn.Value) { OnFall(null, Player.Head.position, bots, now); } } } catch (Exception) { } } private static void OnDeath(Bot dead, State ds, Vector3 pos, bool deadEnemy, List<Bot> bots, float now) { //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: 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_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_024d: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) if (!SitOn.Value) { return; } if (VoiceOn.Value && VoiceWav.Value) { AudioClip val = Pick("death"); if ((Object)(object)val != (Object)null) { PlayAt(pos, val); } else if (dead != null && VoiceAvatar.Value) { try { dead.LabVoice("effort"); } catch (Exception) { } } } Bot val2 = null; float num = 20f; Vector3 val3; foreach (Bot bot in bots) { if (bot != dead && _state.TryGetValue(bot, out var value) && value.WasAlive && IsEnemy(bot) != deadEnemy) { val3 = value.LastPos - pos; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude < num && Fighting(bot)) { num = magnitude; val2 = bot; } } } if (val2 != null && _state.TryGetValue(val2, out var ks)) { Bot k = val2; if (Roll()) { Later(Rand(0.3f, 0.9f), delegate { Say(k, ks, "kill", force: false); }); } if (Roll() && _rng.Next(100) < 40) { Later(Rand(2f, 4f), delegate { Say(k, ks, "taunt", force: false); }); } } foreach (Bot bot2 in bots) { if (bot2 == dead || bot2 == val2 || !_state.TryGetValue(bot2, out var bs) || !bs.WasAlive) { continue; } Vector3 lastPos = bs.LastPos; val3 = lastPos - pos; float magnitude2 = ((Vector3)(ref val3)).magnitude; if (magnitude2 > 14f || !CanSee(lastPos, pos)) { continue; } Bot bb = bot2; bool flag = val2 != null && IsEnemy(bot2) == IsEnemy(val2); bool flag2 = IsEnemy(bot2) == deadEnemy; if (flag && Fighting(bot2) && Roll() && _rng.Next(100) < 50) { Later(Rand(0.8f, 1.8f), delegate { Say(bb, bs, "assist", force: false); }); } else if (flag2 && Roll() && _rng.Next(100) < 50) { Later(Rand(0.5f, 1.4f), delegate { Say(bb, bs, "panic", force: false); }); } else if (Roll()) { Later(Rand(0.6f, 1.6f), delegate { Say(bb, bs, "witness", force: false); }); } } } private static bool Calm(Bot b, State s) { if (s.Fleeing || s.InConvo != null || !s.WasAlive) { return false; } return !Fighting(b); } private static List<Listener> Listeners() { //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) List<Listener> list = new List<Listener>(); try { if ((Object)(object)Player.Head != (Object)null) { float amp = 0f; try { if (NetworkInfo.HasServer) { amp = VoiceInfo.VoiceAmplitude; } } catch (Exception) { } list.Add(new Listener { Key = -1, Pos = Player.Head.position, Amp = amp }); } } catch (Exception) { } if (!NetworkInfo.HasServer) { return list; } try { IVoiceManager voiceManager = VoiceInfo.VoiceManager; NetworkPlayer[] array = NetworkPlayer.Players.ToArray(); foreach (NetworkPlayer val in array) { try { if (val == null || !val.HasRig || val.PlayerID == null || (val.NetworkEntity != null && val.NetworkEntity.IsOwner) || NativeBots.IsBot(val.PlayerID)) { continue; } float amp2 = 0f; try { IVoiceSpeaker val2 = ((voiceManager != null) ? voiceManager.GetSpeaker(val.PlayerID) : null); if (val2 != null) { amp2 = val2.Amplitude; } } catch (Exception) { } list.Add(new Listener { Key = val.PlayerID.SmallID, Pos = val.RigRefs.Head.position, Amp = amp2 }); } catch (Exception) { } } } catch (Exception e) { LogOnce("listeners", e); } return list; } private static void TickPlayerTalk(List<Bot> bots, float now) { //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: 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_022b: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_02f7: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) if (!PlayerTalk.Value || !VoiceOn.Value) { return; } List<Listener> list = Listeners(); if (list.Count == 0) { return; } float num = Mathf.Max(ConvoRange.Value, 6f); List<Listener> list2 = new List<Listener>(); foreach (Listener item in list) { if (!_talkers.TryGetValue(item.Key, out var value)) { value = new Talker(); _talkers[item.Key] = value; } if (item.Amp > 0.01f) { if (!value.Active) { value.Active = true; value.Start = now; } value.Last = now; } else if (value.Active && now - value.Last > 0.7f) { value.Active = false; if (value.Last - value.Start >= 0.8f) { list2.Add(item); } } } foreach (Bot bot in bots) { if (!_state.TryGetValue(bot, out var value2) || !value2.WasAlive || !Calm(bot, value2) || ((Object)(object)value2.Audio != (Object)null && value2.Audio.isPlaying)) { continue; } Vector3 position; try { position = bot.Head.position; } catch (Exception) { continue; } Vector3 val; if (now >= value2.NextPlayerTalk) { foreach (Listener item2 in list2) { val = item2.Pos - position; if (((Vector3)(ref val)).magnitude > num) { continue; } value2.NextPlayerTalk = now + Rand(10f, 25f); Bot b = bot; State st = value2; Later(Rand(0.6f, 1.6f), delegate { try { if (b.Alive && Calm(b, st) && VoiceOn.Value) { Say(b, st, "convo", force: true); } } catch (Exception e) { LogOnce("talkback", e); } }); break; } } if (!(now >= value2.NextGreet) || !(now >= value2.NextPlayerTalk)) { continue; } foreach (Listener item3 in list) { val = item3.Pos - position; if (((Vector3)(ref val)).magnitude > 3.5f) { continue; } value2.NextGreet = now + Rand(40f, 90f); Bot b2 = bot; State st2 = value2; Wave(b2, 1); Later(1f, delegate { try { if (b2.Alive && Calm(b2, st2) && VoiceOn.Value) { Say(b2, st2, "convo", force: true); } } catch (Exception e) { LogOnce("greetplayer", e); } }); break; } } } private static void TickConversations(List<Bot> bots, float now) { //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) for (int num = _convos.Count - 1; num >= 0; num--) { Convo c = _convos[num]; if (!StepConvo(c, now)) { EndConvo(c, now); _convos.RemoveAt(num); } } if (!ConvoOn.Value || !VoiceOn.Value) { return; } foreach (Bot bot in bots) { if (!_state.TryGetValue(bot, out var value) || !Calm(bot, value) || now < value.NextConvo) { continue; } value.NextConvo = now + Rand(20f, 50f); if (_rng.NextDouble() * 100.0 > (double)ConvoChance.Value) { continue; } float num2 = (ConvoWalk.Value ? 12f : ConvoRange.Value); Bot val = null; float num3 = num2; foreach (Bot bot2 in bots) { if (bot2 != bot && _state.TryGetValue(bot2, out var value2) && Calm(bot2, value2) && IsEnemy(bot2) == IsEnemy(bot)) { Vector3 val2 = value2.LastPos - value.LastPos; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude < num3) { num3 = magnitude; val = bot2; } } } if (val != null) { Convo inConvo = new Convo { A = bot, B = val, Turns = _rng.Next(4, 9), Started = now, Approaching = (num3 > ConvoRange.Value), Next = now }; Convo convo = (value.InConvo = inConvo); _state[val].InConvo = convo; _convos.Add(convo); if (convo.Approaching) { WalkTo(bot, _state[val].LastPos); } } } } private static void WalkTo(Bot bot, Vector3 headPos) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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) //IL_0044: 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_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) if (_fNav == null) { return; } try { object? value = _fNav.GetValue(bot); Navigator val = (Navigator)((value is Navigator) ? value : null); if (val != null) { Vector3 goal = headPos; goal.y -= 1.6f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(headPos, Vector3.down, ref val2, 4f, -1, (QueryTriggerInteraction)1)) { goal = ((RaycastHit)(ref val2)).point; } val.SetGoal(goal); } } catch (Exception e) { LogOnce("walkto", e); } } private static bool StepConvo(Convo c, float now) { //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: 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) if (c.A == null || c.B == null) { return false; } if (!_state.TryGetValue(c.A, out var value) || !_state.TryGetValue(c.B, out var value2)) { return false; } if (!value.WasAlive || !value2.WasAlive || value.Fleeing || value2.Fleeing || Fighting(c.A) || Fighting(c.B)) { return false; } if (now - c.Started > 90f) { return false; } Vector3 val = value.LastPos - value2.LastPos; float magnitude = ((Vector3)(ref val)).magnitude; if (c.Approaching) { if (now - c.Started > 12f) { return false; } if (magnitude > ConvoRange.Value) { return true; } c.Approaching = false; c.Next = now; Wave(c.A, 1); Later(0.8f, delegate { Wave(c.B, 1); }); c.Next = now + 1.8f; return true; } if (magnitude > ConvoRange.Value + 3f) { return false; } if (now < c.Next) { return true; } if (c.Turn >= c.Turns) { return false; } Bot bot = ((c.Turn % 2 == 0) ? c.A : c.B); State state = ((c.Turn % 2 == 0) ? value : value2); c.Turn++; string cat = ((c.Turn > 1 && _rng.Next(100) < 25) ? "laugh" : (_clipsBy.ContainsKey("convo") ? "convo" : "idle")); bool flag = Say(bot, state, cat, force: true); if (!flag) { flag = Say(bot, state, "idle", force: true); } if (!flag) { return false; } c.Next = now + state.LastLen + Rand(0.4f, 1.3f); return true; } private static void EndConvo(Convo c, float now) { if (c.A != null && _state.TryGetValue(c.A, out var value)) { value.InConvo = null; } if (c.B != null && _state.TryGetValue(c.B, out var value2)) { value2.InConvo = null; } if (c.Turn >= c.Turns && c.Turns > 0) { Wave(c.A, 1); } } private static void TickFlee(Bot bot, State s, float now) { //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fc: 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_0067: Invalid comparison between Unknown and I4 //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: 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_0213: 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) //IL_02a1: Invalid comparison between Unknown and I4 //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: 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_0192: 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) if (!FleeOn.Value) { EndFlee(bot, s, force: true); return; } bool flag = false; try { flag = bot.enemy; } catch (Exception) { } if (flag && !FleeEnemies.Value) { EndFlee(bot, s, force: true); return; } bool flag2 = false; try { flag2 = (int)bot.mode == 4; } catch (Exception) { } if (flag2 && !s.Switched && !FleeBrain.Value) { EndFlee(bot, s, force: true); return; } Vector3 position; try { position = bot.Head.position; } catch (Exception) { return; } float num = s.Height * Mathf.Max(1.01f, FleeRatio.Value); float value = FleeRange.Value; float num2 = float.MaxValue; Entity? entity = null; foreach (Entity entity2 in _entities) { if (entity2.Bot != bot && !((Object)(object)entity2.Head == (Object)null) && (!entity2.IsPlayer || FleePlayer.Value) && (entity2.IsPlayer || FleeBots.Value) && !(entity2.Height < num)) { Vector3 val = entity2.Head.position - position; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= value && magnitude < num2) { num2 = magnitude; entity = entity2; } } } if (entity.HasValue) { Entity value2 = entity.Value; s.LastThreat = now; s.ThreatPos = value2.Head.position; s.ThreatName = value2.Name; if (!s.Fleeing) { s.Fleeing = true; s.Shouted = false; if (FleeShout.Value && VoiceOn.Value) { Say(bot, s, "panic", force: true); s.Shouted = true; } } if (FleeSwitchMode.Value && !s.Switched) { try { if ((int)bot.mode != 4) { s.PrevMode = bot.mode; s.Switched = true; bot.SetMode((Mode)4); } } catch (Exception) { } } if (now >= s.NextPush) { s.NextPush = now + 2f; PushAway(bot, s, position, value2.Head.position); } } else if (s.Fleeing && now - s.LastThreat > 4f) { EndFlee(bot, s, force: false); } } private static void Wave(Bot b, int n) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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) //IL_0054: Invalid comparison between Unknown and I4 if (b == null) { return; } Mode prev; try { prev = b.mode; } catch (Exception) { return; } try { b.LabWave(n); } catch (Exception) { return; } if ((int)prev == 0) { return; } Later(0.35f + (float)n * 0.7f + 0.4f, delegate { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 //IL_002b: Unknown result type (might be due to invalid IL or missing references) try { if (b.Alive && (int)b.mode == 0) { b.SetMode(prev); } } catch (Exception) { } }); } private static void EndFlee(Bot bot, State s, bool force) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Invalid comparison between Unknown and I4 //IL_0099: Unknown result type (might be due to invalid IL or missing references) if (!s.Fleeing && !s.Switched) { return; } bool fleeing = s.Fleeing; s.Fleeing = false; if (fleeing && force && _fNav != null) { try { object? value = _fNav.GetValue(bot); object? obj = ((value is Navigator) ? value : null); if (obj != null) { ((Navigator)obj).Clear(); } } catch (Exception) { } } if (!s.Switched) { return; } s.Switched = false; try { if (bot.Alive && (int)bot.mode == 4) { bot.SetMode(s.PrevMode); } } catch (Exception) { } } private static void PushAway(Bot bot, State s, Vector3 here, Vector3 threat) { //IL_0037: 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_0043: 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_004d: 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) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_0088: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: 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_00ae: Unknown result type (might be due to invalid IL or missing references) if (_fNav == null) { return; } try { object? value = _fNav.GetValue(bot); Navigator val = (Navigator)((value is Navigator) ? value : null); if (val == null) { return; } Vector3 val2 = here - Vector3.up * s.Height; Vector3 goal = Vector3.zero; float num = -1f; bool flag = false; for (int i = 0; i < 8; i++) { Vector3 zero = Vector3.zero; if (Navigator.RandomPlace(val2, 7f, 16f, ref zero)) { Vector3 val3 = zero - threat; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude > num) { num = magnitude; goal = zero; flag = true; } } } if (flag) { val.SetGoal(goal); } } catch (Exception e) { LogOnce("push", e); } } private static void TickClimb(Bot bot, State s, float now) { //IL_004a: 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_005a: 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_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_0070: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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) //IL_0138: 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_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) if (!ClimbOn.Value || _mClimb == null || now < s.NextClimb || s.Fleeing) { return; } Vector3 position; try { position = bot.Head.position; } catch (Exception) { return; } Vector3 val = position - Vector3.up * s.Height; float num = Tuning.F("climb.min", 1.2f); float num2 = Tuning.F("climb.max", 2.5f); float value = ClimbReach.Value; foreach (Entity entity in _entities) { if (entity.Bot == bot || (Object)(object)entity.Head == (Object)null || (entity.IsPlayer && !ClimbOnPlayer.Value) || (!entity.IsPlayer && !ClimbOnBots.Value)) { continue; } Vector3 val2 = entity.Head.position - position; val2.y = 0f; if (((Vector3)(ref val2)).magnitude > value) { continue; } float num3 = entity.Head.position.y - val.y; if (num3 < num || num3 > num2 + 0.5f) { continue; } s.NextClimb = now + ClimbCooldown.Value; try { _mClimb.Invoke(bot, new object[1] { ((Vector3)(ref val2)).normalized }); break; } catch (Exception e) { LogOnce("climb", e); break; } } } private static void ScanSpawnPoints() { _spawnScanned = true; _spawnPoints.Clear(); try { List<Transform> list = new List<Transform>(); List<Transform> list2 = new List<Transform>(); foreach (Transform item in Object.FindObjectsOfType<Transform>()) { if ((Object)(object)item == (Object)null) { continue; } string n = ((Object)item).name.ToLowerInvariant(); if ((n.Contains("spawn") || n.Contains("playerstart")) && !_reject.Any((string r) => n.Contains(r) && !n.Contains("player"))) { if (n.Contains("player") || n.Contains("playerstart")) { list.Add(item); } else { list2.Add(item); } } } _spawnPoints.AddRange((list.Count > 0) ? list : list2); MelonLogger.Msg("[DoppelExtras] Spawn points: " + _spawnPoints.Count + ((_spawnPoints.Count > 0) ? (" (e.g. " + string.Join(", ", from x in _spawnPoints.Take(4) select ((Object)x).name) + ")") : " - will fall back to your position")); } catch (Exception ex) { MelonLogger.Warning("[DoppelExtras] spawn scan: " + ex.Message); } } private static Vector3 PickSpawn(out Vector3 forward) { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: 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_0093: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0128: 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_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: 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_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_014d: 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) //IL_018c: Unknown result type (might be due to invalid IL or missing references) if (!_spawnScanned) { ScanSpawnPoints(); } Transform val = null; for (int i = 0; i < 8; i++) { if (!((Object)(object)val == (Object)null)) { break; } if (_spawnPoints.Count <= 0) { break; } Transform val2 = _spawnPoints[_rng.Next(_spawnPoints.Count)]; if ((Object)(object)val2 != (Object)null) { val = val2; } } Vector3 val3; if ((Object)(object)val != (Object)null) { val3 = val.position; forward = Vector3.ProjectOnPlane(val.forward, Vector3.up); } else { val3 = (((Object)(object)Player.Head != (Object)null) ? (Player.Head.position + Player.Head.forward * 2f) : Vector3.zero); forward = Vector3.forward; } Vector2 val4 = new Vector2((float)_rng.NextDouble() - 0.5f, (float)_rng.NextDouble() - 0.5f) * 2.5f; val3 += new Vector3(val4.x, 0f, val4.y); if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forwar