Decompiled source of RockyPet v0.1.28

Pix.RockyPet.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using UnityEngine;
using UnityEngine.Rendering;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace Pix.RockyPet;

[BepInPlugin("Pix.RockyPet", "RockyPet", "0.1.28")]
public sealed class RockyPetPlugin : BaseUnityPlugin
{
	[Serializable]
	[CompilerGenerated]
	private sealed class <>c
	{
		public static readonly <>c <>9 = new <>c();

		public static ConsoleEvent <>9__34_0;

		internal void <TryRegisterTerminalCommands>b__34_0(ConsoleEventArgs args)
		{
			if (!Enabled)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			string text = null;
			if (args != null && args.Length > 1)
			{
				text = string.Join(" ", args.Args, 1, args.Length - 1)?.Trim();
				if (string.IsNullOrEmpty(text))
				{
					text = null;
				}
			}
			RockyPetBehaviour rockyPetBehaviour = RockyPetBehaviour.FindHoveredOrNearestOwned(localPlayer, 14f);
			if ((Object)(object)rockyPetBehaviour == (Object)null)
			{
				if ((Object)(object)MessageHud.instance != (Object)null)
				{
					MessageHud.instance.ShowMessage((MessageType)1, "No Rocky found (look at Rocky or stand closer).", 0, (Sprite)null, false);
				}
			}
			else
			{
				rockyPetBehaviour.ForceSpeakNow(text);
			}
		}
	}

	public const string PluginGuid = "Pix.RockyPet";

	public const string PluginName = "RockyPet";

	public const string PluginVersion = "0.1.28";

	internal static ConfigEntry<bool> CfgEnabled;

	internal static ConfigEntry<string> CfgTargetPrefab;

	internal static ConfigEntry<KeyCode> CfgToggleKey;

	internal static ConfigEntry<float> CfgFollowDistance;

	internal static ConfigEntry<float> CfgFollowSideOffset;

	internal static ConfigEntry<float> CfgCatchupTeleportDistance;

	internal static ConfigEntry<float> CfgStartFollowRadius;

	internal static ConfigEntry<float> CfgStopFollowRadius;

	internal static ConfigEntry<float> CfgMaxMoveSpeed;

	internal static ConfigEntry<float> CfgWalkMaxMoveSpeed;

	internal static ConfigEntry<float> CfgMoveSmoothTime;

	internal static ConfigEntry<float> CfgRunMoveSpeedMultiplier;

	internal static ConfigEntry<float> CfgRunSmoothTimeMultiplier;

	internal static ConfigEntry<float> CfgFreezeWithinMeters;

	internal static ConfigEntry<float> CfgStopDeadzone;

	internal static ConfigEntry<float> CfgGroundRayStartUp;

	internal static ConfigEntry<float> CfgGroundRayDown;

	internal static ConfigEntry<float> CfgGroundMinNormalY;

	internal static ConfigEntry<float> CfgRunLiftMeters;

	internal static ConfigEntry<float> CfgTurnSpeed;

	internal static ConfigEntry<float> CfgFrontRollOffsetDegrees;

	internal static ConfigEntry<float> CfgWalkHopHeightMeters;

	internal static ConfigEntry<float> CfgWalkHopHz;

	internal static ConfigEntry<float> CfgWalkHopForwardNudgeMeters;

	internal static ConfigEntry<bool> CfgRockyQuotesEnabled;

	internal static ConfigEntry<float> CfgQuoteBubbleSeconds;

	internal static ConfigEntry<float> CfgQuoteBubbleUpMeters;

	internal static ConfigEntry<float> CfgQuoteWorldTextSize;

	internal static ConfigEntry<int> CfgQuoteWrapChars;

	private Harmony _harmony;

	internal static bool Enabled => CfgEnabled != null && CfgEnabled.Value;

