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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using Unity.Mathematics;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Thanks.I_am_a_Tumbleweed")]
[assembly: AssemblyDescription("Client-side controllable tumbleweed form for PEAK. Hold N for one second in any scene to become a rolling tumbleweed; press N again to return to normal. WASD rolls, Shift sprints, Space hops.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Thanks")]
[assembly: AssemblyProduct("I'm a Tumbleweed")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("8c2f5d61-9a47-4e36-b7e4-1d6f0a83c529")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ImTumbleweed
{
[BepInPlugin("com.github.Thanks.ImTumbleweed", "I'm a Tumbleweed", "0.1.0")]
public sealed class TumbleweedPlugin : BaseUnityPlugin
{
public const string Id = "com.github.Thanks.ImTumbleweed";
public const string Name = "I'm a Tumbleweed";
public const string Version = "0.1.0";
internal static ManualLogSource Log;
internal static ConfigEntry<KeyCode> ToggleKey;
internal static ConfigEntry<float> TransformHoldSeconds;
internal static ConfigEntry<float> AutoRevertSeconds;
internal static ConfigEntry<float> WeedRenewInterval;
internal static ConfigEntry<KeyCode> JumpKey;
internal static ConfigEntry<KeyCode> SprintKey;
internal static ConfigEntry<float> MovementForce;
internal static ConfigEntry<float> SprintMultiplier;
internal static ConfigEntry<float> MaxSpeed;
internal static ConfigEntry<float> JumpSpeed;
internal static ConfigEntry<float> WeedScale;
internal static ConfigEntry<float> CameraDistance;
internal static ConfigEntry<float> CameraHeight;
internal static ConfigEntry<float> CameraFov;
internal static ConfigEntry<bool> ShowWeedVisual;
private readonly Harmony _harmony = new Harmony("com.github.Thanks.ImTumbleweed");
private TumbleweedController _controller;
private float _toggleHoldSeconds;
private void Awake()
{
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Expected O, but got Unknown
//IL_00da: Unknown result type (might be due to invalid IL or missing references)
//IL_00e4: Expected O, but got Unknown
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
//IL_0121: Expected O, but got Unknown
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_01a3: Expected O, but got Unknown
//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Expected O, but got Unknown
//IL_0213: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Expected O, but got Unknown
//IL_0250: Unknown result type (might be due to invalid IL or missing references)
//IL_025a: Expected O, but got Unknown
//IL_028d: Unknown result type (might be due to invalid IL or missing references)
//IL_0297: Expected O, but got Unknown
//IL_02ca: Unknown result type (might be due to invalid IL or missing references)
//IL_02d4: Expected O, but got Unknown
//IL_0307: Unknown result type (might be due to invalid IL or missing references)
//IL_0311: Expected O, but got Unknown
//IL_0344: Unknown result type (might be due to invalid IL or missing references)
//IL_034e: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
_harmony.PatchAll(typeof(TumbleweedHarmonyPatches).Assembly);
ConfigureOptionalCharacterPatches();
ConfigureOptionalEndgamePatches();
ConfigureCameraFallbackPatch();
SceneManager.sceneLoaded += OnSceneLoaded;
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleKey", (KeyCode)110, "Hold to become a tumbleweed. Press again (short press) to return to normal.");
TransformHoldSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Controls", "TransformHoldSeconds", 1f, new ConfigDescription("How long the toggle key must be held down before the transformation starts.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 3f), Array.Empty<object>()));
AutoRevertSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "AutoRevertSeconds", 0f, new ConfigDescription("How long the tumbleweed form lasts before the player automatically reverts. 0 = unlimited (the form lasts until the player presses the toggle key again).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 300f), Array.Empty<object>()));
WeedRenewInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "WeedRenewInterval", 10f, new ConfigDescription("How often the owner destroys and respawns the networked tumbleweed so unmodded clients never lose it to their vanilla RemoveAfterSeconds self-destruct (~15s). Must stay below 15. 0 = disabled (only matters in rooms with unmodded clients; modded clients keep the weed alive through Harmony patches anyway).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 14f), Array.Empty<object>()));
JumpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "JumpKey", (KeyCode)32, "Press Space while in tumbleweed form to hop. Only works when the weed is on the ground.");
SprintKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SprintKey", (KeyCode)304, "Hold Shift to roll faster while in tumbleweed form.");
MovementForce = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "MovementForce", 22f, new ConfigDescription("How strongly WASD pushes the tumbleweed (acceleration, mass-independent).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>()));
SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "SprintMultiplier", 2f, new ConfigDescription("Force/speed multiplier while holding the sprint key.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
MaxSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "MaxSpeed", 18f, new ConfigDescription("Horizontal speed cap for WASD rolling (physics like rolling downhill can exceed it).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>()));
JumpSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "JumpSpeed", 15.65f, new ConfigDescription("Upward speed applied when hopping (about 5x the default jump height).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
WeedScale = ((BaseUnityPlugin)this).Config.Bind<float>("Weed", "Scale", 1f, new ConfigDescription("Size multiplier of the tumbleweed. 1 = vanilla prefab size (2x), which makes the owner's weed and unmodded clients' weed identical, so the character stays centered in the ball on both sides. Larger values enlarge the owner's ball but unmodded clients still see the vanilla size (scale is not synced), so the remote character appears above the ball.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 4f), Array.Empty<object>()));
CameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Distance", 12f, new ConfigDescription("Third-person tumbleweed camera distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(6f, 30f), Array.Empty<object>()));
CameraHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Height", 4f, new ConfigDescription("Third-person tumbleweed camera height above the weed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 14f), Array.Empty<object>()));
CameraFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Fov", 80f, new ConfigDescription("Field of view while in tumbleweed form.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 110f), Array.Empty<object>()));
ShowWeedVisual = ((BaseUnityPlugin)this).Config.Bind<bool>("Weed", "ShowWeedVisual", true, "Show the tumbleweed ball while transformed (the physics body stays active either way).");
((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm a Tumbleweed] Loaded version 0.1.0.");
}
private void ConfigureOptionalCharacterPatches()
{
TryPatchOptionalCharacterMethod("RPCA_Die", Type.EmptyTypes, "CharacterRpcDiePrefix", "Character.RPCA_Die()");
TryPatchOptionalCharacterMethod("RPCA_SetDead", Type.EmptyTypes, "CharacterRpcSetDeadPrefix", "Character.RPCA_SetDead()");
TryPatchOptionalCharacterMethod("RPCA_PassOut", Type.EmptyTypes, "CharacterRpcPassOutPrefix", "Character.RPCA_PassOut()");
TryPatchOptionalCharacterMethod("DieInstantly", Type.EmptyTypes, "CharacterDieInstantlyPrefix", "Character.DieInstantly()");
TryPatchOptionalCharacterMethod("HandleDeath", Type.EmptyTypes, "CharacterHandleDeathPrefix", "Character.HandleDeath()");
TryPatchOptionalCharacterMethod("WarpPlayerRPC", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, "CharacterWarpPlayerRpcPrefix", "Character.WarpPlayerRPC(Vector3,bool)");
TryPatchOptionalCharacterMethod("WarpPlayer", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, "CharacterWarpPlayerPrefix", "Character.WarpPlayer(Vector3,bool)");
TryPatchOptionalCharacterMethod("Fall", new Type[2]
{
typeof(float),
typeof(float)
}, "CharacterFallPrefix", "Character.Fall(float,float)");
TryPatchOptionalCharacterMethod("RPCA_Fall", new Type[2]
{
typeof(float),
typeof(float)
}, "CharacterRpcFallPrefix", "Character.RPCA_Fall(float,float)");
}
private void TryPatchOptionalCharacterMethod(string methodName, Type[] parameterTypes, string prefixName, string description)
{
TryPatchOptionalMethod(typeof(Character), methodName, parameterTypes, prefixName, description);
}
private void ConfigureOptionalEndgamePatches()
{
TryPatchOptionalMethod(typeof(Character), "RPCEndGame", Type.EmptyTypes, "CharacterRPCEndGamePrefix", "Character.RPCEndGame()");
TryPatchOptionalMethod(typeof(CharacterStats), "Win", Type.EmptyTypes, "CharacterStatsWinPrefix", "CharacterStats.Win()");
TryPatchOptionalMethod(typeof(CharacterStats), "GetFinalTimelineInfo", Type.EmptyTypes, "CharacterStatsGetFinalTimelineInfoPrefix", "CharacterStats.GetFinalTimelineInfo()");
TryPatchOptionalMethod(typeof(CharacterStats), "GetFirstTimelineInfo", Type.EmptyTypes, "CharacterStatsGetFirstTimelineInfoPrefix", "CharacterStats.GetFirstTimelineInfo()");
TryPatchOptionalMethod(typeof(PeakHandler), "EndCutscene", Type.EmptyTypes, "PeakHandlerEndCutscenePrefix", "PeakHandler.EndCutscene()");
TryPatchOptionalMethod(typeof(GameOverHandler), "BeginAirportLoadRPC", Type.EmptyTypes, "GameOverHandlerBeginAirportLoadRPCPrefix", "GameOverHandler.BeginAirportLoadRPC()");
TryPatchOptionalMethod(typeof(EndScreen), "ReturnToAirport", Type.EmptyTypes, "EndScreenReturnToAirportPrefix", "EndScreen.ReturnToAirport()");
}
private void TryPatchOptionalMethod(Type declaringType, string methodName, Type[] parameterTypes, string prefixName, string description)
{
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Expected O, but got Unknown
try
{
MethodInfo methodInfo = AccessTools.Method(declaringType, methodName, parameterTypes, (Type[])null);
if (methodInfo == null)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm a Tumbleweed] Optional " + description + " patch skipped; method is not present in this game build."));
return;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(TumbleweedHarmonyPatches), prefixName, (Type[])null, (Type[])null);
if (methodInfo2 == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Tumbleweed] Optional " + description + " patch skipped; prefix method was not found."));
}
else
{
_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Tumbleweed] Optional " + description + " patch failed: " + ex.Message));
}
}
private void ConfigureCameraFallbackPatch()
{
//IL_0100: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Expected O, but got Unknown
try
{
Type type = AccessTools.TypeByName("MainCameraMovement");
if (type == null)
{
foreach (Type item in AccessTools.AllTypes())
{
if (item.FullName == "MainCameraMovement")
{
type = item;
break;
}
}
}
if (type == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm a Tumbleweed] Camera fallback patch skipped; MainCameraMovement type not found.");
return;
}
MethodInfo methodInfo = AccessTools.Method(type, "LateUpdate", (Type[])null, (Type[])null);
if (methodInfo == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm a Tumbleweed] Camera fallback patch skipped; MainCameraMovement.LateUpdate not found.");
return;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(TumbleweedHarmonyPatches), "MainCameraMovementLateUpdatePostfix", (Type[])null, (Type[])null);
if (methodInfo2 == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)"[I'm a Tumbleweed] Camera fallback patch skipped; postfix method not found.");
return;
}
_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
TumbleweedController.CameraOverridePatchActive = true;
((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm a Tumbleweed] Camera Harmony fallback active (MainCameraMovement.LateUpdate postfix).");
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Tumbleweed] Camera fallback patch failed: " + ex.Message));
}
}
private void Update()
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((int)ToggleKey.Value == 0)
{
return;
}
if ((Object)(object)_controller != (Object)null && _controller.Active)
{
if (Input.GetKeyDown(ToggleKey.Value))
{
ExitWeed();
}
}
else if (Input.GetKey(ToggleKey.Value))
{
_toggleHoldSeconds += Time.deltaTime;
if (_toggleHoldSeconds >= TransformHoldSeconds.Value)
{
_toggleHoldSeconds = 0f;
TryEnterWeed();
}
}
else
{
_toggleHoldSeconds = 0f;
}
if ((Object)(object)_controller != (Object)null && _controller.Active && !_controller.IsValid())
{
ForceExit();
}
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Tumbleweed] Plugin.Update: " + ex));
}
}
}
private void OnDestroy()
{
try
{
SceneManager.sceneLoaded -= OnSceneLoaded;
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[I'm a Tumbleweed] SceneLoaded unsubscribe failed (non-fatal): " + ex.Message));
}
}
try
{
ForceExit();
}
catch (Exception ex2)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("[I'm a Tumbleweed] Exit during cleanup failed: " + ex2.Message));
}
}
try
{
_harmony.UnpatchSelf();
}
catch (Exception ex3)
{
ManualLogSource log3 = Log;
if (log3 != null)
{
log3.LogWarning((object)("[I'm a Tumbleweed] Harmony unpatch failed (non-fatal): " + ex3.Message));
}
}
}
private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
{
try
{
TumbleweedController.ForceExitForEndGame();
_controller = null;
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[I'm a Tumbleweed] Exit during scene load failed: " + ex.Message));
}
}
}
private void TryEnterWeed()
{
Character localCharacter = Character.localCharacter;
if (CanTransform(localCharacter))
{
EnterWeed(localCharacter);
}
}
private static bool CanTransform(Character character)
{
if ((Object)(object)character == (Object)null)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)"[I'm a Tumbleweed] No local character found.");
}
return false;
}
if (TumbleweedController.IsLocalWeedCharacter(character))
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)"[I'm a Tumbleweed] Already in tumbleweed form.");
}
return false;
}
if (character.isZombie || character.isBot || character.isScoutmaster)
{
ManualLogSource log3 = Log;
if (log3 != null)
{
log3.LogWarning((object)"[I'm a Tumbleweed] Cannot transform while in another special form.");
}
return false;
}
if ((Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null)
{
ManualLogSource log4 = Log;
if (log4 != null)
{
log4.LogWarning((object)"[I'm a Tumbleweed] Local character is not ready yet.");
}
return false;
}
if (character.data.dead || character.data.passedOut || character.data.fullyPassedOut || character.data.fallSeconds > 0f || character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing)
{
ManualLogSource log5 = Log;
if (log5 != null)
{
log5.LogWarning((object)"[I'm a Tumbleweed] Local character is not in a valid state to transform.");
}
return false;
}
return true;
}
private void EnterWeed(Character character)
{
try
{
_controller = ((Component)character).gameObject.GetComponent<TumbleweedController>();
if ((Object)(object)_controller == (Object)null)
{
_controller = ((Component)character).gameObject.AddComponent<TumbleweedController>();
}
_controller.EnterWeed(character);
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Tumbleweed] Failed to enter tumbleweed form:\n" + ex));
}
_controller = null;
}
}
private void ExitWeed()
{
try
{
_controller?.ExitWeed();
_controller = null;
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Tumbleweed] Failed to exit tumbleweed form: " + ex));
}
}
}
private void ForceExit()
{
if ((Object)(object)_controller == (Object)null)
{
return;
}
try
{
_controller.ExitWeed();
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[I'm a Tumbleweed] ForceExit failed: " + ex.Message));
}
}
_controller = null;
}
}
[DefaultExecutionOrder(600)]
public sealed class TumbleweedController : MonoBehaviour
{
private const float CameraLookAhead = 3f;
private const float CameraSmoothTime = 0.08f;
private const float CameraRotationSharpness = 12f;
private const float DefaultCameraDistance = 12f;
private const float DefaultCameraHeight = 4f;
private const float DefaultCameraFov = 80f;
private const float JumpCooldown = 0.25f;
private const float GroundCheckExtra = 0.35f;
private const float VoidExitHeight = -80f;
private Character _character;
private Vector3 _prevCenter;
private Vector3 _cameraVelocity;
private Vector3 _cameraSmoothedPosition;
private Quaternion _cameraSmoothedRotation;
private bool _cameraHasSmoothedPosition;
private GameObject _weedRoot;
private Rigidbody _weedRigidbody;
private SphereCollider _weedCollider;
private bool _weedIsNetworked;
private float _nextJumpAllowedTime;
private float _activeSeconds;
internal const string NetworkVisualMarker = "ImTumbleweed.Visual";
internal static readonly Dictionary<int, GameObject> WeedRootByCharacter = new Dictionary<int, GameObject>();
private readonly Dictionary<GameObject, bool> _hiddenHudStates = new Dictionary<GameObject, bool>();
private float _nextHudSearchTime;
private readonly List<KeyValuePair<Rigidbody, RigidbodyInterpolation>> _savedInterpolations = new List<KeyValuePair<Rigidbody, RigidbodyInterpolation>>();
private Renderer[] _localRenderers;
private float _nextRenewTime;
private bool _pendingRenewal;
private Vector3 _renewPosition;
private Quaternion _renewRotation;
private Vector3 _renewVelocity;
private Vector3 _renewAngularVelocity;
public static Character ActiveWeedCharacter { get; private set; }
internal static bool CameraOverridePatchActive { get; set; }
public bool Active { get; private set; }
internal static void RegisterWeedCharacter(int characterViewId, GameObject weedRoot)
{
if (characterViewId > 0 && !((Object)(object)weedRoot == (Object)null))
{
WeedRootByCharacter[characterViewId] = weedRoot;
}
}
internal static bool TryGetWeedForCharacter(int characterViewId, out GameObject weedRoot)
{
if (WeedRootByCharacter.TryGetValue(characterViewId, out weedRoot) && (Object)(object)weedRoot != (Object)null && weedRoot.activeInHierarchy)
{
return true;
}
WeedRootByCharacter.Remove(characterViewId);
weedRoot = null;
return false;
}
internal static void UnregisterWeedCharacter(int characterViewId)
{
WeedRootByCharacter.Remove(characterViewId);
}
internal static void HideRemoteRider(Character character)
{
SetCharacterRenderersEnabled(character, enabled: false);
}
internal static void ShowRemoteRider(Character character)
{
SetCharacterRenderersEnabled(character, enabled: true);
}
private static void SetCharacterRenderersEnabled(Character character, bool enabled)
{
if ((Object)(object)character == (Object)null)
{
return;
}
try
{
Renderer[] componentsInChildren = ((Component)character).GetComponentsInChildren<Renderer>(true);
Renderer[] array = componentsInChildren;
foreach (Renderer val in array)
{
if ((Object)(object)val != (Object)null)
{
val.enabled = enabled;
}
}
}
catch (Exception ex)
{
LogError("TumbleweedController.SetCharacterRenderersEnabled", ex);
}
}
public bool IsValid()
{
if (!Active || (Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null)
{
return false;
}
if (_pendingRenewal)
{
return true;
}
if ((Object)(object)_weedRoot == (Object)null || (Object)(object)_weedRigidbody == (Object)null)
{
return false;
}
return !_character.data.dead && !_character.data.fullyPassedOut;
}
private static void LogInfo(string message)
{
ManualLogSource log = TumbleweedPlugin.Log;
if (log != null)
{
log.LogInfo((object)("[I'm a Tumbleweed] " + message));
}
}
private static void LogError(string entryPoint, Exception ex)
{
ManualLogSource log = TumbleweedPlugin.Log;
if (log != null)
{
log.LogError((object)("[I'm a Tumbleweed] " + entryPoint + ": " + ex));
}
}
public static bool IsLocalWeedCharacter(Character character)
{
if ((Object)(object)character == (Object)null || !character.IsLocal)
{
return false;
}
TumbleweedController component = ((Component)character).GetComponent<TumbleweedController>();
return (Object)(object)component != (Object)null && component.Active;
}
internal static void ForceExitForEndGame()
{
try
{
if ((Object)(object)ActiveWeedCharacter != (Object)null)
{
TumbleweedController component = ((Component)ActiveWeedCharacter).GetComponent<TumbleweedController>();
if ((Object)(object)component != (Object)null && component.Active)
{
component.ExitWeed();
return;
}
}
TumbleweedController[] array = Object.FindObjectsByType<TumbleweedController>((FindObjectsSortMode)0);
foreach (TumbleweedController tumbleweedController in array)
{
if ((Object)(object)tumbleweedController != (Object)null && tumbleweedController.Active)
{
tumbleweedController.ExitWeed();
break;
}
}
}
catch (Exception ex)
{
LogError("ForceExitForEndGame", ex);
}
}
public void EnterWeed(Character character)
{
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
_character = character;
_prevCenter = character.Center;
_cameraVelocity = Vector3.zero;
_cameraHasSmoothedPosition = false;
_nextJumpAllowedTime = 0f;
_activeSeconds = 0f;
_nextHudSearchTime = 0f;
_pendingRenewal = false;
float renewInterval = GetRenewInterval();
_nextRenewTime = ((renewInterval > 0f) ? (Time.time + renewInterval) : float.MaxValue);
Active = true;
ActiveWeedCharacter = character;
((Behaviour)this).enabled = true;
SetWeedNoClip(enable: true);
BuildWeedVisual();
RegisterWeedCharacter(((MonoBehaviourPun)_character).photonView.ViewID, _weedRoot);
HideLocalRenderers();
HideHud();
LogInfo("Entered tumbleweed form.");
}
public void ExitWeed()
{
if (Active || !((Object)(object)_weedRoot == (Object)null))
{
Active = false;
ActiveWeedCharacter = null;
((Behaviour)this).enabled = false;
PositionCharacterForExit();
SetWeedNoClip(enable: false);
DestroyWeedVisual();
ForceShowLocalRenderers();
_localRenderers = null;
RestoreHud();
LogInfo("Exited tumbleweed form.");
}
}
private void Update()
{
//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
if (!Active || (Object)(object)_character == (Object)null)
{
return;
}
try
{
_activeSeconds += Time.deltaTime;
if (TumbleweedPlugin.AutoRevertSeconds != null && TumbleweedPlugin.AutoRevertSeconds.Value > 0f && _activeSeconds >= TumbleweedPlugin.AutoRevertSeconds.Value)
{
LogInfo("Tumbleweed form auto-reverted after " + TumbleweedPlugin.AutoRevertSeconds.Value.ToString("0.#") + " seconds.");
ExitWeed();
return;
}
ClearNonMovementInput();
KeepPlayerAlive();
MaybeRenewWeed();
UpdateWeedVisual();
KeepLocalRenderersHidden();
HideHud();
if ((Object)(object)_weedRoot != (Object)null && _weedRoot.transform.position.y < -80f)
{
LogInfo("Tumbleweed fell out of the world; exiting form.");
ExitWeed();
}
}
catch (Exception ex)
{
LogError("TumbleweedController.Update", ex);
}
}
private void FixedUpdate()
{
if (!Active || (Object)(object)_character == (Object)null)
{
return;
}
try
{
FollowWeedWithCharacterRoot();
DriveWeedPhysics();
}
catch (Exception ex)
{
LogError("TumbleweedController.FixedUpdate", ex);
}
}
private void LateUpdate()
{
if (!Active || (Object)(object)_character == (Object)null)
{
return;
}
try
{
SyncCharacterData();
if (!CameraOverridePatchActive)
{
RefreshCamera();
}
}
catch (Exception ex)
{
LogError("TumbleweedController.LateUpdate", ex);
}
}
private void OnDestroy()
{
if (Active)
{
Active = false;
ActiveWeedCharacter = null;
SetWeedNoClip(enable: false);
DestroyWeedVisual();
ForceShowLocalRenderers();
RestoreHud();
}
}
private void DriveWeedPhysics()
{
//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_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_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_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_0036: Unknown result type (might be due to invalid IL or missing references)
//IL_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_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_007d: Unknown result type (might be due to invalid IL or missing references)
//IL_0089: Unknown result type (might be due to invalid IL or missing references)
//IL_0141: Unknown result type (might be due to invalid IL or missing references)
//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_014d: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_017c: Unknown result type (might be due to invalid IL or missing references)
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: 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_01ad: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_weedRigidbody == (Object)null)
{
return;
}
Vector3 flatLookDirection = GetFlatLookDirection();
Vector2 movementInput = GetMovementInput();
Vector3 val = Vector3.Cross(Vector3.up, flatLookDirection);
Vector3 normalized = ((Vector3)(ref val)).normalized;
Vector3 val2 = flatLookDirection * movementInput.y + normalized * movementInput.x;
if (((Vector3)(ref val2)).sqrMagnitude > 1f)
{
((Vector3)(ref val2)).Normalize();
}
float num = (((int)TumbleweedPlugin.SprintKey.Value != 0 && Input.GetKey(TumbleweedPlugin.SprintKey.Value)) ? Mathf.Max(1f, TumbleweedPlugin.SprintMultiplier.Value) : 1f);
float num2 = TumbleweedPlugin.MovementForce.Value * num;
float num3 = TumbleweedPlugin.MaxSpeed.Value * num;
if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f)
{
Vector3 linearVelocity = _weedRigidbody.linearVelocity;
Vector3 val3 = default(Vector3);
((Vector3)(ref val3))..ctor(linearVelocity.x, 0f, linearVelocity.z);
if (((Vector3)(ref val3)).magnitude < num3)
{
_weedRigidbody.AddForce(val2 * num2, (ForceMode)5);
}
}
if ((int)TumbleweedPlugin.JumpKey.Value != 0 && Input.GetKeyDown(TumbleweedPlugin.JumpKey.Value) && Time.time >= _nextJumpAllowedTime && IsWeedGrounded())
{
Vector3 linearVelocity2 = _weedRigidbody.linearVelocity;
_weedRigidbody.linearVelocity = new Vector3(linearVelocity2.x, Mathf.Max(linearVelocity2.y, TumbleweedPlugin.JumpSpeed.Value), linearVelocity2.z);
_nextJumpAllowedTime = Time.time + 0.25f;
}
}
private bool IsWeedGrounded()
{
//IL_0028: 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)
if ((Object)(object)_weedRoot == (Object)null)
{
return false;
}
float weedWorldRadius = GetWeedWorldRadius();
return Physics.Raycast(_weedRoot.transform.position, Vector3.down, weedWorldRadius + 0.35f, -5, (QueryTriggerInteraction)1);
}
private float GetWeedWorldRadius()
{
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: 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)
try
{
if ((Object)(object)_weedCollider != (Object)null)
{
Bounds bounds = ((Collider)_weedCollider).bounds;
return Mathf.Max(0.1f, ((Bounds)(ref bounds)).extents.x);
}
}
catch
{
}
return 0.5f;
}
private Vector3 GetFlatLookDirection()
{
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_002b: 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_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_0037: 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_0068: Unknown result type (might be due to invalid IL or missing references)
//IL_006d: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: 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_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)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00c3: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = (((Object)(object)_character.data != (Object)null) ? _character.data.lookDirection_Flat : Vector3.zero);
val = Vector3.ProjectOnPlane(val, Vector3.up);
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null)
{
val = Vector3.ProjectOnPlane(((Component)Camera.main).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.ProjectOnPlane(((Component)this).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.forward;
}
return ((Vector3)(ref val)).normalized;
}
private void ClearNonMovementInput()
{
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null))
{
_character.input.jumpWasPressed = false;
_character.input.jumpIsPressed = false;
_character.input.sprintIsPressed = false;
_character.input.sprintWasPressed = false;
_character.input.sprintToggleWasPressed = false;
_character.input.usePrimaryWasPressed = false;
_character.input.usePrimaryIsPressed = false;
_character.input.useSecondaryWasPressed = false;
_character.input.useSecondaryIsPressed = false;
_character.input.crouchWasPressed = false;
_character.input.crouchIsPressed = false;
_character.input.crouchToggleWasPressed = false;
_character.input.dropWasPressed = false;
_character.input.dropIsPressed = false;
_character.input.interactWasPressed = false;
_character.input.interactIsPressed = false;
}
}
private void KeepPlayerAlive()
{
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null))
{
_character.data.dead = false;
_character.data.zombified = false;
_character.data.passedOut = false;
_character.data.fullyPassedOut = false;
_character.data.fallSeconds = 0f;
_character.data.isSprinting = false;
}
}
private Vector2 GetMovementInput()
{
//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_0043: 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_0079: 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_0028: 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_007d: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_character == (Object)null || (Object)(object)_character.input == (Object)null)
{
return Vector2.zero;
}
Vector2 movementInput = _character.input.movementInput;
movementInput.x = Mathf.Clamp(movementInput.x, -1f, 1f);
movementInput.y = Mathf.Clamp(movementInput.y, -1f, 1f);
return movementInput;
}
private void SyncCharacterData()
{
//IL_0033: 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_0052: 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_006d: 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_0072: 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_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: 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_00c1: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null))
{
Vector3 center = _character.Center;
Vector3 avarageVelocity = ((((Vector3)(ref _prevCenter)).sqrMagnitude > 0f) ? ((center - _prevCenter) / Mathf.Max(Time.deltaTime, 0.0001f)) : Vector3.zero);
_prevCenter = center;
_character.data.avarageLastFrameVelocity = _character.data.avarageVelocity;
_character.data.avarageVelocity = avarageVelocity;
_character.data.worldMovementInput = (_character.data.worldMovementInput_Grounded = Vector3.zero);
_character.data.sinceGrounded = Mathf.Min(_character.data.sinceGrounded, 0.1f);
}
}
private void FollowWeedWithCharacterRoot()
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: 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)
if (!((Object)(object)_weedRoot == (Object)null) && !((Object)(object)_character == (Object)null))
{
Vector3 position = _weedRoot.transform.position;
Vector3 center = _character.Center;
Transform transform = ((Component)this).transform;
transform.position += position - center;
}
}
private unsafe void PositionCharacterForExit()
{
//IL_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: 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)
if ((Object)(object)_character == (Object)null)
{
return;
}
try
{
Vector3 start = (((Object)(object)_weedRoot != (Object)null) ? _weedRoot.transform.position : ((Component)this).transform.position);
Vector3 position = FindSafeExitPosition(start);
((Component)this).transform.position = position;
LogInfo("Repositioned player to safe exit spot: " + ((object)(*(Vector3*)(&position))/*cast due to .constrained prefix*/).ToString());
}
catch (Exception ex)
{
LogError("TumbleweedController.PositionCharacterForExit", ex);
}
}
private Vector3 FindSafeExitPosition(Vector3 start)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0016: 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_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_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_00c0: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = start + Vector3.up * 20f;
RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 80f, -5, (QueryTriggerInteraction)1);
Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance));
for (int num = 0; num < array.Length; num++)
{
if (!((Object)(object)((RaycastHit)(ref array[num])).collider == (Object)null) && (!((Object)(object)_weedRoot != (Object)null) || !((Component)((RaycastHit)(ref array[num])).collider).transform.IsChildOf(_weedRoot.transform)))
{
return ((RaycastHit)(ref array[num])).point + Vector3.up * 1f;
}
}
return start + Vector3.up * 1f;
}
private void SetWeedNoClip(bool enable)
{
if ((Object)(object)_character == (Object)null || _character.refs == null || (Object)(object)_character.refs.ragdoll == (Object)null)
{
return;
}
CharacterRagdoll ragdoll = _character.refs.ragdoll;
try
{
if (enable && (Object)(object)_character.data != (Object)null && _character.data.IsCarryingCharacter)
{
AccessTools.Method(typeof(Character), "DropCarriedCharacter", (Type[])null, (Type[])null)?.Invoke(_character, new object[1] { true });
}
ragdoll.ToggleKinematic(enable);
ragdoll.ToggleCollision(!enable);
if (ragdoll.partList != null)
{
foreach (Bodypart part in ragdoll.partList)
{
Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null);
if (!((Object)(object)val == (Object)null))
{
val.useGravity = !enable;
}
}
}
SetRagdollInterpolation(enable);
if (!enable)
{
ragdoll.HaltBodyVelocity(false);
}
}
catch (Exception ex)
{
LogError("TumbleweedController.SetWeedNoClip(" + enable + ")", ex);
}
}
private void SetRagdollInterpolation(bool weedEnabled)
{
//IL_0096: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Invalid comparison between Unknown and I4
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
CharacterRagdoll val = (((Object)(object)_character != (Object)null && _character.refs != null) ? _character.refs.ragdoll : null);
if ((Object)(object)val == (Object)null || val.partList == null)
{
return;
}
if (!weedEnabled)
{
for (int i = 0; i < _savedInterpolations.Count; i++)
{
Rigidbody key = _savedInterpolations[i].Key;
if ((Object)(object)key != (Object)null)
{
try
{
key.interpolation = _savedInterpolations[i].Value;
}
catch
{
}
}
}
_savedInterpolations.Clear();
return;
}
_savedInterpolations.Clear();
foreach (Bodypart part in val.partList)
{
Rigidbody val2 = (((Object)(object)part != (Object)null) ? part.Rig : null);
if ((Object)(object)val2 == (Object)null)
{
continue;
}
try
{
if ((int)val2.interpolation > 0)
{
_savedInterpolations.Add(new KeyValuePair<Rigidbody, RigidbodyInterpolation>(val2, val2.interpolation));
val2.interpolation = (RigidbodyInterpolation)0;
}
}
catch
{
}
}
}
private void HideLocalRenderers()
{
if ((Object)(object)_character == (Object)null)
{
return;
}
try
{
_localRenderers = ((Component)_character).GetComponentsInChildren<Renderer>(true);
Renderer[] localRenderers = _localRenderers;
foreach (Renderer val in localRenderers)
{
if ((Object)(object)val != (Object)null)
{
val.enabled = false;
}
}
}
catch (Exception ex)
{
LogError("TumbleweedController.HideLocalRenderers", ex);
}
}
private void KeepLocalRenderersHidden()
{
if (_localRenderers == null)
{
return;
}
try
{
Renderer[] localRenderers = _localRenderers;
foreach (Renderer val in localRenderers)
{
if ((Object)(object)val != (Object)null && val.enabled)
{
val.enabled = false;
}
}
}
catch (Exception ex)
{
LogError("TumbleweedController.KeepLocalRenderersHidden", ex);
}
}
private void ForceShowLocalRenderers()
{
if ((Object)(object)_character == (Object)null)
{
return;
}
try
{
Renderer[] componentsInChildren = ((Component)_character).GetComponentsInChildren<Renderer>(true);
Renderer[] array = componentsInChildren;
foreach (Renderer val in array)
{
if ((Object)(object)val != (Object)null)
{
val.enabled = true;
}
}
}
catch (Exception ex)
{
LogError("TumbleweedController.ForceShowLocalRenderers", ex);
}
}
private void HideHud()
{
if (_hiddenHudStates.Count < 2 && !(Time.unscaledTime < _nextHudSearchTime))
{
_nextHudSearchTime = Time.unscaledTime + 0.5f;
TryHideCanvas("Canvas_HUD");
TryHideCanvas("Canvas_Names");
}
}
private void TryHideCanvas(string canvasName)
{
GameObject val = GameObject.Find(canvasName);
if (!((Object)(object)val == (Object)null) && !_hiddenHudStates.ContainsKey(val))
{
_hiddenHudStates[val] = val.activeSelf;
if (val.activeSelf)
{
val.SetActive(false);
}
}
}
private void RestoreHud()
{
if (_hiddenHudStates.Count == 0)
{
return;
}
foreach (KeyValuePair<GameObject, bool> hiddenHudState in _hiddenHudStates)
{
if ((Object)(object)hiddenHudState.Key != (Object)null)
{
hiddenHudState.Key.SetActive(hiddenHudState.Value);
}
}
_hiddenHudStates.Clear();
}
private void BuildWeedVisual()
{
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
Vector3 position = (((Object)(object)_character != (Object)null) ? _character.Center : ((Component)this).transform.position);
BuildWeedVisual(position, Quaternion.identity);
}
private void BuildWeedVisual(Vector3 position, Quaternion rotation)
{
//IL_0095: 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)
//IL_0087: 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_00bd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_weedRoot != (Object)null || (Object)(object)_character == (Object)null)
{
return;
}
try
{
GameObject val = Resources.Load<GameObject>("tumbleweed");
if ((Object)(object)val == (Object)null)
{
LogInfo("Resources.Load(\"tumbleweed\") returned null; no tumbleweed visual will be shown.");
return;
}
if (PhotonNetwork.InRoom && (Object)(object)((MonoBehaviourPun)_character).photonView != (Object)null && ((MonoBehaviourPun)_character).photonView.ViewID > 0)
{
BuildNetworkedWeed(position, rotation);
}
else
{
BuildLocalWeed(val, position, rotation);
}
if ((Object)(object)_weedRoot != (Object)null)
{
Transform transform = _weedRoot.transform;
transform.localScale *= Mathf.Max(0.05f, TumbleweedPlugin.WeedScale.Value);
DisableVanillaLifetime(_weedRoot);
}
}
catch (Exception ex)
{
LogError("TumbleweedController.BuildWeedVisual", ex);
DestroyWeedVisual();
}
}
private void BuildNetworkedWeed(Vector3 position, Quaternion rotation)
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
GameObject val = PhotonNetwork.Instantiate("tumbleweed", position, rotation, (byte)0, new object[3]
{
"ImTumbleweed.Visual",
((MonoBehaviourPun)_character).photonView.ViewID,
TumbleweedPlugin.WeedScale.Value
});
((Object)val).name = "ImTumbleweedNetworked";
_weedRoot = val;
_weedIsNetworked = true;
_weedRigidbody = val.GetComponent<Rigidbody>();
_weedCollider = val.GetComponent<SphereCollider>();
TumbleWeed component = val.GetComponent<TumbleWeed>();
if ((Object)(object)component != (Object)null)
{
component.testFullPower = false;
}
IgnoreCollisionWithCharacter(val, _character);
LogInfo("Spawned networked tumbleweed visual with vanilla tumbleweed prefab.");
}
private void BuildLocalWeed(GameObject prefab, Vector3 position, Quaternion rotation)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
GameObject val = Object.Instantiate<GameObject>(prefab, position, rotation);
((Object)val).name = "ImTumbleweedLocal";
_weedRoot = val;
_weedIsNetworked = false;
_weedRigidbody = val.GetComponent<Rigidbody>();
_weedCollider = val.GetComponent<SphereCollider>();
TumbleWeed component = val.GetComponent<TumbleWeed>();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
}
LogInfo("Spawned local-only tumbleweed visual (offline / single-player).");
}
private float GetRenewInterval()
{
if (TumbleweedPlugin.WeedRenewInterval == null)
{
return 0f;
}
float value = TumbleweedPlugin.WeedRenewInterval.Value;
return (value <= 0f) ? 0f : Mathf.Clamp(value, 1f, 14f);
}
private void MaybeRenewWeed()
{
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: 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_012a: Unknown result type (might be due to invalid IL or missing references)
//IL_012f: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Unknown result type (might be due to invalid IL or missing references)
//IL_0145: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_0167: Unknown result type (might be due to invalid IL or missing references)
float renewInterval = GetRenewInterval();
if (renewInterval <= 0f || !PhotonNetwork.InRoom)
{
return;
}
if (_pendingRenewal)
{
_pendingRenewal = false;
try
{
BuildWeedVisual(_renewPosition, _renewRotation);
if ((Object)(object)_weedRigidbody != (Object)null)
{
_weedRigidbody.linearVelocity = _renewVelocity;
_weedRigidbody.angularVelocity = _renewAngularVelocity;
}
RegisterWeedCharacter(((MonoBehaviourPun)_character).photonView.ViewID, _weedRoot);
return;
}
catch (Exception ex)
{
LogError("TumbleweedController.RenewWeed(rebuild)", ex);
return;
}
}
if (!_weedIsNetworked || Time.time < _nextRenewTime)
{
return;
}
_nextRenewTime = Time.time + renewInterval;
if ((Object)(object)_weedRoot == (Object)null || (Object)(object)_weedRigidbody == (Object)null)
{
return;
}
try
{
_renewPosition = _weedRoot.transform.position;
_renewRotation = _weedRoot.transform.rotation;
_renewVelocity = _weedRigidbody.linearVelocity;
_renewAngularVelocity = _weedRigidbody.angularVelocity;
LogInfo("Renewing networked tumbleweed (keeps it alive on unmodded clients).");
DestroyWeedVisual();
_pendingRenewal = true;
}
catch (Exception ex2)
{
LogError("TumbleweedController.RenewWeed(destroy)", ex2);
}
}
internal static void DisableVanillaLifetime(GameObject weedRoot)
{
RemoveAfterSeconds component = weedRoot.GetComponent<RemoveAfterSeconds>();
if ((Object)(object)component != (Object)null)
{
((Behaviour)component).enabled = false;
}
ScaleIn component2 = weedRoot.GetComponent<ScaleIn>();
if ((Object)(object)component2 != (Object)null)
{
((Behaviour)component2).enabled = false;
}
}
internal static void IgnoreCollisionWithCharacter(GameObject weedRoot, Character character)
{
if ((Object)(object)weedRoot == (Object)null || (Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.ragdoll == (Object)null)
{
return;
}
Collider[] componentsInChildren = weedRoot.GetComponentsInChildren<Collider>(true);
if (componentsInChildren.Length == 0)
{
return;
}
foreach (Bodypart part in character.refs.ragdoll.partList)
{
if ((Object)(object)part == (Object)null)
{
continue;
}
Collider[] componentsInChildren2 = ((Component)part).GetComponentsInChildren<Collider>(true);
Collider[] array = componentsInChildren;
foreach (Collider val in array)
{
Collider[] array2 = componentsInChildren2;
foreach (Collider val2 in array2)
{
if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && val.enabled && val2.enabled)
{
try
{
Physics.IgnoreCollision(val, val2, true);
}
catch
{
}
}
}
}
}
}
private void UpdateWeedVisual()
{
if (!((Object)(object)_weedRoot == (Object)null))
{
Renderer component = _weedRoot.GetComponent<Renderer>();
if ((Object)(object)component != (Object)null && component.enabled != TumbleweedPlugin.ShowWeedVisual.Value)
{
component.enabled = TumbleweedPlugin.ShowWeedVisual.Value;
}
}
}
private void DestroyWeedVisual()
{
if ((Object)(object)_weedRoot != (Object)null)
{
if (_weedIsNetworked && PhotonNetwork.InRoom)
{
try
{
PhotonNetwork.Destroy(_weedRoot);
}
catch
{
}
}
else
{
Object.Destroy((Object)(object)_weedRoot);
}
}
_weedRoot = null;
_weedRigidbody = null;
_weedCollider = null;
_weedIsNetworked = false;
if ((Object)(object)_character != (Object)null && (Object)(object)((MonoBehaviourPun)_character).photonView != (Object)null)
{
UnregisterWeedCharacter(((MonoBehaviourPun)_character).photonView.ViewID);
}
}
private Vector3 GetWeedCenter()
{
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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_002f: Unknown result type (might be due to invalid IL or missing references)
return ((Object)(object)_weedRoot != (Object)null) ? _weedRoot.transform.position : _character.Center;
}
internal static void ApplyCameraOverrideForLocalWeed()
{
Character activeWeedCharacter = ActiveWeedCharacter;
if (!((Object)(object)activeWeedCharacter == (Object)null))
{
TumbleweedController component = ((Component)activeWeedCharacter).GetComponent<TumbleweedController>();
if ((Object)(object)component != (Object)null && component.IsValid())
{
component.RefreshCamera();
}
}
}
private void RefreshCamera()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: 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_0054: 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_0059: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0072: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_0095: 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_00a0: Unknown result type (might be due to invalid IL or missing references)
//IL_00a5: 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_00a8: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
//IL_010c: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0129: Unknown result type (might be due to invalid IL or missing references)
//IL_012e: Unknown result type (might be due to invalid IL or missing references)
//IL_0130: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0156: Unknown result type (might be due to invalid IL or missing references)
//IL_015a: Unknown result type (might be due to invalid IL or missing references)
//IL_015f: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: 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_00ee: Unknown result type (might be due to invalid IL or missing references)
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
//IL_016c: Unknown result type (might be due to invalid IL or missing references)
//IL_0172: Unknown result type (might be due to invalid IL or missing references)
try
{
Camera main = Camera.main;
if (!((Object)(object)main == (Object)null))
{
Vector3 weedCenter = GetWeedCenter();
Vector3 cameraForward = GetCameraForward(_character);
Vector3 val = (((Object)(object)_character.data != (Object)null) ? ((Vector3)(ref _character.data.lookDirection)).normalized : cameraForward);
float num = Mathf.Clamp(val.y, -0.35f, 0.65f);
Vector3 lookTarget = weedCenter + Vector3.up * (GetCameraHeight() * 0.5f + num * 2f) + cameraForward * 3f;
Vector3 val2 = weedCenter + Vector3.up * (GetCameraHeight() + 0.5f) - cameraForward * GetCameraDistance();
if (!_cameraHasSmoothedPosition)
{
_cameraSmoothedPosition = val2;
_cameraSmoothedRotation = GetCameraRotation(_cameraSmoothedPosition, lookTarget);
_cameraHasSmoothedPosition = true;
}
else
{
_cameraSmoothedPosition = Vector3.SmoothDamp(_cameraSmoothedPosition, val2, ref _cameraVelocity, 0.08f);
Quaternion cameraRotation = GetCameraRotation(_cameraSmoothedPosition, lookTarget);
float num2 = 1f - Mathf.Exp(-12f * Time.deltaTime);
_cameraSmoothedRotation = Quaternion.Slerp(_cameraSmoothedRotation, cameraRotation, num2);
}
((Component)main).transform.SetPositionAndRotation(_cameraSmoothedPosition, _cameraSmoothedRotation);
main.fieldOfView = Mathf.Lerp(main.fieldOfView, GetCameraFov(), Time.deltaTime * 4f);
}
}
catch (Exception ex)
{
LogError("TumbleweedController.RefreshCamera", ex);
}
}
private static float GetCameraDistance()
{
float num = ((TumbleweedPlugin.CameraDistance != null) ? TumbleweedPlugin.CameraDistance.Value : 12f);
return Mathf.Clamp(num, 6f, 30f);
}
private static float GetCameraHeight()
{
float num = ((TumbleweedPlugin.CameraHeight != null) ? TumbleweedPlugin.CameraHeight.Value : 4f);
return Mathf.Clamp(num, 1f, 14f);
}
private static float GetCameraFov()
{
float num = ((TumbleweedPlugin.CameraFov != null) ? TumbleweedPlugin.CameraFov.Value : 80f);
return Mathf.Clamp(num, 60f, 110f);
}
private static Vector3 GetCameraForward(Character character)
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_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_002d: 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_0063: 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)
//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_008d: 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_00b0: 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_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_00b9: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = (((Object)(object)character.data != (Object)null) ? character.data.lookDirection_Flat : Vector3.zero);
val = Vector3.ProjectOnPlane(val, Vector3.up);
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null)
{
val = Vector3.ProjectOnPlane(((Component)Camera.main).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.ProjectOnPlane(((Component)character).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.forward;
}
return ((Vector3)(ref val)).normalized;
}
private static Quaternion GetCameraRotation(Vector3 cameraPosition, Vector3 lookTarget)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
//IL_0034: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = lookTarget - cameraPosition;
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.forward;
}
return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
}
}
[HarmonyPatch]
public static class TumbleweedHarmonyPatches
{
private sealed class WeedState
{
public PhotonView View;
public bool LifetimeDisabled;
public bool ScaleApplied;
public bool CollisionIgnored;
public Character OwnerCharacter;
}
private static readonly ConditionalWeakTable<TumbleWeed, WeedState> WeedStates = new ConditionalWeakTable<TumbleWeed, WeedState>();
private static Vector3 _prefabScale;
private static bool _prefabScaleLoaded;
private static readonly HashSet<int> _hiddenRiderViewIds = new HashSet<int>();
private static bool IsWeed(Character character)
{
return TumbleweedController.IsLocalWeedCharacter(character);
}
[HarmonyPatch(typeof(TumbleWeed), "FixedUpdate")]
[HarmonyPrefix]
private static bool TumbleWeedFixedUpdatePrefix(TumbleWeed __instance)
{
WeedState orCreateValue = WeedStates.GetOrCreateValue(__instance);
if ((Object)(object)orCreateValue.View == (Object)null)
{
orCreateValue.View = ((Component)__instance).GetComponent<PhotonView>();
}
if (!IsOurWeed(orCreateValue.View))
{
return true;
}
MaintainOurWeed(__instance, orCreateValue);
return false;
}
private static bool IsOurWeed(PhotonView view)
{
object[] array = (((Object)(object)view != (Object)null) ? view.InstantiationData : null);
return array != null && array.Length != 0 && array[0] is string text && text == "ImTumbleweed.Visual";
}
private static void MaintainOurWeed(TumbleWeed weed, WeedState state)
{
if (!state.LifetimeDisabled)
{
TumbleweedController.DisableVanillaLifetime(((Component)weed).gameObject);
state.LifetimeDisabled = true;
}
if (!state.ScaleApplied)
{
ApplyOwnerScale(weed, state);
}
if (!state.CollisionIgnored)
{
TrySetupCollisionIgnore(weed, state);
}
if ((Object)(object)state.OwnerCharacter == (Object)null)
{
TryResolveOwnerCharacter(weed, state);
}
}
private static void TryResolveOwnerCharacter(TumbleWeed weed, WeedState state)
{
object[] array = (((Object)(object)state.View != (Object)null) ? state.View.InstantiationData : null);
if (array == null || array.Length < 2)
{
return;
}
object obj = array[1];
int num = default(int);
int num2;
if (obj is int)
{
num = (int)obj;
num2 = 1;
}
else
{
num2 = 0;
}
if (num2 != 0)
{
PhotonView val = PhotonView.Find(num);
Character val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Character>() : null);
if (!((Object)(object)val2 == (Object)null))
{
state.OwnerCharacter = val2;
TumbleweedController.RegisterWeedCharacter(((MonoBehaviourPun)val2).photonView.ViewID, ((Component)weed).gameObject);
}
}
}
private static void ApplyOwnerScale(TumbleWeed weed, WeedState state)
{
//IL_0058: 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)
object[] array = (((Object)(object)state.View != (Object)null) ? state.View.InstantiationData : null);
if (array != null && array.Length >= 3)
{
object obj = array[2];
float num = default(float);
int num2;
if (obj is float)
{
num = (float)obj;
num2 = 1;
}
else
{
num2 = 0;
}
if (num2 != 0)
{
((Component)weed).transform.localScale = GetPrefabScale() * Mathf.Max(0.05f, num);
state.ScaleApplied = true;
return;
}
}
state.ScaleApplied = true;
}
private static Vector3 GetPrefabScale()
{
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: 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)
if (!_prefabScaleLoaded)
{
_prefabScaleLoaded = true;
GameObject val = Resources.Load<GameObject>("tumbleweed");
_prefabScale = (((Object)(object)val != (Object)null) ? val.transform.localScale : Vector3.one);
}
return _prefabScale;
}
private static void TrySetupCollisionIgnore(TumbleWeed weed, WeedState state)
{
object[] array = (((Object)(object)state.View != (Object)null) ? state.View.InstantiationData : null);
if (array != null && array.Length >= 2)
{
object obj = array[1];
int num = default(int);
int num2;
if (obj is int)
{
num = (int)obj;
num2 = 1;
}
else
{
num2 = 0;
}
if (num2 != 0)
{
PhotonView val = PhotonView.Find(num);
Character val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Character>() : null);
if (!((Object)(object)val2 == (Object)null))
{
TumbleweedController.IgnoreCollisionWithCharacter(((Component)weed).gameObject, val2);
state.CollisionIgnored = true;
}
return;
}
}
state.CollisionIgnored = true;
}
internal static bool CharacterRpcDiePrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterRpcSetDeadPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterRpcPassOutPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterDieInstantlyPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterHandleDeathPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterWarpPlayerRpcPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterWarpPlayerPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterFallPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static bool CharacterRpcFallPrefix(Character __instance)
{
return !IsWeed(__instance);
}
internal static void CharacterRPCEndGamePrefix()
{
TumbleweedController.ForceExitForEndGame();
PruneInvalidAllCharactersEntries();
}
internal static void CharacterStatsWinPrefix(CharacterStats __instance)
{
EnsureCharacterStatsTimelinePopulated(__instance);
}
internal static void CharacterStatsGetFinalTimelineInfoPrefix(CharacterStats __instance)
{
EnsureCharacterStatsTimelinePopulated(__instance);
}
internal static void CharacterStatsGetFirstTimelineInfoPrefix(CharacterStats __instance)
{
EnsureCharacterStatsTimelinePopulated(__instance);
}
internal static void PeakHandlerEndCutscenePrefix()
{
TumbleweedController.ForceExitForEndGame();
}
private static void PruneInvalidAllCharactersEntries()
{
try
{
List<Character> allCharacters = Character.AllCharacters;
if (allCharacters != null && allCharacters.Count != 0)
{
allCharacters.RemoveAll((Character c) => (Object)(object)c == (Object)null || ((object)c).Equals((object?)null) || (Object)(object)((Component)c).gameObject == (Object)null || !((Component)c).gameObject.activeInHierarchy);
}
}
catch
{
}
}
private static void EnsureCharacterStatsTimelinePopulated(CharacterStats stats)
{
//IL_0041: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)stats == (Object)null)
{
return;
}
try
{
if (stats.timelineInfo != null && stats.timelineInfo.Count <= 0)
{
stats.timelineInfo.Add(new TimelineInfo((BiomeType)5, 1200f, 0f, (TimelineNote)0));
}
}
catch
{
}
}
internal static void GameOverHandlerBeginAirportLoadRPCPrefix()
{
TumbleweedController.ForceExitForEndGame();
}
internal static void EndScreenReturnToAirportPrefix()
{
TumbleweedController.ForceExitForEndGame();
}
internal static void MainCameraMovementLateUpdatePostfix()
{
TumbleweedController.ApplyCameraOverrideForLocalWeed();
}
[HarmonyPatch(typeof(CharacterSyncer), "GetDataToWrite")]
[HarmonyPostfix]
private static void CharacterSyncerGetDataToWritePostfix(CharacterSyncer __instance, ref CharacterSyncData __result)
{
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: 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_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//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)
Character component = ((Component)__instance).GetComponent<Character>();
if (!((Object)(object)component == (Object)null) && TumbleweedController.IsLocalWeedCharacter(component))
{
Vector3 val = float3.op_Implicit(__result.hipLocation);
__result.hipLocation = new float3(val.x, val.y - 30f, val.z);
__result.averageVelocity = float3.zero;
}
}
[HarmonyPatch(typeof(CharacterSyncer), "InterpolateRigPositions")]
[HarmonyPrefix]
private static bool CharacterSyncerInterpolatePrefix(CharacterSyncer __instance)
{
Character component = ((Component)__instance).GetComponent<Character>();
if ((Object)(object)component == (Object)null || component.IsLocal)
{
return true;
}
if ((Object)(object)((MonoBehaviourPun)component).photonView != (Object)null)
{
int viewID = ((MonoBehaviourPun)component).photonView.ViewID;
if (TumbleweedController.TryGetWeedForCharacter(viewID, out var _))
{
TumbleweedController.HideRemoteRider(component);
_hiddenRiderViewIds.Add(viewID);
return false;
}
if (_hiddenRiderViewIds.Remove(viewID))
{
TumbleweedController.ShowRemoteRider(component);
}
}
return true;
}
}
}