using System; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Unity.Netcode; using UnityEngine; [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: Guid("D181CDA7-EF07-4BBC-B975-2B80FC6BBFAE")] [assembly: ComVisible(false)] [assembly: AssemblyTrademark("")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyProduct("GnomeRider")] [assembly: AssemblyCompany("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyDescription("")] [assembly: AssemblyTitle("GnomeRider")] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: CompilationRelaxations(8)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] 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 NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace GnomeRider { internal static class DogControl { private static bool _resolved; private static Type _tDog; private static Type _tAI; private static Type _tServer; private static Type _tStealable; private static Type _tPlayerNet; private static Type _tListener; private static FieldInfo _fFollower; private static FieldInfo _fFsm; private static PropertyInfo _pTarget; private static PropertyInfo _pCategory; private static PropertyInfo _pActor; private static PropertyInfo _pPlayerCenter; private static PropertyInfo _pPlayerPosition; private static bool _playerPosLogged; private static MethodInfo _mSetOverrides; private static MethodInfo _mSetUsable; private static MethodInfo _mSetPosition; private static MethodInfo _mSetRotation; private static PropertyInfo _pCaPosition; private static PropertyInfo _pCaVelocity; private static PropertyInfo _pCaForward; private static bool _actorResolved; private static MethodInfo _mSetDestination; private static Type[] _setDestParamTypes; private static PropertyInfo _pIsStopped; private static PropertyInfo _pStopDistance; private static bool _followerResolved; private static bool _seatLogged; private static bool _bonesDumped; private static readonly List<(Collider a, Collider b)> _ignored = new List<(Collider, Collider)>(); private static Type _tMecanim; private static PropertyInfo _pPuppet; private static float _savedKnockout = -1f; private static float _savedPin = -1f; private static bool _agentToggleLogged; private static bool _wakeLogged; private static bool _animDumped; private static bool _audioDumped; private static bool _quietLogged; private static Animator _locoAnim; private static bool _hasX; private static bool _hasY; private static bool _hasMag; private static bool _locoLogged; private static bool _dumpedOnce; private static PropertyInfo[] _followerProbe; public static Type DogType { get { Resolve(); return _tDog; } } public static Type AIType { get { Resolve(); return _tAI; } } public static Type StealableType { get { Resolve(); return _tStealable; } } public static bool InSession => (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsListening; public static bool IsServer => (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer; public static bool Resolve() { if (_resolved) { return _tAI != null; } _resolved = true; _tDog = AccessTools.TypeByName("Dog"); _tAI = AccessTools.TypeByName("GameEntityAI"); _tServer = AccessTools.TypeByName("ServerManager"); _tStealable = AccessTools.TypeByName("StealableObject"); _tPlayerNet = AccessTools.TypeByName("PlayerNetworking"); if (_tAI != null) { _fFollower = AccessTools.Field(_tAI, "followerEntity"); _fFsm = AccessTools.Field(_tAI, "fsm"); _pTarget = AccessTools.Property(_tAI, "TargetedEntityInVision"); _mSetPosition = AccessTools.Method(_tAI, "SetPosition", new Type[1] { typeof(Vector3) }, (Type[])null); _mSetRotation = AccessTools.Method(_tAI, "SetRotation", new Type[1] { typeof(Quaternion) }, (Type[])null); } if (_tStealable != null) { _pCategory = AccessTools.Property(_tStealable, "Category"); } if (_tPlayerNet != null) { _pActor = AccessTools.Property(_tPlayerNet, "Actor"); _pPlayerCenter = AccessTools.Property(_tPlayerNet, "Center"); _pPlayerPosition = AccessTools.Property(_tPlayerNet, "Position"); } _tListener = AccessTools.TypeByName("PlayerInteractListener"); if (_tListener != null) { MethodInfo[] methods = _tListener.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name == "SetInteractOverrides" && methodInfo.GetParameters().Length == 3) { _mSetOverrides = methodInfo; break; } } _mSetUsable = AccessTools.Method(_tListener, "SetUsable", new Type[1] { typeof(bool) }, (Type[])null); } Plugin.Log.LogInfo((object)($"GnomeRider resolve: Dog={_tDog != null}, GameEntityAI={_tAI != null}, " + $"followerEntity={_fFollower != null}, fsm={_fFsm != null}, target={_pTarget != null}, " + $"StealableObject={_tStealable != null}, Category={_pCategory != null}, " + $"Listener={_tListener != null}, SetOverrides={_mSetOverrides != null}, Actor={_pActor != null}")); if (_tAI == null || _fFollower == null || _pTarget == null) { Plugin.Log.LogWarning((object)"GnomeRider: core dog members missing; taming disabled."); } if (_tStealable == null || _pCategory == null) { Plugin.Log.LogWarning((object)"GnomeRider: StealableObject.Category missing; toy detection disabled."); } return _tAI != null; } public static bool IsTameItem(Component stealable) { if ((Object)(object)stealable == (Object)null || _pCategory == null) { return false; } try { object value = _pCategory.GetValue(stealable); int num = Convert.ToInt32(value); return (num & Plugin.TameCategoryMask.Value) != 0; } catch { return false; } } public static Component LocalPlayerComponent() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.SpawnManager == null || _tPlayerNet == null) { return null; } foreach (NetworkObject spawnedObjects in singleton.SpawnManager.SpawnedObjectsList) { if (!((Object)(object)spawnedObjects == (Object)null) && spawnedObjects.IsPlayerObject && spawnedObjects.IsLocalPlayer) { Component componentInChildren = ((Component)spawnedObjects).GetComponentInChildren(_tPlayerNet); if ((Object)(object)componentInChildren != (Object)null) { return componentInChildren; } } } return null; } public static Vector3 PlayerPos(Component player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_000c: 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_0178: 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_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_0075: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: 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_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } string text = "transform"; Vector3 val = player.transform.position; try { if (_pPlayerCenter != null && _pPlayerCenter.GetValue(player) is Vector3 val2 && ((Vector3)(ref val2)).sqrMagnitude > 0.01f) { val = val2; text = "Center"; } if (text == "transform" && _pPlayerPosition != null && _pPlayerPosition.GetValue(player) is Vector3 val3 && ((Vector3)(ref val3)).sqrMagnitude > 0.01f) { val = val3; text = "Position"; } if (text == "transform" && _pActor != null) { object? value = _pActor.GetValue(player); Component val4 = (Component)((value is Component) ? value : null); if ((Object)(object)val4 != (Object)null) { val = val4.transform.position; text = "Actor.transform"; } } } catch { } if (!_playerPosLogged) { _playerPosLogged = true; Plugin.Log.LogInfo((object)$"GnomeRider: player position read via {text} -> {val}"); } return val; } public static Vector3? NearestPlayerPos(Vector3 from) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_011e: 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_00b1: 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_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.SpawnManager == null || _tPlayerNet == null) { return null; } Vector3 value = Vector3.zero; float num = float.MaxValue; bool flag = false; foreach (NetworkObject spawnedObjects in singleton.SpawnManager.SpawnedObjectsList) { if ((Object)(object)spawnedObjects == (Object)null || !spawnedObjects.IsPlayerObject) { continue; } Component componentInChildren = ((Component)spawnedObjects).GetComponentInChildren(_tPlayerNet); if ((Object)(object)componentInChildren == (Object)null) { continue; } Vector3 val = PlayerPos(componentInChildren); if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { Vector3 val2 = val - from; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; value = val; flag = true; } } } return flag ? new Vector3?(value) : ((Vector3?)null); } public static void MoveDog(Component ai, Vector3 newPos, Vector3 forward) { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: 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) if ((Object)(object)ai == (Object)null) { return; } try { if (_mSetPosition != null) { _mSetPosition.Invoke(ai, new object[1] { newPos }); } else { ai.transform.position = newPos; } if (((Vector3)(ref forward)).sqrMagnitude > 0.001f) { Quaternion val = Quaternion.LookRotation(forward, Vector3.up); if (_mSetRotation != null) { _mSetRotation.Invoke(ai, new object[1] { val }); } else { ai.transform.rotation = val; } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider move failed: " + ex.Message)); } } public static float CalculateSeatHeight(Component ai) { //IL_001d: 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_0042: 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) //IL_00bf: 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_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_00f3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ai == (Object)null) { return 1f; } Vector3 position = ai.transform.position; float num = 1f; try { SkinnedMeshRenderer[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(false); bool flag = false; Bounds val = default(Bounds); SkinnedMeshRenderer[] array = componentsInChildren; foreach (SkinnedMeshRenderer val2 in array) { if (!((Object)(object)val2 == (Object)null)) { if (!flag) { val = ((Renderer)val2).bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(((Renderer)val2).bounds); } } } if (flag) { num = Mathf.Max(0.25f, (((Bounds)(ref val)).max.y - position.y) * 0.85f); if (!_seatLogged) { _seatLogged = true; Plugin.Log.LogInfo((object)($"GnomeRider seat: body bounds size={((Bounds)(ref val)).size}, " + $"fixed seat height={num:0.00}m above dog root.")); } } } catch { } return num; } public static Vector3 SeatPosition(Component ai, float seatHeight, float extraHeight) { //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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_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_000c: 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_003e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ai == (Object)null) { return Vector3.zero; } Vector3 position = ai.transform.position; return new Vector3(position.x, position.y + seatHeight + extraHeight, position.z); } public static Transform FindSeatBone(Component ai, string nameContains) { //IL_0132: 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_013d: 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_0151: 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) if ((Object)(object)ai == (Object)null) { return null; } try { Transform root = ai.transform.root; Transform transform = ai.transform; string text = (nameContains ?? "").Trim(); Transform val = null; Transform val2 = null; if (!_bonesDumped) { _bonesDumped = true; Plugin.Log.LogInfo((object)"[bones] skinned bones (fwd = along dog forward, up = above dog origin):"); SkinnedMeshRenderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val3 in componentsInChildren) { if ((Object)(object)val3 == (Object)null || val3.bones == null) { continue; } Transform[] bones = val3.bones; foreach (Transform val4 in bones) { if (!((Object)(object)val4 == (Object)null)) { string text2 = ((Object)val4).name.ToLowerInvariant(); if (text2.Contains("spine") || text2.Contains("neck") || text2.Contains("chest") || text2.Contains("hip") || text2.Contains("pelvis")) { float num = Vector3.Dot(val4.position - transform.position, transform.forward); float num2 = val4.position.y - transform.position.y; Plugin.Log.LogInfo((object)$"[bones] '{((Object)val4).name}' fwd={num:0.00} up={num2:0.00}"); } } } } } Transform[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (Transform val5 in componentsInChildren2) { if (!((Object)(object)val5 == (Object)null) && text.Length != 0) { if (string.Equals(((Object)val5).name, text, StringComparison.OrdinalIgnoreCase)) { val = val5; break; } if ((Object)(object)val2 == (Object)null && ((Object)val5).name.ToLowerInvariant().Contains(text.ToLowerInvariant())) { val2 = val5; } } } Transform val6 = val ?? val2; Plugin.Log.LogInfo((object)(((Object)(object)val6 != (Object)null) ? ("GnomeRider seat bone: '" + ((Object)val6).name + "' (" + (((Object)(object)val != (Object)null) ? "exact" : "partial") + " match for '" + text + "')") : ("GnomeRider seat bone: nothing matched '" + text + "', using dog root."))); return val6; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider seat bone failed: " + ex.Message)); return null; } } public static Vector3 SeatPositionFromBone(Transform bone, Transform dogT, float up, float forward) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_000c: 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_003b: 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_0033: 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_0046: 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) if ((Object)(object)bone == (Object)null) { return Vector3.zero; } return bone.position + Vector3.up * up + (((Object)(object)dogT != (Object)null) ? (dogT.forward * forward) : Vector3.zero); } public static void SetRiderCollision(object playerObj, Component ai, bool ignore) { Component val = (Component)((playerObj is Component) ? playerObj : null); if ((Object)(object)val == (Object)null || (Object)(object)ai == (Object)null) { return; } try { if (ignore) { RestoreRiderCollision(); Collider[] componentsInChildren = ((Component)val.transform.root).GetComponentsInChildren(true); Collider[] componentsInChildren2 = ((Component)ai.transform.root).GetComponentsInChildren(true); int num = 0; Collider[] array = componentsInChildren; foreach (Collider val2 in array) { if ((Object)(object)val2 == (Object)null || val2.isTrigger) { continue; } Collider[] array2 = componentsInChildren2; foreach (Collider val3 in array2) { if (!((Object)(object)val3 == (Object)null) && !val3.isTrigger) { Physics.IgnoreCollision(val2, val3, true); _ignored.Add((val2, val3)); num++; } } } Plugin.Log.LogInfo((object)$"GnomeRider: ignoring {num} rider/dog collider pairs while mounted."); } else { RestoreRiderCollision(); } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider collision toggle failed: " + ex.Message)); } } private static void RestoreRiderCollision() { foreach (var item in _ignored) { if (!((Object)(object)item.a == (Object)null) && !((Object)(object)item.b == (Object)null)) { try { Physics.IgnoreCollision(item.a, item.b, false); } catch { } } } _ignored.Clear(); } public static void SetMecanimEnabled(Component ai, bool enabled) { if ((Object)(object)ai == (Object)null) { return; } try { if ((object)_tMecanim == null) { _tMecanim = AccessTools.TypeByName("CatMecanim"); } if (_tMecanim == null) { return; } Component[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(_tMecanim, true); foreach (Component val in componentsInChildren) { Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null); if ((Object)(object)val2 != (Object)null && val2.enabled != enabled) { val2.enabled = enabled; Plugin.Log.LogInfo((object)("GnomeRider: CatMecanim " + (enabled ? "re-enabled" : "disabled for riding") + " on '" + ((Object)((Component)val2).gameObject).name + "'.")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider mecanim toggle failed: " + ex.Message)); } } public static void SetRiderPuppetHeld(object playerObj, bool held) { Component val = (Component)((playerObj is Component) ? playerObj : null); if ((Object)(object)val == (Object)null || _tPlayerNet == null) { return; } try { if ((object)_pPuppet == null) { _pPuppet = AccessTools.Property(_tPlayerNet, "Puppet"); } object obj = _pPuppet?.GetValue(val); if (obj == null) { return; } Type type = obj.GetType(); FieldInfo field = type.GetField("knockOutDistance", BindingFlags.Instance | BindingFlags.Public); if (field != null) { if (held) { if (_savedKnockout < 0f) { _savedKnockout = Convert.ToSingle(field.GetValue(obj)); } field.SetValue(obj, 999f); } else if (_savedKnockout >= 0f) { field.SetValue(obj, _savedKnockout); _savedKnockout = -1f; } } object obj2 = type.GetField("puppetMaster", BindingFlags.Instance | BindingFlags.Public)?.GetValue(obj); if (obj2 != null) { FieldInfo field2 = obj2.GetType().GetField("pinWeight", BindingFlags.Instance | BindingFlags.Public); if (field2 != null) { if (held) { if (_savedPin < 0f) { _savedPin = Convert.ToSingle(field2.GetValue(obj2)); } field2.SetValue(obj2, 1f); } else if (_savedPin >= 0f) { field2.SetValue(obj2, _savedPin); _savedPin = -1f; } } } Plugin.Log.LogInfo((object)string.Format("GnomeRider: rider puppet {0} (knockOut={1}, pin={2}).", held ? "held" : "released", field != null, obj2 != null)); } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider puppet hold failed: " + ex.Message)); } } public static void DumpSitRig() { //IL_00d1: Unknown result type (might be due to invalid IL or missing references) try { Component val = LocalPlayerComponent(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)"[sit] no local player."); return; } Animator[] componentsInChildren = ((Component)val.transform.root).GetComponentsInChildren(true); foreach (Animator val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.runtimeAnimatorController == (Object)null) { continue; } Plugin.Log.LogInfo((object)$"[sit] player animator '{((Object)((Component)val2).gameObject).name}' controller='{((Object)val2.runtimeAnimatorController).name}' params={val2.parameters.Length}"); AnimatorControllerParameter[] parameters = val2.parameters; foreach (AnimatorControllerParameter val3 in parameters) { Plugin.Log.LogInfo((object)$"[sit] param {val3.type} {val3.name}"); } AnimationClip[] animationClips = val2.runtimeAnimatorController.animationClips; if (animationClips == null) { continue; } int num = 0; AnimationClip[] array = animationClips; foreach (AnimationClip val4 in array) { if (!((Object)(object)val4 == (Object)null)) { string text = ((Object)val4).name.ToLowerInvariant(); if (text.Contains("sit") || text.Contains("ride") || text.Contains("mount") || text.Contains("drive") || text.Contains("chair")) { Plugin.Log.LogInfo((object)("[sit] clip '" + ((Object)val4).name + "'")); num++; } } } Plugin.Log.LogInfo((object)$"[sit] {animationClips.Length} clips total, {num} sit/ride-ish."); } Component[] componentsInChildren2 = ((Component)val.transform.root).GetComponentsInChildren(true); foreach (Component val5 in componentsInChildren2) { if (!((Object)(object)val5 == (Object)null) && ((object)val5).GetType().Name == "InteractionSystem") { Plugin.Log.LogInfo((object)("[sit] player has InteractionSystem on '" + ((Object)val5.gameObject).name + "'")); break; } } Type type = AccessTools.TypeByName("PlayerSittable"); if (type == null) { Plugin.Log.LogInfo((object)"[sit] PlayerSittable type not found."); return; } Object[] array2 = Object.FindObjectsOfType(type); Plugin.Log.LogInfo((object)$"[sit] PlayerSittable instances in scene: {((array2 != null) ? array2.Length : 0)}"); if (array2 == null) { return; } FieldInfo fieldInfo = AccessTools.Field(type, "effectors"); Object[] array3 = array2; foreach (Object val6 in array3) { Component val7 = (Component)(object)((val6 is Component) ? val6 : null); if ((Object)(object)val7 == (Object)null) { continue; } Plugin.Log.LogInfo((object)("[sit] '" + ((Object)val7.gameObject).name + "' (" + ((object)val7).GetType().Name + ")")); if (fieldInfo?.GetValue(val7) is Array array4) { foreach (object item in array4) { Plugin.Log.LogInfo((object)$"[sit] effector: {item}"); } } Component[] componentsInChildren3 = val7.GetComponentsInChildren(true); foreach (Component val8 in componentsInChildren3) { if (!((Object)(object)val8 == (Object)null)) { string name = ((object)val8).GetType().Name; if (name == "InteractionObject" || name == "InteractionTarget") { Plugin.Log.LogInfo((object)("[sit] " + name + " on '" + ((Object)val8.gameObject).name + "'")); } } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider sit dump failed: " + ex.Message)); } } public static void SetAgentEnabled(Component ai, bool enabled) { if ((Object)(object)ai == (Object)null || _fFollower == null) { return; } try { object? value = _fFollower.GetValue(ai); Behaviour val = (Behaviour)((value is Behaviour) ? value : null); if (!((Object)(object)val == (Object)null) && val.enabled != enabled) { val.enabled = enabled; if (!_agentToggleLogged) { _agentToggleLogged = true; Plugin.Log.LogInfo((object)"GnomeRider: navmesh agent toggles off during jumps (it was flattening them)."); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider agent toggle failed: " + ex.Message)); } } public static void MoveDogRaw(Component ai, Vector3 pos) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ai == (Object)null) { return; } try { ai.transform.position = pos; } catch { } } public static void WakeDog(Component ai) { //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Invalid comparison between Unknown and I4 if ((Object)(object)ai == (Object)null) { return; } try { Animator[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(true); foreach (Animator val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)val.runtimeAnimatorController == (Object)null) { continue; } AnimatorControllerParameter[] parameters = val.parameters; foreach (AnimatorControllerParameter val2 in parameters) { if ((int)val2.type == 4 && val2.name == "Sleep") { if (val.GetBool("Sleep")) { val.SetBool("Sleep", false); Plugin.Log.LogInfo((object)"GnomeRider: dog was asleep - waking him up."); } else if (!_wakeLogged) { _wakeLogged = true; Plugin.Log.LogInfo((object)"GnomeRider: dog already awake (Sleep=false)."); } } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider wake failed: " + ex.Message)); } } public static void TriggerJump(Component ai) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Invalid comparison between Unknown and I4 if ((Object)(object)_locoAnim == (Object)null) { SetLocomotion(ai, 0f, 0f, 0f); } if ((Object)(object)_locoAnim == (Object)null) { return; } try { AnimatorControllerParameter[] parameters = _locoAnim.parameters; foreach (AnimatorControllerParameter val in parameters) { if ((int)val.type == 9 && val.name == "Jump") { _locoAnim.SetTrigger("Jump"); break; } } } catch { } } public static void TurnDog(Component ai, Vector3 forward, float degPerSec) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ai == (Object)null || ((Vector3)(ref forward)).sqrMagnitude < 0.001f) { return; } try { Quaternion val = Quaternion.LookRotation(forward, Vector3.up); Quaternion val2 = Quaternion.RotateTowards(ai.transform.rotation, val, degPerSec * Time.deltaTime); if (_mSetRotation != null) { _mSetRotation.Invoke(ai, new object[1] { val2 }); } else { ai.transform.rotation = val2; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider turn failed: " + ex.Message)); } } public static void LogRootMotion(Component ai) { if ((Object)(object)ai == (Object)null) { return; } try { Animator[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(true); foreach (Animator val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.runtimeAnimatorController == (Object)null)) { Plugin.Log.LogInfo((object)$"GnomeRider: animator '{((Object)((Component)val).gameObject).name}' applyRootMotion={val.applyRootMotion}, speed={val.speed}"); } } } catch { } } public static void DumpAnimatorParams(Component ai) { //IL_00ba: 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) if ((Object)(object)ai == (Object)null || _animDumped) { return; } _animDumped = true; try { Animator[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(true); Animator[] array = componentsInChildren; foreach (Animator val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.runtimeAnimatorController == (Object)null)) { Plugin.Log.LogInfo((object)$"[anim] animator on '{((Object)((Component)val).gameObject).name}' params={val.parameters.Length}"); AnimatorControllerParameter[] parameters = val.parameters; foreach (AnimatorControllerParameter val2 in parameters) { Plugin.Log.LogInfo((object)$"[anim] {val2.type} {val2.name}"); } for (int k = 0; k < val.layerCount; k++) { AnimatorStateInfo currentAnimatorStateInfo = val.GetCurrentAnimatorStateInfo(k); Plugin.Log.LogInfo((object)$"[anim] layer{k} '{val.GetLayerName(k)}' stateHash={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).fullPathHash} len={((AnimatorStateInfo)(ref currentAnimatorStateInfo)).length:0.00}"); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider anim dump failed: " + ex.Message)); } } public static void SilenceDog(Component ai) { //IL_0229: 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) if ((Object)(object)ai == (Object)null) { return; } try { Transform root = ai.transform.root; Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null || ((object)val).GetType().Name != "MMF_Player") { continue; } MethodInfo method = ((object)val).GetType().GetMethod("StopFeedbacks", Type.EmptyTypes); if (!(method != null)) { continue; } try { method.Invoke(val, null); if (!_audioDumped) { Plugin.Log.LogInfo((object)("[quiet] stopped feedbacks on '" + ((Object)val.gameObject).name + "'")); } } catch { } } AudioSource[] componentsInChildren2 = ((Component)root).GetComponentsInChildren(true); foreach (AudioSource val2 in componentsInChildren2) { if (!((Object)(object)val2 == (Object)null)) { if (!_audioDumped) { Plugin.Log.LogInfo((object)("[quiet] dog audio '" + ((Object)((Component)val2).gameObject).name + "' clip='" + (((Object)(object)val2.clip != (Object)null) ? ((Object)val2.clip).name : "null") + "' " + $"playing={val2.isPlaying} loop={val2.loop}")); } if (val2.isPlaying) { val2.Stop(); } } } if (_audioDumped) { return; } _audioDumped = true; AudioSource[] array = Object.FindObjectsOfType(); foreach (AudioSource val3 in array) { if (!((Object)(object)val3 == (Object)null) && val3.isPlaying) { float num = Vector3.Distance(((Component)val3).transform.position, root.position); if (!(num > 12f)) { Plugin.Log.LogInfo((object)($"[audio] near dog ({num:0.0}m): '{((Object)((Component)val3).gameObject).name}' " + string.Format("clip='{0}' loop={1}", ((Object)(object)val3.clip != (Object)null) ? ((Object)val3.clip).name : "null", val3.loop))); } } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider silence failed: " + ex.Message)); } } public static void QuietDog(Component ai) { //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_014b: Invalid comparison between Unknown and I4 //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Invalid comparison between Unknown and I4 //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Invalid comparison between Unknown and I4 if ((Object)(object)ai == (Object)null) { return; } SilenceDog(ai); try { Animator[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(true); Animator[] array = componentsInChildren; foreach (Animator val in array) { if ((Object)(object)val == (Object)null || (Object)(object)val.runtimeAnimatorController == (Object)null) { continue; } AnimatorControllerParameter[] parameters = val.parameters; foreach (AnimatorControllerParameter val2 in parameters) { string name = val2.name; string text = name.ToLowerInvariant(); bool flag = text.Contains("growl") || text.Contains("aggr") || text.Contains("angry") || text.Contains("attack") || text.Contains("bark") || text.Contains("bite") || text.Contains("alert") || text.Contains("chase") || text.Contains("run"); bool flag2 = text.Contains("speed") || text.Contains("velocity") || text.Contains("move"); try { AnimatorControllerParameterType type = val2.type; AnimatorControllerParameterType val3 = type; if ((int)val3 != 1) { if ((int)val3 != 4) { if ((int)val3 == 9 && flag) { val.ResetTrigger(name); LogQuiet("resetTrigger " + name); } } else if (flag) { val.SetBool(name, false); LogQuiet("bool " + name + "=false"); } } else if (flag2) { val.SetFloat(name, 0f); LogQuiet("float " + name + "=0"); } } catch { } } } _quietLogged = true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider quiet failed: " + ex.Message)); } } private static void LogQuiet(string what) { if (!_quietLogged) { Plugin.Log.LogInfo((object)("[quiet] " + what)); } } public static void SetLocomotion(Component ai, float strafe, float forward, float magnitude) { //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Invalid comparison between Unknown and I4 if ((Object)(object)ai == (Object)null) { return; } try { if ((Object)(object)_locoAnim == (Object)null) { Animator[] componentsInChildren = ((Component)ai.transform.root).GetComponentsInChildren(true); foreach (Animator val in componentsInChildren) { if ((Object)(object)val == (Object)null || (Object)(object)val.runtimeAnimatorController == (Object)null) { continue; } AnimatorControllerParameter[] parameters = val.parameters; foreach (AnimatorControllerParameter val2 in parameters) { if ((int)val2.type == 1) { if (val2.name == "X") { _hasX = true; } else if (val2.name == "Y") { _hasY = true; } else if (val2.name == "InputMagnitude") { _hasMag = true; } } } if (_hasX || _hasY || _hasMag) { _locoAnim = val; break; } } if (!_locoLogged) { _locoLogged = true; Plugin.Log.LogInfo((object)$"GnomeRider locomotion anim: found={(Object)(object)_locoAnim != (Object)null}, X={_hasX}, Y={_hasY}, InputMagnitude={_hasMag}"); } } if (!((Object)(object)_locoAnim == (Object)null)) { if (_hasX) { _locoAnim.SetFloat("X", strafe); } if (_hasY) { _locoAnim.SetFloat("Y", forward); } if (_hasMag) { _locoAnim.SetFloat("InputMagnitude", magnitude); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider locomotion failed: " + ex.Message)); } } public static Component TamedDogInRange(float range) { //IL_001d: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) Component val = LocalPlayerComponent(); if ((Object)(object)val == (Object)null) { return null; } Vector3 val2 = PlayerPos(val); float num = range * range; Component result = null; foreach (Component item in Plugin.TamedRegistry) { if (!((Object)(object)item == (Object)null)) { Vector3 val3 = item.transform.position - val2; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude <= num) { num = sqrMagnitude; result = item; } } } return result; } public static void SetTarget(Component ai, Component entity) { if ((Object)(object)ai == (Object)null || _pTarget == null || !_pTarget.CanWrite) { return; } try { _pTarget.SetValue(ai, entity); } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider set-target failed: " + ex.Message)); } } public static void ClearTarget(Component ai) { if ((Object)(object)ai == (Object)null || _pTarget == null || !_pTarget.CanWrite) { return; } try { _pTarget.SetValue(ai, null); } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider clear-target failed: " + ex.Message)); } } public static void PauseBrain(Component ai, bool paused) { if ((Object)(object)ai == (Object)null || _fFsm == null) { return; } try { object? value = _fFsm.GetValue(ai); Behaviour val = (Behaviour)((value is Behaviour) ? value : null); if ((Object)(object)val != (Object)null) { val.enabled = !paused; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider pause-brain failed: " + ex.Message)); } } private static object GetFollower(Component ai) { if ((Object)(object)ai == (Object)null || _fFollower == null) { return null; } try { object value = _fFollower.GetValue(ai); if (value == null) { return null; } if (!_followerResolved) { _followerResolved = true; Type type = value.GetType(); MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "SetDestination") && (_mSetDestination == null || methodInfo.GetParameters().Length > _mSetDestination.GetParameters().Length)) { _mSetDestination = methodInfo; } } if (_mSetDestination != null) { ParameterInfo[] parameters = _mSetDestination.GetParameters(); _setDestParamTypes = new Type[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { _setDestParamTypes[j] = parameters[j].ParameterType; } } _pIsStopped = type.GetProperty("isStopped", BindingFlags.Instance | BindingFlags.Public); _pStopDistance = type.GetProperty("stopDistance", BindingFlags.Instance | BindingFlags.Public); string text = ((_setDestParamTypes != null) ? string.Join(",", Array.ConvertAll(_setDestParamTypes, (Type t) => t.Name)) : "none"); Plugin.Log.LogInfo((object)("GnomeRider follower: SetDestination(" + text + "), " + $"isStopped={_pIsStopped != null}, stopDistance={_pStopDistance != null}")); if (_mSetDestination == null) { Plugin.Log.LogWarning((object)"GnomeRider: FollowerEntity.SetDestination not found; steering unavailable."); } } return value; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider follower access failed: " + ex.Message)); return null; } } private static object ToParam(Vector3 v, Type paramType) { //IL_0015: 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_0053: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (paramType == typeof(Vector3)) { return v; } try { ConstructorInfo constructor = paramType.GetConstructor(new Type[1] { typeof(Vector3) }); if (constructor != null) { return constructor.Invoke(new object[1] { v }); } ConstructorInfo constructor2 = paramType.GetConstructor(new Type[3] { typeof(float), typeof(float), typeof(float) }); if (constructor2 != null) { return constructor2.Invoke(new object[3] { v.x, v.y, v.z }); } } catch { } return v; } public static void SteerTo(Component ai, Vector3 dest, float stopDistance) { //IL_009f: 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) object follower = GetFollower(ai); if (follower == null || _mSetDestination == null || _setDestParamTypes == null) { return; } try { if (_pStopDistance != null && _pStopDistance.CanWrite) { _pStopDistance.SetValue(follower, stopDistance); } if (_pIsStopped != null && _pIsStopped.CanWrite) { _pIsStopped.SetValue(follower, false); } object[] array = new object[_setDestParamTypes.Length]; array[0] = ToParam(dest, _setDestParamTypes[0]); for (int i = 1; i < array.Length; i++) { array[i] = ToParam(Vector3.zero, _setDestParamTypes[i]); } _mSetDestination.Invoke(follower, array); } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider steer failed: " + ex.Message)); } } public static bool WireRideInteract(Component ai, Action onRide) { if (!Resolve() || _tListener == null || _mSetOverrides == null || _tPlayerNet == null) { return false; } Component componentInParent = ai.GetComponentInParent(_tDog); Component val = (Component)(((Object)(object)componentInParent != (Object)null) ? ((object)componentInParent) : ((object)ai)); Component val2 = null; Component[] componentsInChildren = ((Component)val.transform.root).GetComponentsInChildren(_tListener, true); if (componentsInChildren != null && componentsInChildren.Length != 0) { val2 = componentsInChildren[0]; } if ((Object)(object)val2 == (Object)null) { Plugin.Log.LogWarning((object)"GnomeRider: dog has no PlayerInteractListener; can't show a ride prompt. Falling back to auto-follow only."); DumpHierarchy(ai); return false; } try { RideHandler firstArgument = new RideHandler { dog = ai, cb = onRide }; Type type = typeof(Action<>).MakeGenericType(_tPlayerNet); MethodInfo method = typeof(RideHandler).GetMethod("OnRide"); Delegate obj = Delegate.CreateDelegate(type, firstArgument, method); _mSetOverrides.Invoke(val2, new object[3] { obj, null, null }); _mSetUsable?.Invoke(val2, new object[1] { true }); Plugin.Log.LogInfo((object)"GnomeRider: ride prompt wired onto dog's interact listener."); return true; } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider: failed to wire ride interact: " + ex.Message)); return false; } } public static void DumpHierarchy(Component ai) { if (!((Object)(object)ai == (Object)null) && !_dumpedOnce) { _dumpedOnce = true; DumpHierarchyForced(ai); } } public static void DumpHierarchyForced(Component ai) { if ((Object)(object)ai == (Object)null) { return; } try { Transform root = ai.transform.root; Plugin.Log.LogInfo((object)("[dump] dog root='" + ((Object)root).name + "' ai='" + ((Object)ai.gameObject).name + "' " + $"activeInHierarchy={ai.gameObject.activeInHierarchy} layer={LayerMask.LayerToName(ai.gameObject.layer)}")); Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); HashSet hashSet = new HashSet(); Component[] array = componentsInChildren; foreach (Component val in array) { if ((Object)(object)val == (Object)null) { continue; } string name = ((object)val).GetType().Name; switch (name) { case "Transform": case "MeshFilter": case "MeshRenderer": case "SkinnedMeshRenderer": case "BoxCollider": case "SphereCollider": case "CapsuleCollider": case "MeshCollider": case "Rigidbody": case "ConfigurableJoint": continue; } if (!(name == "CharacterJoint") && hashSet.Add(name)) { Plugin.Log.LogInfo((object)("[dump] component: " + name + " (on '" + ((Object)val.gameObject).name + "')")); } } if (!(_tListener != null)) { return; } Object[] array2 = Object.FindObjectsOfType(_tListener); Plugin.Log.LogInfo((object)$"[dump] PlayerInteractListener instances in scene: {((array2 != null) ? array2.Length : 0)}"); if (array2 != null && array2.Length != 0) { Object obj = array2[0]; Component val2 = (Component)(object)((obj is Component) ? obj : null); if ((Object)(object)val2 != (Object)null) { Plugin.Log.LogInfo((object)("[dump] example listener on '" + ((Object)val2.transform.root).name + "/" + ((Object)val2.gameObject).name + "'")); } } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider dump failed: " + ex.Message)); } } public static void LogAgentState(Component ai, string tag) { object follower = GetFollower(ai); if (follower == null) { Plugin.Log.LogInfo((object)("[state:" + tag + "] no FollowerEntity")); return; } try { if (_followerProbe == null) { string[] array = new string[10] { "position", "destination", "isStopped", "canMove", "velocity", "reachedDestination", "reachedEndOfPath", "hasPath", "pathPending", "maxSpeed" }; List list = new List(); Type type = follower.GetType(); string[] array2 = array; foreach (string name in array2) { PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public); if (property != null && property.CanRead) { list.Add(property); } } _followerProbe = list.ToArray(); Plugin.Log.LogInfo((object)$"[state] readable agent props: {list.Count}"); } StringBuilder stringBuilder = new StringBuilder("[state:" + tag + "] "); PropertyInfo[] followerProbe = _followerProbe; foreach (PropertyInfo propertyInfo in followerProbe) { object obj = null; try { obj = propertyInfo.GetValue(follower); } catch { } stringBuilder.Append(propertyInfo.Name).Append('=').Append((obj == null) ? "null" : obj.ToString()) .Append(" "); } if (_fFsm != null) { object? value = _fFsm.GetValue(ai); Behaviour val = (Behaviour)((value is Behaviour) ? value : null); stringBuilder.Append("fsmEnabled=").Append(((Object)(object)val != (Object)null) ? val.enabled.ToString() : "null"); } Plugin.Log.LogInfo((object)stringBuilder.ToString()); } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider state log failed: " + ex.Message)); } } public static Component NearestDogAI(Vector3 from) { //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_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) if (!Resolve() || _tDog == null || _tAI == null) { return null; } Component result = null; float num = float.MaxValue; Object[] array = Object.FindObjectsOfType(_tDog); foreach (Object val in array) { Component val2 = (Component)(object)((val is Component) ? val : null); if ((Object)(object)val2 == (Object)null) { continue; } Component component = val2.GetComponent(_tAI); if (!((Object)(object)component == (Object)null)) { Vector3 val3 = val2.transform.position - from; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; result = component; } } } return result; } public static void PinPlayer(object playerObj, Vector3 seatPos, Vector3 forward) { //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) Component val = (Component)((playerObj is Component) ? playerObj : null); if ((Object)(object)val == (Object)null) { return; } object obj = null; if (_pActor != null) { try { obj = _pActor.GetValue(val); } catch { } } if (obj != null) { if (!_actorResolved) { _actorResolved = true; Type type = obj.GetType(); _pCaPosition = type.GetProperty("Position", BindingFlags.Instance | BindingFlags.Public); _pCaVelocity = type.GetProperty("Velocity", BindingFlags.Instance | BindingFlags.Public); _pCaForward = type.GetProperty("Forward", BindingFlags.Instance | BindingFlags.Public); Plugin.Log.LogInfo((object)$"GnomeRider actor: Position={_pCaPosition != null}, Velocity={_pCaVelocity != null}, Forward={_pCaForward != null}"); } try { if (_pCaVelocity != null && _pCaVelocity.CanWrite) { _pCaVelocity.SetValue(obj, Vector3.zero); } if (_pCaPosition != null && _pCaPosition.CanWrite) { _pCaPosition.SetValue(obj, seatPos); } if (forward != Vector3.zero && _pCaForward != null && _pCaForward.CanWrite) { _pCaForward.SetValue(obj, forward); } if (_pCaPosition != null) { return; } } catch (Exception ex) { Plugin.Log.LogWarning((object)("GnomeRider pin (actor) failed: " + ex.Message)); } } val.transform.position = seatPos; } } internal class RideHandler { public Component dog; public Action cb; public void OnRide(object player) { cb?.Invoke(dog, player); } } [DefaultExecutionOrder(10000)] public class RideController : MonoBehaviour { private float _nextScan; private readonly Collider[] _overlap = (Collider[])(object)new Collider[8]; private readonly List _prune = new List(); private Component _riddenDog; private object _rider; private float _nextState; private float _riddenSeatHeight; private Transform _seatBone; private float _jumpVel; private float _groundY; private bool _airborne; private void Update() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_0088: 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_0025: 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) KeyboardShortcut value = Plugin.DumpKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { Vector3 val = (((Object)(object)Camera.main != (Object)null) ? ((Component)Camera.main).transform.position : Vector3.zero); Component val2 = DogControl.NearestDogAI(val); if ((Object)(object)val2 != (Object)null) { DogControl.DumpHierarchyForced(val2); DogControl.LogAgentState(val2, "manual"); } else { Plugin.Log.LogInfo((object)"[dump] no dog found in scene."); } DogControl.DumpSitRig(); } value = Plugin.MountKey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ToggleMountNearest(); } if (!DogControl.IsServer || Time.time < _nextScan) { return; } _nextScan = Time.time + 0.15f; ScanForToyTames(); FollowStep(); if (!Plugin.Verbose.Value || !(Time.time >= _nextState) || Plugin.TamedRegistry.Count <= 0) { return; } _nextState = Time.time + 2f; foreach (Component item in Plugin.TamedRegistry) { if ((Object)(object)item != (Object)null) { DogControl.LogAgentState(item, ((Object)(object)item == (Object)(object)_riddenDog) ? "ridden" : "follow"); break; } } } private void LateUpdate() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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 (DogControl.IsServer) { RideSteer(); } if (!((Object)(object)_riddenDog == (Object)null) && _rider != null && !((Object)(object)_riddenDog == (Object)null)) { Vector3 seatPos = (((Object)(object)_seatBone != (Object)null) ? DogControl.SeatPositionFromBone(_seatBone, _riddenDog.transform, Plugin.RideHeight.Value, Plugin.SeatForward.Value) : DogControl.SeatPosition(_riddenDog, _riddenSeatHeight, Plugin.RideHeight.Value)); DogControl.PinPlayer(_rider, seatPos, _riddenDog.transform.forward); NudgeRideCamera(); } } private void NudgeRideCamera() { //IL_0058: 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_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_006f: 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_0079: Unknown result type (might be due to invalid IL or missing references) float value = Plugin.RideCameraForward.Value; float value2 = Plugin.RideCameraUp.Value; if (!Mathf.Approximately(value, 0f) || !Mathf.Approximately(value2, 0f)) { Camera main = Camera.main; if (!((Object)(object)main == (Object)null)) { Transform transform = ((Component)main).transform; transform.position += transform.forward * value + Vector3.up * value2; } } } private void OnGUI() { //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00b5: 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_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) if (Plugin.ShowMountHint.Value) { string text = null; KeyboardShortcut value; if ((Object)(object)_riddenDog != (Object)null) { value = Plugin.MountKey.Value; text = $"[{((KeyboardShortcut)(ref value)).MainKey}] dismount [WASD] steer"; } else if ((Object)(object)DogControl.TamedDogInRange(Plugin.MountRange.Value) != (Object)null) { value = Plugin.MountKey.Value; text = $"Press [{((KeyboardShortcut)(ref value)).MainKey}] to ride"; } if (text != null) { GUIStyle val = new GUIStyle(GUI.skin.label) { fontSize = 18, fontStyle = (FontStyle)1, alignment = (TextAnchor)4 }; val.normal.textColor = Color.white; GUIStyle val2 = val; Rect val3 = default(Rect); ((Rect)(ref val3))..ctor(0f, (float)Screen.height * 0.62f, (float)Screen.width, 28f); GUI.color = new Color(0f, 0f, 0f, 0.6f); GUI.Label(new Rect(((Rect)(ref val3)).x + 1f, ((Rect)(ref val3)).y + 1f, ((Rect)(ref val3)).width, ((Rect)(ref val3)).height), text, val2); GUI.color = Color.white; GUI.Label(val3, text, val2); } } } private void ToggleMountNearest() { //IL_006e: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_00c7: Unknown result type (might be due to invalid IL or missing references) if (!DogControl.IsServer) { Plugin.Log.LogInfo((object)"GnomeRider: riding is host/solo only for now."); return; } if ((Object)(object)_riddenDog != (Object)null) { Dismount(); return; } Component val = DogControl.LocalPlayerComponent(); if ((Object)(object)val == (Object)null) { Plugin.Log.LogInfo((object)"GnomeRider: no local player found."); return; } Vector3 val2 = DogControl.PlayerPos(val); Component val3 = null; float num = Plugin.MountRange.Value * Plugin.MountRange.Value; foreach (Component item in Plugin.TamedRegistry) { if (!((Object)(object)item == (Object)null)) { Vector3 val4 = item.transform.position - val2; float sqrMagnitude = ((Vector3)(ref val4)).sqrMagnitude; if (sqrMagnitude <= num) { num = sqrMagnitude; val3 = item; } } } if ((Object)(object)val3 == (Object)null) { Plugin.Log.LogInfo((object)$"GnomeRider: no tamed dog within {Plugin.MountRange.Value}m (tamed: {Plugin.TamedRegistry.Count})."); return; } _riddenDog = val3; _rider = val; _riddenSeatHeight = DogControl.CalculateSeatHeight(val3); _seatBone = DogControl.FindSeatBone(val3, Plugin.SeatBoneName.Value); DogControl.SetTarget(val3, null); DogControl.QuietDog(val3); DogControl.SetMecanimEnabled(val3, enabled: false); DogControl.WakeDog(val3); DogControl.SetLocomotion(val3, 0f, 0f, 0f); DogControl.SetRiderCollision(val, val3, ignore: true); DogControl.SetRiderPuppetHeld(val, held: true); if (Plugin.Verbose.Value) { DogControl.LogRootMotion(val3); } if (Plugin.Verbose.Value) { DogControl.DumpAnimatorParams(val3); } Plugin.Log.LogInfo((object)$"GnomeRider: mounted a dog. Seat height={_riddenSeatHeight:0.00}m."); } private void OnRideInteract(Component dogAi, object player) { if ((Object)(object)_riddenDog == (Object)(object)dogAi) { Dismount(); return; } if ((Object)(object)_riddenDog != (Object)null) { Dismount(); } _riddenDog = dogAi; _rider = player; _riddenSeatHeight = DogControl.CalculateSeatHeight(dogAi); _seatBone = DogControl.FindSeatBone(dogAi, Plugin.SeatBoneName.Value); DogControl.SetTarget(dogAi, null); DogControl.QuietDog(dogAi); DogControl.SetMecanimEnabled(dogAi, enabled: false); DogControl.WakeDog(dogAi); DogControl.SetLocomotion(dogAi, 0f, 0f, 0f); DogControl.SetRiderCollision(player, dogAi, ignore: true); DogControl.SetRiderPuppetHeld(player, held: true); Plugin.Log.LogInfo((object)$"GnomeRider: mounted a dog. Seat height={_riddenSeatHeight:0.00}m."); } private void Dismount() { if (!((Object)(object)_riddenDog == (Object)null)) { DogControl.SetLocomotion(_riddenDog, 0f, 0f, 0f); DogControl.SetRiderPuppetHeld(_rider, held: false); DogControl.SetRiderCollision(_rider, _riddenDog, ignore: false); DogControl.SetMecanimEnabled(_riddenDog, enabled: true); if (Plugin.RidePausesBrain.Value && !Plugin.TameStay.Value) { DogControl.PauseBrain(_riddenDog, paused: false); } _seatBone = null; if (_airborne) { DogControl.SetAgentEnabled(_riddenDog, enabled: true); } _airborne = false; _jumpVel = 0f; Plugin.Log.LogInfo((object)"GnomeRider: dismounted."); _riddenDog = null; _rider = null; _riddenSeatHeight = 0f; } } private void RideSteer() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_02b8: 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_02bf: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: 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) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0206: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: Unknown result type (might be due to invalid IL or missing references) //IL_02dd: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02f9: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0309: Unknown result type (might be due to invalid IL or missing references) //IL_030e: Unknown result type (might be due to invalid IL or missing references) //IL_0313: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0227: 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_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_0344: Unknown result type (might be due to invalid IL or missing references) //IL_035d: 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_040d: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_riddenDog == (Object)null) { return; } DogControl.SetTarget(_riddenDog, null); if (Plugin.RidePausesBrain.Value) { DogControl.PauseBrain(_riddenDog, paused: true); } KeyboardShortcut value; if (!_airborne) { value = Plugin.JumpKey.Value; if (Input.GetKeyDown(((KeyboardShortcut)(ref value)).MainKey)) { DogControl.TriggerJump(_riddenDog); _groundY = _riddenDog.transform.position.y; _jumpVel = Plugin.JumpForce.Value; _airborne = true; DogControl.SetAgentEnabled(_riddenDog, enabled: false); } } float num = 0f; float num2 = 0f; if (Input.GetKey((KeyCode)119) || Input.GetKey((KeyCode)273)) { num2 += 1f; } if (Input.GetKey((KeyCode)115) || Input.GetKey((KeyCode)274)) { num2 -= 1f; } if (Input.GetKey((KeyCode)100) || Input.GetKey((KeyCode)275)) { num += 1f; } if (Input.GetKey((KeyCode)97) || Input.GetKey((KeyCode)276)) { num -= 1f; } value = Plugin.SprintKey.Value; float num3 = (((KeyboardShortcut)(ref value)).IsPressed() ? Plugin.SprintMultiplier.Value : 1f); bool flag = Mathf.Abs(num) >= 0.1f || Mathf.Abs(num2) >= 0.1f; Vector3 forward = Vector3.zero; if (flag) { Camera main = Camera.main; Vector3 val = (((Object)(object)main != (Object)null) ? ((Component)main).transform.forward : _riddenDog.transform.forward); Vector3 val2 = (((Object)(object)main != (Object)null) ? ((Component)main).transform.right : _riddenDog.transform.right); val.y = 0f; val2.y = 0f; forward = ((Vector3)(ref val)).normalized * num2 + ((Vector3)(ref val2)).normalized * num; if (((Vector3)(ref forward)).sqrMagnitude > 0.001f) { ((Vector3)(ref forward)).Normalize(); DogControl.TurnDog(_riddenDog, forward, Plugin.TurnSpeed.Value); } DogControl.SetLocomotion(_riddenDog, 0f, num3, num3); } else { DogControl.SetLocomotion(_riddenDog, 0f, 0f, 0f); } Vector3 position = _riddenDog.transform.position; Vector3 val3 = position; if (flag && !Plugin.UseRootMotion.Value) { val3 += _riddenDog.transform.forward * Plugin.RideSpeed.Value * num3 * Time.deltaTime; } if (_airborne) { _jumpVel -= Plugin.JumpGravity.Value * Time.deltaTime; val3.y = position.y + _jumpVel * Time.deltaTime; if (val3.y <= _groundY && _jumpVel < 0f) { val3.y = _groundY; _airborne = false; _jumpVel = 0f; DogControl.MoveDogRaw(_riddenDog, val3); DogControl.SetAgentEnabled(_riddenDog, enabled: true); DogControl.MoveDog(_riddenDog, val3, _riddenDog.transform.forward); } else { DogControl.MoveDogRaw(_riddenDog, val3); } } else if (flag && !Plugin.UseRootMotion.Value) { DogControl.MoveDog(_riddenDog, val3, _riddenDog.transform.forward); } } private void ScanForToyTames() { //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) Type dogType = DogControl.DogType; Type aIType = DogControl.AIType; Type stealableType = DogControl.StealableType; if (dogType == null || aIType == null || stealableType == null) { return; } Object[] array = Object.FindObjectsOfType(dogType); foreach (Object val in array) { Component val2 = (Component)(object)((val is Component) ? val : null); if ((Object)(object)val2 == (Object)null) { continue; } Component component = val2.GetComponent(aIType); if ((Object)(object)component == (Object)null || Plugin.TamedRegistry.Contains(component)) { continue; } Vector3 val3 = val2.transform.position + Vector3.up * 0.3f; int num = Physics.OverlapSphereNonAlloc(val3, Plugin.ToyTouchRadius.Value, _overlap); for (int j = 0; j < num; j++) { Collider val4 = _overlap[j]; if (!((Object)(object)val4 == (Object)null)) { Component val5 = (((Object)(object)val4.attachedRigidbody != (Object)null) ? ((Component)val4.attachedRigidbody).GetComponent(stealableType) : null) ?? ((Component)val4).GetComponentInParent(stealableType); if ((Object)(object)val5 != (Object)null && DogControl.IsTameItem(val5)) { Tame(component); break; } } } } } private void Tame(Component ai) { Plugin.Log.LogInfo((object)"GnomeRider: a dog was tamed by a toy!"); if (Plugin.PauseBrainOnTame.Value) { DogControl.PauseBrain(ai, paused: true); } DogControl.ClearTarget(ai); Plugin.TamedRegistry.Add(ai); if (Plugin.Verbose.Value) { DogControl.DumpAnimatorParams(ai); } if (Plugin.TameStay.Value) { DogControl.WakeDog(ai); DogControl.PauseBrain(ai, paused: true); DogControl.QuietDog(ai); } else { DogControl.WakeDog(ai); } if (Plugin.Verbose.Value) { DogControl.DumpHierarchy(ai); DogControl.LogAgentState(ai, "on-tame"); } DogControl.WireRideInteract(ai, OnRideInteract); } private void FollowStep() { //IL_00f6: 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) if (Plugin.TamedRegistry.Count == 0) { return; } _prune.Clear(); foreach (Component item in Plugin.TamedRegistry) { if ((Object)(object)item == (Object)null) { _prune.Add(item); } else { if ((Object)(object)item == (Object)(object)_riddenDog) { continue; } if (Plugin.TameStay.Value) { DogControl.ClearTarget(item); DogControl.QuietDog(item); continue; } if (!Plugin.FollowEnabled.Value) { DogControl.ClearTarget(item); continue; } if (Plugin.FollowViaTarget.Value) { Component val = DogControl.LocalPlayerComponent(); if ((Object)(object)val != (Object)null) { DogControl.SetTarget(item, val); } continue; } DogControl.ClearTarget(item); Vector3? val2 = DogControl.NearestPlayerPos(item.transform.position); if (val2.HasValue) { DogControl.SteerTo(item, val2.Value, Mathf.Max(0f, Plugin.FollowStopDistance.Value)); } } } for (int i = 0; i < _prune.Count; i++) { Plugin.TamedRegistry.Remove(_prune[i]); } } } [BepInPlugin("com.odinplus.gnomerider", "GnomeRider", "1.0.0")] public class Plugin : BaseUnityPlugin { public static Plugin Instance; public static ManualLogSource Log; public static readonly HashSet TamedRegistry = new HashSet(); public static ConfigEntry TameStay; public static ConfigEntry FollowEnabled; public static ConfigEntry FollowStopDistance; public static ConfigEntry ToyTouchRadius; public static ConfigEntry TameCategoryMask; public static ConfigEntry MountKey; public static ConfigEntry MountRange; public static ConfigEntry RideHeight; public static ConfigEntry RideLookAhead; public static ConfigEntry RideSpeed; public static ConfigEntry RidePausesBrain; public static ConfigEntry ShowMountHint; public static ConfigEntry SeatBoneName; public static ConfigEntry SeatForward; public static ConfigEntry UseRootMotion; public static ConfigEntry TurnSpeed; public static ConfigEntry JumpKey; public static ConfigEntry SprintKey; public static ConfigEntry SprintMultiplier; public static ConfigEntry JumpForce; public static ConfigEntry JumpGravity; public static ConfigEntry RideCameraForward; public static ConfigEntry RideCameraUp; public static ConfigEntry Verbose; public static ConfigEntry DumpKey; public static ConfigEntry PauseBrainOnTame; public static ConfigEntry FollowViaTarget; private void Awake() { //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Expected O, but got Unknown //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_023f: 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) //IL_0393: Unknown result type (might be due to invalid IL or missing references) //IL_03ec: Unknown result type (might be due to invalid IL or missing references) //IL_03f2: Expected O, but got Unknown //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0404: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; TameStay = ((BaseUnityPlugin)this).Config.Bind("Tame", "StayAfterTame", true, "A tamed dog settles down and stays put instead of following you around."); FollowEnabled = ((BaseUnityPlugin)this).Config.Bind("Tame", "FollowPlayer", false, "A tamed dog paths toward the nearest player. Ignored when StayAfterTame is on."); FollowStopDistance = ((BaseUnityPlugin)this).Config.Bind("Tame", "FollowStopDistance", 3f, "A tamed dog aims for a point this far from the player so it doesn't trample them."); ToyTouchRadius = ((BaseUnityPlugin)this).Config.Bind("Tame", "ToyTouchRadius", 1.5f, "How close a toy must get to a dog to tame it (metres)."); TameCategoryMask = ((BaseUnityPlugin)this).Config.Bind("Tame", "ItemCategoryMask", 4, new ConfigDescription("Which item categories tame a dog, as a bitmask. Default 4 = Toy. Values: Food=1, Canned_Food=2, Toy=4, Weapon=8, Utensil=16, Drink=256. Add them together to widen, or use -1 for any categorised item.", (AcceptableValueBase)null, Array.Empty())); MountKey = ((BaseUnityPlugin)this).Config.Bind("Ride", "MountKey", new KeyboardShortcut((KeyCode)103, Array.Empty()), "Mount / dismount the nearest tamed dog (host/solo)."); MountRange = ((BaseUnityPlugin)this).Config.Bind("Ride", "MountRange", 4f, "How close you must be to a tamed dog to mount it."); RideHeight = ((BaseUnityPlugin)this).Config.Bind("Ride", "SeatHeight", -0.05f, "Extra vertical offset after the auto seat height (metres). Negative values lower the rider into the dog's back. Default -0.25."); RideSpeed = ((BaseUnityPlugin)this).Config.Bind("Ride", "RideSpeed", 12f, "How fast the dog moves while you're steering it (metres/sec)."); RidePausesBrain = ((BaseUnityPlugin)this).Config.Bind("Ride", "PauseBrainWhileRiding", true, "Pause the dog's normal AI while mounted so it does not fight rider control. Rider movement and locomotion animation are controlled separately."); ShowMountHint = ((BaseUnityPlugin)this).Config.Bind("Ride", "ShowMountHint", true, "Show an on-screen prompt when you're near a tamed dog (dogs have no built-in interact prompt, so this stands in for one)."); SeatBoneName = ((BaseUnityPlugin)this).Config.Bind("Ride", "SeatBoneName", "Spine_02", "Bone name (substring) the rider is anchored to. The rig has bones like 'Spine_base'. Blank or unmatched falls back to the dog root."); SeatForward = ((BaseUnityPlugin)this).Config.Bind("Ride", "SeatForward", 1f, "Shift the rider forward (+) or back (-) along the dog, in metres."); UseRootMotion = ((BaseUnityPlugin)this).Config.Bind("Ride", "UseRootMotion", false, "Move the dog with its own run animation (root motion) instead of sliding it. This also disables CatMecanim while riding so it can't overwrite the animator parameters we set. Turn off to fall back to direct position drive."); TurnSpeed = ((BaseUnityPlugin)this).Config.Bind("Ride", "TurnSpeed", 180f, "How fast the dog turns toward your steering direction (degrees/sec)."); JumpKey = ((BaseUnityPlugin)this).Config.Bind("Ride", "JumpKey", new KeyboardShortcut((KeyCode)32, Array.Empty()), "Make the dog jump while riding (uses its own Jump animation trigger)."); SprintKey = ((BaseUnityPlugin)this).Config.Bind("Ride", "SprintKey", new KeyboardShortcut((KeyCode)304, Array.Empty()), "Hold to make the dog run faster."); RideCameraForward = ((BaseUnityPlugin)this).Config.Bind("Ride", "CameraForward", 0.35f, "Push the first-person camera forward while riding, in metres. Moves only the camera - the gnome stays put - so his body stops clipping into view. Raise it if you still see yourself; 0 disables."); RideCameraUp = ((BaseUnityPlugin)this).Config.Bind("Ride", "CameraUp", 0f, "Raise (+) or lower (-) the camera while riding, in metres."); JumpForce = ((BaseUnityPlugin)this).Config.Bind("Ride", "JumpForce", 9f, "Upward speed when the dog jumps (metres/sec). Higher = bigger hop."); JumpGravity = ((BaseUnityPlugin)this).Config.Bind("Ride", "JumpGravity", 20f, "How fast the dog falls back down after a jump."); SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind("Ride", "SprintMultiplier", 1.8f, "Speed multiplier while the sprint key is held."); RideLookAhead = ((BaseUnityPlugin)this).Config.Bind("Ride", "SteerLookAhead", 5f, "How far ahead of the dog your input steers it."); Verbose = ((BaseUnityPlugin)this).Config.Bind("Debug", "VerboseLogging", false, "Log dog/agent state while tamed."); DumpKey = ((BaseUnityPlugin)this).Config.Bind("Debug", "DumpKey", new KeyboardShortcut((KeyCode)290, Array.Empty()), "Dump the nearest dog's components and agent state to the log."); PauseBrainOnTame = ((BaseUnityPlugin)this).Config.Bind("Debug", "PauseBrainOnTame", false, "Disable the dog's FSM when tamed. Leave false to keep normal dog animation and behaviour."); FollowViaTarget = ((BaseUnityPlugin)this).Config.Bind("Debug", "FollowViaTarget", true, "Follow by pointing the dog's own AI target at you, letting its brain do the pathing and animation. Bite behaviour is patched out."); Harmony h = new Harmony("com.odinplus.gnomerider"); Patches.Apply(h); GameObject val = new GameObject("GnomeRiderManager"); val.AddComponent(); Object.DontDestroyOnLoad((Object)(object)val); Log.LogInfo((object)"GnomeRider 1.2.3 loaded."); } } internal static class Patches { private static Type _tAI; public static void Apply(Harmony h) { //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Expected O, but got Unknown Type type = AccessTools.TypeByName("Dog"); MethodInfo methodInfo = ((type != null) ? AccessTools.Method(type, "FixedUpdate", (Type[])null, (Type[])null) : null); if (methodInfo == null) { Plugin.Log.LogWarning((object)"GnomeRider: Dog.FixedUpdate not found; bite suppression unavailable."); return; } h.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(Patches).GetMethod("DogFixedUpdatePrefix", BindingFlags.Static | BindingFlags.NonPublic)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Plugin.Log.LogInfo((object)"GnomeRider: patched Dog.FixedUpdate (bite suppression while tamed)."); } private static bool DogFixedUpdatePrefix(object __instance) { if (Plugin.TamedRegistry.Count == 0) { return true; } Component val = (Component)((__instance is Component) ? __instance : null); if ((Object)(object)val == (Object)null) { return true; } if ((object)_tAI == null) { _tAI = AccessTools.TypeByName("GameEntityAI"); } if (_tAI == null) { return true; } Component component = val.GetComponent(_tAI); if ((Object)(object)component != (Object)null && Plugin.TamedRegistry.Contains(component)) { return false; } return true; } } }