	private void Awake()
	{
		//IL_040d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0417: Expected O, but got Unknown
		CfgEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable/disable RockyPet.");
		CfgTargetPrefab = ((BaseUnityPlugin)this).Config.Bind<string>("General", "TargetPrefab", "Placeable_HardRock", "Prefab name to attach RockyPet behaviour to.");
		CfgToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleFollowKey", (KeyCode)114, "Key to toggle follow/stay while hovering Rocky.");
		CfgFollowDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "FollowDistance", 2.6f, "Nominal distance behind player while following.");
		CfgFollowSideOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "FollowSideOffset", 0.45f, "Side offset while following.");
		CfgCatchupTeleportDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "CatchupTeleportDistance", 20f, "Teleport to player if farther than this while following.");
		CfgStartFollowRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "StartFollowRadius", 3f, "If Rocky is farther than this from his follow slot, he starts moving.");
		CfgStopFollowRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "StopFollowRadius", 1.6f, "If Rocky gets within this of his follow slot, he stops moving.");
		CfgMaxMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "MaxMoveSpeed", 5.2f, "Maximum movement speed (used for run-roll / general).");
		CfgWalkMaxMoveSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "WalkMaxMoveSpeed", 3f, "Maximum movement speed while walking (not rolling).");
		CfgMoveSmoothTime = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "MoveSmoothTime", 0.25f, "SmoothDamp time (lower = snappier, higher = more lag).");
		CfgRunMoveSpeedMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "RunMoveSpeedMultiplier", 1.65f, "Multiply MaxMoveSpeed while player is running (roll mode).");
		CfgRunSmoothTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "RunSmoothTimeMultiplier", 0.6f, "Multiply MoveSmoothTime while running (lower = quicker response).");
		CfgFreezeWithinMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Follow", "FreezeWithinMeters", 3f, "If Rocky is within this distance of the owner, he won't readjust to the follow slot.");
		CfgStopDeadzone = ((BaseUnityPlugin)this).Config.Bind<float>("Stability", "StopDeadzone", 0.06f, "If within this distance of target, snap hard to target to avoid jitter.");
		CfgGroundRayStartUp = ((BaseUnityPlugin)this).Config.Bind<float>("Stability", "GroundRayStartUp", 4f, "Raycast starts this many meters above intended position.");
		CfgGroundRayDown = ((BaseUnityPlugin)this).Config.Bind<float>("Stability", "GroundRayDown", 18f, "Raycast length downward for ground snapping.");
		CfgGroundMinNormalY = ((BaseUnityPlugin)this).Config.Bind<float>("Stability", "GroundMinNormalY", 0.55f, "Minimum hit normal.y to be considered 'ground' (higher = stricter).");
		CfgRunLiftMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Stability", "RunLiftMeters", 0.22f, "Extra lift while rolling/running to keep attachments from scraping.");
		CfgTurnSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "TurnSpeed", 420f, "Degrees/sec turning speed to face the player.");
		CfgFrontRollOffsetDegrees = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "FrontRollOffsetDegrees", 90f, "Model roll correction applied ONLY during run-roll (degrees).");
		CfgWalkHopHeightMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "WalkHopHeightMeters", 0.45f, "Walk hop peak height (meters).");
		CfgWalkHopHz = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "WalkHopHz", 2f, "Walk hop cadence (hops per second).");
		CfgWalkHopForwardNudgeMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Animation", "WalkHopForwardNudgeMeters", 0.1f, "Small forward nudge during hop (meters).");
		CfgRockyQuotesEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Flavor", "RockyQuotesEnabled", true, "If true, Rocky will occasionally say positive/funny lines (client-side only).");
		CfgQuoteBubbleSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Flavor", "QuoteSeconds", 2.8f, "How long Rocky's world-text bubble stays visible (seconds).");
		CfgQuoteBubbleUpMeters = ((BaseUnityPlugin)this).Config.Bind<float>("Flavor", "QuoteUpMeters", 0.65f, "How high above Rocky the bubble appears (meters).");
		CfgQuoteWorldTextSize = ((BaseUnityPlugin)this).Config.Bind<float>("Flavor", "WorldTextSize", 0.048f, "World text size. Smaller = less billboardy.");
		CfgQuoteWrapChars = ((BaseUnityPlugin)this).Config.Bind<int>("Flavor", "WrapChars", 28, "Approx wrap characters for world-text to reduce billboard feel.");
		_harmony = new Harmony("Pix.RockyPet");
		_harmony.PatchAll(typeof(Patches));
		_harmony.PatchAll(typeof(HoverTextPatches));
		TryRegisterTerminalCommands();
	}

	private static void TryRegisterTerminalCommands()
	{
		//IL_0034: 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_002b: Expected O, but got Unknown
		try
		{
			object obj = <>c.<>9__34_0;
			if (obj == null)
			{
				ConsoleEvent val = delegate(ConsoleEventArgs args)
				{
					if (Enabled)
					{
						Player localPlayer = Player.m_localPlayer;
						if (!((Object)(object)localPlayer == (Object)null))
						{
							string text = null;
							if (args != null && args.Length > 1)
							{
								text = string.Join(" ", args.Args, 1, args.Length - 1)?.Trim();
								if (string.IsNullOrEmpty(text))
								{
									text = null;
								}
							}
							RockyPetBehaviour rockyPetBehaviour = RockyPetBehaviour.FindHoveredOrNearestOwned(localPlayer, 14f);
							if ((Object)(object)rockyPetBehaviour == (Object)null)
							{
								if ((Object)(object)MessageHud.instance != (Object)null)
								{
									MessageHud.instance.ShowMessage((MessageType)1, "No Rocky found (look at Rocky or stand closer).", 0, (Sprite)null, false);
								}
							}
							else
							{
								rockyPetBehaviour.ForceSpeakNow(text);
							}
						}
					}
				};
				<>c.<>9__34_0 = val;
				obj = (object)val;
			}
			new ConsoleCommand("rocky_say", "Force Rocky to say a line. Usage: rocky_say OR rocky_say <text>", (ConsoleEvent)obj, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
		}
		catch
		{
		}
	}
}
internal static class Patches
{
	[CompilerGenerated]
	private sealed class <TargetMethods>d__2 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private MethodBase <>2__current;

		private int <>l__initialThreadId;

		private MethodBase <m>5__1;

		MethodBase IEnumerator<MethodBase>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <TargetMethods>d__2(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<m>5__1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<m>5__1 = SafeFindMethodWithBody(typeof(ZNetScene), "Awake");
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 1;
					return true;
				}
				goto IL_0074;
			case 1:
				<>1__state = -1;
				goto IL_0074;
			case 2:
				{
					<>1__state = -1;
					break;
				}
				IL_0074:
				<m>5__1 = SafeFindMethodWithBody(typeof(ZNetScene), "CreateDestroyObjects");
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 2;
					return true;
				}
				break;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}

		[DebuggerHidden]
		IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
		{
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				return this;
			}
			return new <TargetMethods>d__2(0);
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<MethodBase>)this).GetEnumerator();
		}
	}

	private static bool _injected;

	private static MethodBase SafeFindMethodWithBody(Type t, string name)
	{
		if (t == null || string.IsNullOrEmpty(name))
		{
			return null;
		}
		MethodInfo methodInfo = null;
		try
		{
			methodInfo = t.GetMethod(name, BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
		}
		catch
		{
			methodInfo = null;
		}
		if (methodInfo == null)
		{
			return null;
		}
		if (methodInfo.IsAbstract)
		{
			return null;
		}
		try
		{
			if (methodInfo.GetMethodBody() == null)
			{
				return null;
			}
		}
		catch
		{
			return null;
		}
		return methodInfo;
	}

	[IteratorStateMachine(typeof(<TargetMethods>d__2))]
	[HarmonyTargetMethods]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TargetMethods>d__2(-2);
	}

	[HarmonyPostfix]
	private static void ZNetScene_AnyInit_Postfix(ZNetScene __instance)
	{
		TryInject(__instance);
	}

	private static void TryInject(ZNetScene scene)
	{
		if (_injected || !RockyPetPlugin.Enabled || (Object)(object)scene == (Object)null)
		{
			return;
		}
		string text = RockyPetPlugin.CfgTargetPrefab.Value?.Trim();
		if (string.IsNullOrEmpty(text))
		{
			return;
		}
		GameObject prefab = scene.GetPrefab(text);
		if (Object.op_Implicit((Object)(object)prefab))
		{
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZNetView>()))
			{
				prefab.AddComponent<ZNetView>();
			}
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<ZSyncTransform>()))
			{
				prefab.AddComponent<ZSyncTransform>();
			}
			if (!Object.op_Implicit((Object)(object)prefab.GetComponent<RockyPetBehaviour>()))
			{
				prefab.AddComponent<RockyPetBehaviour>();
			}
			_injected = true;
		}
	}
}
internal static class HoverTextPatches
{
	[CompilerGenerated]
	private sealed class <TargetMethods>d__1 : IEnumerable<MethodBase>, IEnumerable, IEnumerator<MethodBase>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private MethodBase <>2__current;

		private int <>l__initialThreadId;

		private MethodBase <m>5__1;

		MethodBase IEnumerator<MethodBase>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <TargetMethods>d__1(int <>1__state)
		{
			this.<>1__state = <>1__state;
			<>l__initialThreadId = Environment.CurrentManagedThreadId;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<m>5__1 = null;
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<m>5__1 = SafeFindHoverTextMethod(typeof(Piece));
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 1;
					return true;
				}
				goto IL_008a;
			case 1:
				<>1__state = -1;
				goto IL_008a;
			case 2:
				<>1__state = -1;
				goto IL_00cb;
			case 3:
				<>1__state = -1;
				goto IL_010c;
			case 4:
				<>1__state = -1;
				goto IL_014f;
			case 5:
				{
					<>1__state = -1;
					break;
				}
				IL_010c:
				<m>5__1 = SafeFindHoverTextMethod(typeof(Container));
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 4;
					return true;
				}
				goto IL_014f;
				IL_008a:
				<m>5__1 = SafeFindHoverTextMethod(typeof(ItemStand));
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 2;
					return true;
				}
				goto IL_00cb;
				IL_00cb:
				<m>5__1 = SafeFindHoverTextMethod(typeof(Tameable));
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 3;
					return true;
				}
				goto IL_010c;
				IL_014f:
				<m>5__1 = SafeFindHoverTextMethod(typeof(Door));
				if (<m>5__1 != null)
				{
					<>2__current = <m>5__1;
					<>1__state = 5;
					return true;
				}
				break;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}

		[DebuggerHidden]
		IEnumerator<MethodBase> IEnumerable<MethodBase>.GetEnumerator()
		{
			if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
			{
				<>1__state = 0;
				return this;
			}
			return new <TargetMethods>d__1(0);
		}

		[DebuggerHidden]
		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable<MethodBase>)this).GetEnumerator();
		}
	}

	private static MethodBase SafeFindHoverTextMethod(Type t)
	{
		if (t == null)
		{
			return null;
		}
		Type type = t;
		while (type != null)
		{
			MethodInfo methodInfo = null;
			try
			{
				methodInfo = type.GetMethod("GetHoverText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			}
			catch
			{
				methodInfo = null;
			}
			if (methodInfo != null && !methodInfo.IsAbstract)
			{
				try
				{
					if (methodInfo.GetMethodBody() != null)
					{
						return methodInfo;
					}
				}
				catch
				{
				}
			}
			type = type.BaseType;
		}
		return null;
	}

	[IteratorStateMachine(typeof(<TargetMethods>d__1))]
	[HarmonyTargetMethods]
	private static IEnumerable<MethodBase> TargetMethods()
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <TargetMethods>d__1(-2);
	}

	[HarmonyPostfix]
	private static void Any_GetHoverText_Postfix(object __instance, ref string __result)
	{
		//IL_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		if (!RockyPetPlugin.Enabled || __instance == null)
		{
			return;
		}
		Component val = (Component)((__instance is Component) ? __instance : null);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		RockyPetBehaviour componentInParent = val.GetComponentInParent<RockyPetBehaviour>();
		if (!((Object)(object)componentInParent == (Object)null))
		{
			bool followingForTooltip = componentInParent.GetFollowingForTooltip();
			KeyCode value = RockyPetPlugin.CfgToggleKey.Value;
			string text = ((object)(KeyCode)(ref value)).ToString().ToUpperInvariant();
			string text2 = (followingForTooltip ? "Stay" : "Follow");
			string text3 = "\n<color=white>[</color><color=yellow>" + text + "</color><color=white>]</color> " + text2;
			if (string.IsNullOrEmpty(__result))
			{
				__result = text3.TrimStart(new char[1] { '\n' });
			}
			else if (!__result.Contains(text3))
			{
				__result += text3;
			}
		}
	}
}
internal sealed class RockyWorldBubble : MonoBehaviour
{
	private float _dieAt;

	private Transform _follow;

	private Vector3 _localOffset;

	private TextMesh _tm;

	private float _startTime;

	internal static void Show(Transform anchor, Vector3 localOffset, float seconds, string text, float textSize, int wrapChars)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Expected O, but got Unknown
		//IL_0062: Unknown result type (might be due to invalid IL or missing references)
		//IL_0063: Unknown result type (might be due to invalid IL or missing references)
		//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
		if (!((Object)(object)anchor == (Object)null) && !string.IsNullOrEmpty(text))
		{
			string text2 = WrapText(text, Mathf.Clamp(wrapChars, 18, 64));
			GameObject val = new GameObject("RockyWorldBubble");
			val.layer = ((Component)anchor).gameObject.layer;
			RockyWorldBubble rockyWorldBubble = val.AddComponent<RockyWorldBubble>();
			rockyWorldBubble._follow = anchor;
			rockyWorldBubble._localOffset = localOffset;
			rockyWorldBubble._startTime = Time.time;
			rockyWorldBubble._dieAt = Time.time + Mathf.Max(0.25f, seconds);
			TextMesh val2 = (rockyWorldBubble._tm = val.AddComponent<TextMesh>());
			val2.text = text2;
			val2.anchor = (TextAnchor)7;
			val2.alignment = (TextAlignment)1;
			val2.richText = false;
			val2.fontSize = 64;
			val2.characterSize = Mathf.Clamp(textSize, 0.025f, 0.18f);
			val2.lineSpacing = 0.92f;
			val2.color = new Color(1f, 1f, 1f, 0.92f);
			MeshRenderer component = ((Component)val2).GetComponent<MeshRenderer>();
			if ((Object)(object)component != (Object)null)
			{
				((Renderer)component).shadowCastingMode = (ShadowCastingMode)0;
				((Renderer)component).receiveShadows = false;
			}
			rockyWorldBubble.LateUpdate();
		}
	}

	private void LateUpdate()
	{
		//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_00ae: Unknown result type (might be due to invalid IL or missing references)
		//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_00be: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
		//IL_018a: Unknown result type (might be due to invalid IL or missing references)
		//IL_018f: Unknown result type (might be due to invalid IL or missing references)
		//IL_01a6: 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)
		//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
		//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ed: 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)
		if ((Object)(object)_follow == (Object)null)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		if (Time.time >= _dieAt)
		{
			Object.Destroy((Object)(object)((Component)this).gameObject);
			return;
		}
		((Component)this).transform.position = _follow.TransformPoint(_localOffset);
		Camera val = Camera.main;
		if ((Object)(object)GameCamera.instance != (Object)null)
		{
			Camera component = ((Component)GameCamera.instance).GetComponent<Camera>();
			if ((Object)(object)component != (Object)null)
			{
				val = component;
			}
		}
		if ((Object)(object)val != (Object)null)
		{
			Vector3 val2 = ((Component)this).transform.position - ((Component)val).transform.position;
			val2.y = 0f;
			if (((Vector3)(ref val2)).sqrMagnitude > 0.001f)
			{
				((Component)this).transform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up);
			}
		}
		if ((Object)(object)_tm != (Object)null)
		{
			float num = Mathf.Max(0.01f, _dieAt - _startTime);
			float num2 = Mathf.Clamp01((Time.time - _startTime) / num);
			float num3 = Mathf.InverseLerp(0f, 0.12f, num2);
			float num4 = 1f - Mathf.InverseLerp(0.72f, 1f, num2);
			float num5 = Mathf.Clamp01(Mathf.Min(num3, num4));
			Color color = _tm.color;
			color.a = 0.92f * num5;
			_tm.color = color;
			Vector3 position = ((Component)this).transform.position;
			position.y += 0.12f * num2;
			((Component)this).transform.position = position;
		}
	}

	private static string WrapText(string s, int wrap)
	{
		if (string.IsNullOrEmpty(s))
		{
			return s;
		}
		if (s.Length <= wrap)
		{
			return s;
		}
		StringBuilder stringBuilder = new StringBuilder(s.Length + 16);
		int num = 0;
		string[] array = s.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
		foreach (string text in array)
		{
			int num2 = ((num == 0) ? text.Length : (text.Length + 1));
			if (num > 0 && num + num2 > wrap)
			{
				stringBuilder.Append('\n');
				stringBuilder.Append(text);
				num = text.Length;
				continue;
			}
			if (num > 0)
			{
				stringBuilder.Append(' ');
				num++;
			}
			stringBuilder.Append(text);
			num += text.Length;
		}
		return stringBuilder.ToString();
	}
}
public sealed class RockyPetBehaviour : MonoBehaviour
{
	private enum QuoteBucket
	{
		Compliment,
		Encouragement,
		Joke,
		Viking
	}

	private const string ZFollow = "PX_Rocky_Follow";

	private const string ZOwner = "PX_Rocky_Owner";

	private const string RpcToggle = "PX_Rocky_ToggleFollow";

	private const float RollRampSeconds = 0.35f;

	private const float RunTipDegrees = 88f;

	private const float RunSpinDegPerSec = 760f;

	private const float RollAxisBlendToRight = 0.92f;

	private const float HopReturnSeconds = 0.18f;

	private const float HopSmooth = 0.55f;

	private const float HopPitchDegrees = 12f;

	private const float QuoteChancePerCheck = 0.14f;

	private const float QuoteMinDelaySeconds = 180f;

	private const float QuoteMaxDelaySeconds = 420f;

	private const int QuoteMaxPerDay = 2;

	private static readonly int[] BucketWeights = new int[4] { 26, 34, 28, 12 };

	private static readonly string[] QuotesCompliment = new string[10] { "You’re looking beautiful today!", "You’ve got main character energy right now.", "That’s a legendary vibe you’re carrying.", "You look like you’ve got good loot luck today.", "Radiant. Absolutely radiant.", "I’m proud to be your rock.", "You’re built different—in the best way.", "Your drip is immaculate, adventurer.", "You make the meadows look even nicer.", "Honestly? You’re crushing it." };

	private static readonly string[] QuotesEncouragement = new string[10] { "Another great day to adventure with my friend!", "You’ve got this. One step at a time.", "Even a small win is still a win.", "I believe in you—like, aggressively.", "Deep breath. Next swing. You’re doing great.", "Your future self is cheering right now.", "We can handle anything together.", "Good things are ahead. Keep going.", "You’re tougher than the game thinks you are.", "I’m here. You’re not alone." };

	private static readonly string[] QuotesJokes = new string[10] { "Sharpen your axe… but not on me.", "If you need emotional support, I’m literally a rock.", "I’m not judging, but… we’ve eaten worse than that.", "If we die, I’m haunting the respawn stone with compliments.", "That was a plan. A questionable plan. But a plan.", "I’d help carry, but I’m already carrying the vibe.", "If you hear a noise… it’s probably just your greatness echoing.", "If fear shows up, tell it I said “no thanks.”", "We are so back. Even if we were never gone.", "I would follow you anywhere. Except into deep water. I’m a rock." };

	private static readonly string[] QuotesViking = new string[10] { "Skål! Another tale begins.", "Your saga is getting good.", "Even the Allfather would respect that effort.", "Keep your shield up, and your heart up too.", "The ravens are taking notes… probably.", "Forge onward, friend.", "Today, we earn a story worth telling.", "The winds favor your path.", "Valhalla can wait. We’ve got living to do.", "A true warrior rests—then rises." };

	private ZNetView _nview;

	private float _pivotToBottom;

	private float _lastGoodGroundY;

	private bool _hasLastGroundY;

	private bool _isMoving;

	private Vector3 _smoothVel;

	private float _roll01;

	private float _hopT;

	private float _hopY;

	private float _hopSin;

	private float _nextQuoteTime;

	private int _quoteDay = -1;

	private int _quotesToday = 0;

	private QuoteBucket _lastBucket = (QuoteBucket)(-1);

	private int _lastIndexInBucket = -1;

	private static MethodInfo _miGetHoverObject;

	private static MethodInfo _miIsRunningChar;

	private static MethodInfo _miIsRunningPlayer;

	private static readonly RaycastHit[] _groundHits = (RaycastHit[])(object)new RaycastHit[24];

	private void Awake()
	{
		_nview = ((Component)this).GetComponent<ZNetView>();
		if ((Object)(object)_nview != (Object)null && _nview.IsValid())
		{
			_nview.Register<long>("PX_Rocky_ToggleFollow", (Action<long, long>)RPC_ToggleFollow);
		}
		if (_miGetHoverObject == null)
		{
			_miGetHoverObject = AccessTools.Method(typeof(Player), "GetHoverObject", (Type[])null, (Type[])null);
		}
		if (_miIsRunningChar == null)
		{
			_miIsRunningChar = AccessTools.Method(typeof(Character), "IsRunning", (Type[])null, (Type[])null);
		}
		if (_miIsRunningPlayer == null)
		{
			_miIsRunningPlayer = AccessTools.Method(typeof(Player), "IsRunning", (Type[])null, (Type[])null);
		}
		_pivotToBottom = ComputePivotToBottom();
		_nextQuoteTime = Time.time + Random.Range(180f, 420f);
	}

	private void OnEnable()
	{
		//IL_0002: Unknown result type (might be due to invalid IL or missing references)
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		_smoothVel = Vector3.zero;
		_isMoving = false;
		_roll01 = 0f;
		_hopT = 0f;
		_hopY = 0f;
		_hopSin = 0f;
		_nextQuoteTime = Time.time + Random.Range(180f, 420f);
	}

	private void Update()
	{
		//IL_0072: Unknown result type (might be due to invalid IL or missing references)
		if (!RockyPetPlugin.Enabled)
		{
			return;
		}
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null || (Object)(object)_nview == (Object)null || !_nview.IsValid())
		{
			return;
		}
		TryRockyQuotes(localPlayer);
		if (IsHoveringThisRock(localPlayer) && Input.GetKeyDown(RockyPetPlugin.CfgToggleKey.Value))
		{
			long playerID = localPlayer.GetPlayerID();
			bool flag = !GetFollowing();
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				MessageHud.instance.ShowMessage((MessageType)2, flag ? "Rocky now follows" : "Rocky now stays", 0, (Sprite)null, false);
			}
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				ApplyToggle(playerID);
			}
			else
			{
				_nview.InvokeRPC("PX_Rocky_ToggleFollow", new object[1] { playerID });
			}
			_nextQuoteTime = Time.time + Random.Range(70f, 140f);
		}
	}

	private void TryRockyQuotes(Player lp)
	{
		if (RockyPetPlugin.CfgRockyQuotesEnabled == null || !RockyPetPlugin.CfgRockyQuotesEnabled.Value || !GetFollowing())
		{
			return;
		}
		long ownerId = GetOwnerId();
		if (ownerId == 0 || lp.GetPlayerID() != ownerId)
		{
			return;
		}
		int num = 0;
		if ((Object)(object)EnvMan.instance != (Object)null)
		{
			num = EnvMan.instance.GetDay();
		}
		if (_quoteDay != num)
		{
			_quoteDay = num;
			_quotesToday = 0;
		}
		if (_quotesToday < 2 && !(Time.time < _nextQuoteTime))
		{
			if (Random.value > 0.14f)
			{
				_nextQuoteTime = Time.time + Random.Range(45f, 85f);
				return;
			}
			SpeakBubble(PickQuoteNoRepeat());
			_quotesToday++;
			_nextQuoteTime = Time.time + Random.Range(180f, 420f);
		}
	}

	public void ForceSpeakNow(string forcedTextOrNull)
	{
		Player localPlayer = Player.m_localPlayer;
		if ((Object)(object)localPlayer == (Object)null)
		{
			return;
		}
		long ownerId = GetOwnerId();
		if (ownerId == 0L || localPlayer.GetPlayerID() == ownerId)
		{
			string text = forcedTextOrNull;
			if (string.IsNullOrEmpty(text))
			{
				text = PickQuoteNoRepeat(forceImmediate: true);
			}
			SpeakBubble(text);
			_nextQuoteTime = Time.time + Random.Range(108.00001f, 336f);
		}
	}

	private string PickQuoteNoRepeat(bool forceImmediate = false)
	{
		QuoteBucket quoteBucket = PickBucketWeighted();
		if (!forceImmediate && _lastBucket >= QuoteBucket.Compliment && quoteBucket == _lastBucket)
		{
			QuoteBucket quoteBucket2 = PickBucketWeighted();
			quoteBucket = quoteBucket2;
		}
		string[] bucketArray = GetBucketArray(quoteBucket);
		if (bucketArray == null || bucketArray.Length == 0)
		{
			return "You’re doing great!";
		}
		int num = Random.Range(0, bucketArray.Length);
		if (_lastBucket >= QuoteBucket.Compliment && quoteBucket == _lastBucket && num == _lastIndexInBucket)
		{
			for (int i = 0; i < 6; i++)
			{
				int num2 = Random.Range(0, bucketArray.Length);
				if (num2 != _lastIndexInBucket)
				{
					num = num2;
					break;
				}
			}
		}
		_lastBucket = quoteBucket;
		_lastIndexInBucket = num;
		return bucketArray[num];
	}

	private QuoteBucket PickBucketWeighted()
	{
		int num = 0;
		for (int i = 0; i < BucketWeights.Length; i++)
		{
			num += Mathf.Max(0, BucketWeights[i]);
		}
		if (num <= 0)
		{
			return QuoteBucket.Encouragement;
		}
		int num2 = Random.Range(0, num);
		int num3 = 0;
		for (int j = 0; j < BucketWeights.Length; j++)
		{
			num3 += Mathf.Max(0, BucketWeights[j]);
			if (num2 < num3)
			{
				return (QuoteBucket)j;
			}
		}
		return QuoteBucket.Encouragement;
	}

	private static string[] GetBucketArray(QuoteBucket bucket)
	{
		return bucket switch
		{
			QuoteBucket.Compliment => QuotesCompliment, 
			QuoteBucket.Encouragement => QuotesEncouragement, 
			QuoteBucket.Joke => QuotesJokes, 
			QuoteBucket.Viking => QuotesViking, 
			_ => QuotesEncouragement, 
		};
	}

	private void SpeakBubble(string text)
	{
		//IL_009a: Unknown result type (might be due to invalid IL or missing references)
		if (!string.IsNullOrEmpty(text))
		{
			float seconds = ((RockyPetPlugin.CfgQuoteBubbleSeconds != null) ? RockyPetPlugin.CfgQuoteBubbleSeconds.Value : 2.8f);
			float num = ((RockyPetPlugin.CfgQuoteBubbleUpMeters != null) ? RockyPetPlugin.CfgQuoteBubbleUpMeters.Value : 0.65f);
			float textSize = ((RockyPetPlugin.CfgQuoteWorldTextSize != null) ? RockyPetPlugin.CfgQuoteWorldTextSize.Value : 0.048f);
			int wrapChars = ((RockyPetPlugin.CfgQuoteWrapChars != null) ? RockyPetPlugin.CfgQuoteWrapChars.Value : 28);
			Vector3 localOffset = default(Vector3);
			((Vector3)(ref localOffset))..ctor(0f, Mathf.Clamp(num, 0.1f, 4f), 0f);
			RockyWorldBubble.Show(((Component)this).transform, localOffset, seconds, text, textSize, wrapChars);
		}
	}

	public static RockyPetBehaviour FindHoveredOrNearestOwned(Player lp, float maxDist)
	{
		//IL_006a: Unknown result type (might be due to invalid IL or missing references)
		//IL_006f: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
		if ((Object)(object)lp == (Object)null)
		{
			return null;
		}
		RockyPetBehaviour hoveredRocky = GetHoveredRocky(lp);
		if ((Object)(object)hoveredRocky != (Object)null)
		{
			return hoveredRocky;
		}
		long playerID = lp.GetPlayerID();
		RockyPetBehaviour result = null;
		float num = float.MaxValue;
		RockyPetBehaviour[] array = Object.FindObjectsByType<RockyPetBehaviour>((FindObjectsSortMode)0);
		if (array == null || array.Length == 0)
		{
			return null;
		}
		Vector3 position = ((Component)lp).transform.position;
		foreach (RockyPetBehaviour rockyPetBehaviour in array)
		{
			if ((Object)(object)rockyPetBehaviour == (Object)null || (Object)(object)rockyPetBehaviour._nview == (Object)null || !rockyPetBehaviour._nview.IsValid())
			{
				continue;
			}
			long ownerId = rockyPetBehaviour.GetOwnerId();
			if (ownerId == 0L || ownerId == playerID)
			{
				float num2 = Vector3.Distance(position, ((Component)rockyPetBehaviour).transform.position);
				if (!(num2 > maxDist) && num2 < num)
				{
					num = num2;
					result = rockyPetBehaviour;
				}
			}
		}
		return result;
	}

	private static RockyPetBehaviour GetHoveredRocky(Player lp)
	{
		//IL_007d: 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)
		if ((Object)(object)lp == (Object)null)
		{
			return null;
		}
		GameObject val = null;
		MethodInfo miGetHoverObject = _miGetHoverObject;
		if (miGetHoverObject != null)
		{
			try
			{
				object? obj = miGetHoverObject.Invoke(lp, null);
				val = (GameObject)((obj is GameObject) ? obj : null);
			}
			catch
			{
				val = null;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			Transform transform = ((Component)instance).transform;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(transform.position, transform.forward, ref val2, 6f, -1, (QueryTriggerInteraction)1))
			{
				val = (((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val2)).collider).gameObject : null);
				if ((Object)(object)val != (Object)null)
				{
					Transform root = val.transform.root;
					if ((Object)(object)root != (Object)null)
					{
						val = ((Component)root).gameObject;
					}
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return null;
		}
		RockyPetBehaviour componentInChildren = val.GetComponentInChildren<RockyPetBehaviour>();
		if ((Object)(object)componentInChildren != (Object)null)
		{
			return componentInChildren;
		}
		return val.GetComponentInParent<RockyPetBehaviour>();
	}

	private void FixedUpdate()
	{
		//IL_0084: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
		//IL_0114: Unknown result type (might be due to invalid IL or missing references)
		//IL_011f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0139: Unknown result type (might be due to invalid IL or missing references)
		//IL_013e: 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_0153: 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_0177: Unknown result type (might be due to invalid IL or missing references)
		//IL_017c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0189: Unknown result type (might be due to invalid IL or missing references)
		//IL_018e: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c0: Unknown result type (might be due to invalid IL or missing references)
		//IL_01c9: 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_029e: Unknown result type (might be due to invalid IL or missing references)
		//IL_03b8: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c2: Unknown result type (might be due to invalid IL or missing references)
		//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0391: Unknown result type (might be due to invalid IL or missing references)
		//IL_0396: Unknown result type (might be due to invalid IL or missing references)
		//IL_03a7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_03fe: Unknown result type (might be due to invalid IL or missing references)
		//IL_046f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0474: Unknown result type (might be due to invalid IL or missing references)
		//IL_048d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0492: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04d4: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e2: Unknown result type (might be due to invalid IL or missing references)
		//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
		//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_04f4: Unknown result type (might be due to invalid IL or missing references)
		if (!RockyPetPlugin.Enabled || (Object)(object)_nview == (Object)null || !_nview.IsValid() || !_nview.IsOwner())
		{
			return;
		}
		if (!GetFollowing())
		{
			UpdateRoll01(wantRolling: false);
			UpdateHop(wantHop: false);
			((Component)this).transform.position = PlantToGround(((Component)this).transform.position, 0f);
			_isMoving = false;
			_smoothVel = Vector3.zero;
			Player val = ResolveOwnerPlayer();
			if ((Object)(object)val != (Object)null)
			{
				FacePlayer(val, applyRunRollCorrection: false);
			}
			return;
		}
		Player val2 = ResolveOwnerPlayer();
		if ((Object)(object)val2 == (Object)null)
		{
			return;
		}
		bool ownerIsRunning = GetOwnerIsRunning(val2);
		UpdateRoll01(ownerIsRunning);
		float num = Mathf.Max(0f, RockyPetPlugin.CfgFreezeWithinMeters.Value);
		float num2 = Vector3.Distance(((Component)this).transform.position, ((Component)val2).transform.position);
		bool flag = num2 <= num;
		Vector3 val3 = ((Component)this).transform.position;
		if (!flag)
		{
			val3 = ComputeFollowTarget(val2);
			float extraLift = Mathf.Max(0f, RockyPetPlugin.CfgRunLiftMeters.Value) * _roll01;
			val3 = PlantToGround(val3, extraLift);
		}
		float num3 = (flag ? 0f : Vector3.Distance(((Component)this).transform.position, val3));
		if (!flag && num3 > RockyPetPlugin.CfgCatchupTeleportDistance.Value)
		{
			((Component)this).transform.position = val3;
			_smoothVel = Vector3.zero;
			_isMoving = false;
			num3 = 0f;
		}
		float num4 = Mathf.Max(0.05f, RockyPetPlugin.CfgStartFollowRadius.Value);
		float num5 = Mathf.Clamp(RockyPetPlugin.CfgStopFollowRadius.Value, 0.05f, num4);
		if (flag)
		{
			_isMoving = false;
		}
		else if (_isMoving)
		{
			if (num3 <= num5)
			{
				_isMoving = false;
			}
		}
		else if (num3 >= num4)
		{
			_isMoving = true;
		}
		float num6 = Mathf.Max(0.01f, RockyPetPlugin.CfgStopDeadzone.Value);
		if (!_isMoving && !flag && num3 <= num6)
		{
			((Component)this).transform.position = val3;
			num3 = 0f;
		}
		float num7 = Mathf.Max(0.01f, RockyPetPlugin.CfgMoveSmoothTime.Value);
		float num8 = Mathf.Max(0.1f, RockyPetPlugin.CfgMaxMoveSpeed.Value);
		float num9 = Mathf.Clamp(RockyPetPlugin.CfgWalkMaxMoveSpeed.Value, 0.1f, num8);
		float num10 = ((_roll01 < 0.05f) ? num9 : num8);
		float num11 = Mathf.Max(1f, RockyPetPlugin.CfgRunMoveSpeedMultiplier.Value);
		float num12 = Mathf.Clamp(RockyPetPlugin.CfgRunSmoothTimeMultiplier.Value, 0.2f, 1f);
		float num13 = Mathf.Lerp(1f, num11, _roll01);
		float num14 = Mathf.Lerp(1f, num12, _roll01);
		num10 *= num13;
		num7 *= num14;
		if (_isMoving && !flag)
		{
			((Component)this).transform.position = Vector3.SmoothDamp(((Component)this).transform.position, val3, ref _smoothVel, num7, num10, Time.fixedDeltaTime);
		}
		else
		{
			_smoothVel *= 0.7f;
		}
		float extraLift2 = Mathf.Max(0f, RockyPetPlugin.CfgRunLiftMeters.Value) * _roll01;
		((Component)this).transform.position = PlantToGround(((Component)this).transform.position, extraLift2);
		bool flag2 = _isMoving && !flag && _roll01 < 0.05f;
		UpdateHop(flag2);
		float num15 = Mathf.Max(0f, RockyPetPlugin.CfgWalkHopHeightMeters.Value);
		if (_hopY > 0.0001f && num15 > 0.0001f)
		{
			Vector3 position = ((Component)this).transform.position;
			position.y += _hopY;
			Vector3 forward = ((Component)val2).transform.forward;
			forward.y = 0f;
			if (((Vector3)(ref forward)).sqrMagnitude > 0.001f)
			{
				((Vector3)(ref forward)).Normalize();
			}
			float num16 = Mathf.Max(0f, RockyPetPlugin.CfgWalkHopForwardNudgeMeters.Value);
			position += forward * (num16 * (_hopY / num15));
			((Component)this).transform.position = position;
		}
		FacePlayer(val2, _roll01 > 0.001f);
		if (flag2)
		{
			ApplyHopPitchTilt();
		}
		if (_roll01 > 0.001f)
		{
			ApplyRunRoll(val2);
		}
	}

	private void UpdateRoll01(bool wantRolling)
	{
		float num = (wantRolling ? 1f : 0f);
		float num2 = Mathf.Max(0.05f, 0.35f);
		float num3 = Time.fixedDeltaTime / num2;
		_roll01 = Mathf.MoveTowards(_roll01, num, num3);
	}

	private void UpdateHop(bool wantHop)
	{
		if (wantHop)
		{
			_hopT += Time.fixedDeltaTime;
			float num = Mathf.Max(0.1f, RockyPetPlugin.CfgWalkHopHz.Value);
			float num2 = Mathf.Max(0f, RockyPetPlugin.CfgWalkHopHeightMeters.Value);
			float num3 = _hopT * ((float)Math.PI * 2f) * num;
			_hopSin = Mathf.Sin(num3);
			float hopSin = _hopSin;
			float num4 = hopSin * hopSin;
			num4 = Mathf.Pow(num4, 1.25f);
			float num5 = num4 * num2;
			_hopY = Mathf.Lerp(_hopY, num5, 0.55f);
		}
		else
		{
			_hopSin = Mathf.MoveTowards(_hopSin, 0f, Time.fixedDeltaTime * 8f);
			float num6 = Mathf.Max(0.05f, 0.18f);
			float num7 = Time.fixedDeltaTime / num6;
			float num8 = Mathf.Max(0f, RockyPetPlugin.CfgWalkHopHeightMeters.Value);
			_hopY = Mathf.MoveTowards(_hopY, 0f, num7 * Mathf.Max(0.05f, num8));
		}
	}

	private void ApplyHopPitchTilt()
	{
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0051: Unknown result type (might be due to invalid IL or missing references)
		//IL_005c: 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)
		float num = Mathf.Max(0.001f, RockyPetPlugin.CfgWalkHopHeightMeters.Value);
		float num2 = Mathf.Clamp01(_hopY / num);
		float num3 = 12f * _hopSin * (0.35f + 0.65f * num2);
		((Component)this).transform.rotation = Quaternion.AngleAxis(num3, ((Component)this).transform.right) * ((Component)this).transform.rotation;
	}

	private bool GetOwnerIsRunning(Player owner)
	{
		//IL_0091: Unknown result type (might be due to invalid IL or missing references)
		//IL_0096: Unknown result type (might be due to invalid IL or missing references)
		if (_miIsRunningPlayer != null)
		{
			try
			{
				object obj = _miIsRunningPlayer.Invoke(owner, null);
				if (obj is bool)
				{
					bool result = (bool)obj;
					if (true)
					{
						return result;
					}
				}
			}
			catch
			{
			}
		}
		if (_miIsRunningChar != null)
		{
			try
			{
				object obj3 = _miIsRunningChar.Invoke(owner, null);
				if (obj3 is bool)
				{
					bool result2 = (bool)obj3;
					if (true)
					{
						return result2;
					}
				}
			}
			catch
			{
			}
		}
		Vector3 velocity = ((Character)owner).GetVelocity();
		return ((Vector3)(ref velocity)).magnitude >= 5.2f;
	}

	private void FacePlayer(Player owner, bool applyRunRollCorrection)
	{
		//IL_0007: Unknown result type (might be due to invalid IL or missing references)
		//IL_0012: Unknown result type (might be due to invalid IL or missing references)
		//IL_0017: Unknown result type (might be due to invalid IL or missing references)
		//IL_001c: Unknown result type (might be due to invalid IL or missing references)
		//IL_004a: Unknown result type (might be due to invalid IL or missing references)
		//IL_004b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0050: Unknown result type (might be due to invalid IL or missing references)
		//IL_0055: 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)
		//IL_00cc: 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_0085: 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_0097: 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)
		Vector3 val = ((Component)owner).transform.position - ((Component)this).transform.position;
		val.y = 0f;
		if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
		{
			return;
		}
		((Vector3)(ref val)).Normalize();
		Quaternion val2 = Quaternion.LookRotation(val, Vector3.up);
		if (applyRunRollCorrection)
		{
			float num = RockyPetPlugin.CfgFrontRollOffsetDegrees.Value * _roll01;
			if (Mathf.Abs(num) > 0.01f)
			{
				val2 *= Quaternion.Euler(0f, 0f, num);
			}
		}
		float num2 = Mathf.Max(30f, RockyPetPlugin.CfgTurnSpeed.Value);
		float num3 = num2 * Time.fixedDeltaTime;
		((Component)this).transform.rotation = Quaternion.RotateTowards(((Component)this).transform.rotation, val2, num3);
	}

	private void ApplyRunRoll(Player owner)
	{
		//IL_0007: 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_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		//IL_0041: Unknown result type (might be due to invalid IL or missing references)
		//IL_0046: Unknown result type (might be due to invalid IL or missing references)
		//IL_002d: 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_008c: Unknown result type (might be due to invalid IL or missing references)
		//IL_008d: 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_00a2: 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_00b4: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00c6: 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_0061: Unknown result type (might be due to invalid IL or missing references)
		//IL_0066: Unknown result type (might be due to invalid IL or missing references)
		//IL_010e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0110: Unknown result type (might be due to invalid IL or missing references)
		//IL_011b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0120: 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_00e8: Unknown result type (might be due to invalid IL or missing references)
		Vector3 forward = ((Component)owner).transform.forward;
		forward.y = 0f;
		if (((Vector3)(ref forward)).sqrMagnitude < 0.001f)
		{
			forward = Vector3.forward;
		}
		((Vector3)(ref forward)).Normalize();
		Vector3 val = Vector3.Cross(Vector3.up, forward);
		if (((Vector3)(ref val)).sqrMagnitude < 0.001f)
		{
			val = ((Component)owner).transform.right;
		}
		((Vector3)(ref val)).Normalize();
		float num = Mathf.Clamp(88f * _roll01, 0f, 90f);
		Quaternion val2 = Quaternion.AngleAxis(num, val) * ((Component)this).transform.rotation;
		((Component)this).transform.rotation = Quaternion.Slerp(((Component)this).transform.rotation, val2, 0.2f);
		Vector3 val3 = Vector3.Lerp(forward, val, 0.92f);
		if (((Vector3)(ref val3)).sqrMagnitude < 0.001f)
		{
			val3 = val;
		}
		((Vector3)(ref val3)).Normalize();
		float num2 = 760f * _roll01 * Time.fixedDeltaTime;
		((Component)this).transform.rotation = Quaternion.AngleAxis(num2, val3) * ((Component)this).transform.rotation;
	}

	private Vector3 ComputeFollowTarget(Player owner)
	{
		//IL_0007: 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_001b: 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_0027: 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_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_0048: Unknown result type (might be due to invalid IL or missing references)
		//IL_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_0056: Unknown result type (might be due to invalid IL or missing references)
		Vector3 val = -((Component)owner).transform.forward * RockyPetPlugin.CfgFollowDistance.Value;
		Vector3 val2 = ((Component)owner).transform.right * RockyPetPlugin.CfgFollowSideOffset.Value;
		return ((Component)owner).transform.position + val + val2;
	}

	private Vector3 PlantToGround(Vector3 pos, float extraLift)
	{
		//IL_003b: Unknown result type (might be due to invalid IL or missing references)
		//IL_003c: Unknown result type (might be due to invalid IL or missing references)
		//IL_0042: Unknown result type (might be due to invalid IL or missing references)
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: 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_007b: Unknown result type (might be due to invalid IL or missing references)
		//IL_0080: Unknown result type (might be due to invalid IL or missing references)
		//IL_0152: Unknown result type (might be due to invalid IL or missing references)
		//IL_0164: 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_0182: Unknown result type (might be due to invalid IL or missing references)
		//IL_0183: Unknown result type (might be due to invalid IL or missing references)
		//IL_0187: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
		float num = Mathf.Max(0.1f, RockyPetPlugin.CfgGroundRayStartUp.Value);
		float num2 = Mathf.Max(0.5f, RockyPetPlugin.CfgGroundRayDown.Value);
		float num3 = Mathf.Clamp01(RockyPetPlugin.CfgGroundMinNormalY.Value);
		Vector3 val = pos + Vector3.up * num;
		int num4 = Physics.RaycastNonAlloc(val, Vector3.down, _groundHits, num + num2, -1, (QueryTriggerInteraction)1);
		float num5 = float.NaN;
		for (int i = 0; i < num4; i++)
		{
			RaycastHit val2 = _groundHits[i];
			if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && (!((Object)(object)((Component)((RaycastHit)(ref val2)).collider).transform != (Object)null) || !((Component)((RaycastHit)(ref val2)).collider).transform.IsChildOf(((Component)this).transform)) && !(((RaycastHit)(ref val2)).normal.y < num3))
			{
				float y = ((RaycastHit)(ref val2)).point.y;
				if (float.IsNaN(num5) || y > num5)
				{
					num5 = y;
				}
			}
		}
		if (!float.IsNaN(num5))
		{
			pos.y = num5 + _pivotToBottom + Mathf.Max(0f, extraLift);
			_lastGoodGroundY = pos.y;
			_hasLastGroundY = true;
			return pos;
		}
		if (_hasLastGroundY)
		{
			pos.y = _lastGoodGroundY;
		}
		return pos;
	}

	private float ComputePivotToBottom()
	{
		//IL_001f: Unknown result type (might be due to invalid IL or missing references)
		//IL_0024: Unknown result type (might be due to invalid IL or missing references)
		//IL_0028: Unknown result type (might be due to invalid IL or missing references)
		//IL_0039: Unknown result type (might be due to invalid IL or missing references)
		Collider componentInChildren = ((Component)this).GetComponentInChildren<Collider>();
		if ((Object)(object)componentInChildren == (Object)null)
		{
			return 0.2f;
		}
		Bounds bounds = componentInChildren.bounds;
		float y = ((Bounds)(ref bounds)).min.y;
		float y2 = ((Component)this).transform.position.y;
		float num = y2 - y;
		if (num < 0.01f)
		{
			num = 0.2f;
		}
		if (num > 5f)
		{
			num = 0.2f;
		}
		return num;
	}

	private Player ResolveOwnerPlayer()
	{
		long ownerId = GetOwnerId();
		if (ownerId == 0)
		{
			return null;
		}
		List<Player> allPlayers = Player.GetAllPlayers();
		if (allPlayers == null)
		{
			return null;
		}
		for (int i = 0; i < allPlayers.Count; i++)
		{
			Player val = allPlayers[i];
			if ((Object)(object)val != (Object)null && val.GetPlayerID() == ownerId)
			{
				return val;
			}
		}
		return null;
	}

	private bool IsHoveringThisRock(Player lp)
	{
		//IL_0068: 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)
		GameObject val = null;
		if (_miGetHoverObject != null)
		{
			try
			{
				object? obj = _miGetHoverObject.Invoke(lp, null);
				val = (GameObject)((obj is GameObject) ? obj : null);
			}
			catch
			{
				val = null;
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			GameCamera instance = GameCamera.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return false;
			}
			Transform transform = ((Component)instance).transform;
			RaycastHit val2 = default(RaycastHit);
			if (Physics.Raycast(transform.position, transform.forward, ref val2, 6f, -1, (QueryTriggerInteraction)1))
			{
				val = (((Object)(object)((RaycastHit)(ref val2)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val2)).collider).gameObject : null);
				if ((Object)(object)val != (Object)null)
				{
					Transform root = val.transform.root;
					if ((Object)(object)root != (Object)null)
					{
						val = ((Component)root).gameObject;
					}
				}
			}
		}
		if ((Object)(object)val == (Object)null)
		{
			return false;
		}
		if ((Object)(object)val == (Object)(object)((Component)this).gameObject)
		{
			return true;
		}
		Transform val3 = val.transform;
		while ((Object)(object)val3 != (Object)null)
		{
			if ((Object)(object)((Component)val3).gameObject == (Object)(object)((Component)this).gameObject)
			{
				return true;
			}
			val3 = val3.parent;
		}
		return false;
	}

	private bool GetFollowing()
	{
		ZNetView nview = _nview;
		ZDO val = ((nview != null) ? nview.GetZDO() : null);
		if (val == null)
		{
			return false;
		}
		return val.GetBool("PX_Rocky_Follow", false);
	}

	internal bool GetFollowingForTooltip()
	{
		return GetFollowing();
	}

	private long GetOwnerId()
	{
		ZNetView nview = _nview;
		ZDO val = ((nview != null) ? nview.GetZDO() : null);
		if (val == null)
		{
			return 0L;
		}
		return val.GetLong("PX_Rocky_Owner", 0L);
	}

	private void ApplyToggle(long ownerPlayerId)
	{
		//IL_0047: Unknown result type (might be due to invalid IL or missing references)
		//IL_004c: Unknown result type (might be due to invalid IL or missing references)
		ZDO zDO = _nview.GetZDO();
		if (zDO != null)
		{
			bool flag = !zDO.GetBool("PX_Rocky_Follow", false);
			zDO.Set("PX_Rocky_Follow", flag);
			if (flag)
			{
				zDO.Set("PX_Rocky_Owner", ownerPlayerId);
			}
			_smoothVel = Vector3.zero;
			_isMoving = false;
		}
	}

	private void RPC_ToggleFollow(long sender, long ownerPlayerId)
	{
		if (RockyPetPlugin.Enabled)
		{
			ApplyToggle(ownerPlayerId);
		}
	}
}