Decompiled source of PEAK Transform v0.9.10
plugins/Thanks.Transform.dll
Decompiled 2 weeks ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using ImCritter; using ImGhost; using ImScoutmaster; using ImTornado; using ImTumbleweed; using ImZombie; using Microsoft.CodeAnalysis; using Peak; using Photon.Pun; using Photon.Realtime; using TMPro; using Transform.Core; using Transform.Statue; using Unity.Mathematics; using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.SceneManagement; using Zorro.Core; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("Thanks.Transform")] [assembly: AssemblyDescription("Unified transformation mod for PEAK: mushroom zombie, scoutmaster, ghost, tumbleweed, tornado and petrified scout statue forms with an in-game menu.")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("Thanks")] [assembly: AssemblyProduct("Thanks.Transform")] [assembly: AssemblyCopyright("Copyright © Thanks 2026")] [assembly: AssemblyTrademark("")] [assembly: AssemblyFileVersion("0.9.10")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("0.9.10.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; } } } internal static class TransformState { internal static bool MenuOpen; internal static bool AnyFormActive; } namespace ImCritter { internal static class CritterPlugin { public const string Id = "com.github.Thanks.Transform.Critter"; public const string Name = "Critter Forms"; public const string Version = "0.9.10"; private const float OldFrogJumpPowerDefault = 1.6f; private const float PreviousFrogJumpPowerDefault = 0.85f; private const float NewFrogJumpPowerDefault = 1.2f; internal const string ModPlayerProperty = "ImCritter.Mod"; internal static ManualLogSource Log; private static Harmony _harmony; private static CritterController _controller; private static bool _switching; private static bool _initialized; private static bool _advertised; internal static ConfigEntry<bool> UnmoddedRoomSupport; internal static ConfigEntry<KeyCode> JumpKey; internal static ConfigEntry<KeyCode> AttackKey; private static ConfigEntry<float>[] _movementForce = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _sprintMultiplier = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _maxSpeed = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _jumpSpeed = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _jumpPower = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _attackCooldown = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _cameraDistance = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _cameraHeight = new ConfigEntry<float>[6]; private static ConfigEntry<float>[] _cameraFov = new ConfigEntry<float>[6]; internal static bool IsActive { get { if ((Object)(object)_controller != (Object)null) { return _controller.Active; } return false; } } internal static CritterKind ActiveKind { get { if (!((Object)(object)_controller != (Object)null) || !_controller.Active) { return (CritterKind)(-1); } return _controller.Kind; } } internal static ConfigEntry<float> MovementForce(CritterKind kind) { return _movementForce[(int)kind]; } internal static ConfigEntry<float> SprintMultiplier(CritterKind kind) { return _sprintMultiplier[(int)kind]; } internal static ConfigEntry<float> MaxSpeed(CritterKind kind) { return _maxSpeed[(int)kind]; } internal static ConfigEntry<float> JumpSpeed(CritterKind kind) { return _jumpSpeed[(int)kind]; } internal static ConfigEntry<float> JumpPower(CritterKind kind) { return _jumpPower[(int)kind]; } internal static ConfigEntry<float> AttackCooldown(CritterKind kind) { return _attackCooldown[(int)kind]; } internal static ConfigEntry<float> CameraDistance(CritterKind kind) { return _cameraDistance[(int)kind]; } internal static ConfigEntry<float> CameraHeight(CritterKind kind) { return _cameraHeight[(int)kind]; } internal static ConfigEntry<float> CameraFov(CritterKind kind) { return _cameraFov[(int)kind]; } private static string Section(CritterKind kind) { return kind switch { CritterKind.Frog => "Frog", CritterKind.Beetle => "Beetle", CritterKind.Scorpion => "Scorpion", CritterKind.Coconut => "Coconut", CritterKind.Bomb => "Bomb", CritterKind.Cactus => "Cactus", _ => "Critter", }; } internal static void Initialize(ConfigFile config, ManualLogSource log) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown if (!_initialized) { _initialized = true; Log = log; _harmony = new Harmony("com.github.Thanks.Transform.Critter"); _harmony.PatchAll(typeof(CritterHarmonyPatches)); TryPatchFrogActionGuard(); TryPatchBombFlareGuard(); ConfigureOptionalEndgamePatches(); BindConfig(config); SceneManager.sceneLoaded += OnSceneLoaded; Log.LogInfo((object)"[Critter] Module loaded (frog, beetle, scorpion, coconut and bomb forms)."); } } private static void TryPatchFrogActionGuard() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(FrogTongue), "RPCA_FrogAction", (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Critter] RPCA_FrogAction not found; frog AI guard skipped."); } return; } bool flag = methodInfo.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(PhotonMessageInfo)); string text = (flag ? "FrogActionGuardWithInfo" : "FrogActionGuard"); MethodInfo methodInfo2 = AccessTools.Method(typeof(CritterHarmonyPatches), text, (Type[])null, (Type[])null); if (methodInfo2 == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Critter] Prefix " + text + " not found; frog AI guard skipped.")); } return; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)("[Critter] FrogActionGuard installed (" + text + ", PhotonMessageInfo=" + flag + ").")); } } catch (Exception ex) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("[Critter] FrogActionGuard patch failed: " + ex.Message)); } } } private static void TryPatchBombFlareGuard() { //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown try { MethodInfo methodInfo = AccessTools.Method(typeof(Dynamite), "SetFlareLitRPC", (Type[])null, (Type[])null); if (methodInfo == null) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Critter] Dynamite.SetFlareLitRPC not found; bomb fuse guard skipped."); } return; } bool flag = methodInfo.GetParameters().Any((ParameterInfo p) => p.ParameterType == typeof(PhotonMessageInfo)); string text = (flag ? "BombFlareLitGuardWithInfo" : "BombFlareLitGuard"); MethodInfo methodInfo2 = AccessTools.Method(typeof(CritterHarmonyPatches), text, (Type[])null, (Type[])null); if (methodInfo2 == null) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Critter] Prefix " + text + " not found; bomb fuse guard skipped.")); } return; } _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ManualLogSource log3 = Log; if (log3 != null) { log3.LogInfo((object)("[Critter] Bomb flare guard installed (" + text + ", PhotonMessageInfo=" + flag + ").")); } } catch (Exception ex) { ManualLogSource log4 = Log; if (log4 != null) { log4.LogWarning((object)("[Critter] Bomb flare guard patch failed: " + ex.Message)); } } } private static void ConfigureOptionalEndgamePatches() { PatchUtility.TryPatchOptionalMethod(_harmony, Log, "Critter", typeof(Character), "RPCEndGame", Type.EmptyTypes, typeof(CritterHarmonyPatches), "CharacterRPCEndGamePrefix", "Character.RPCEndGame()"); PatchUtility.TryPatchOptionalMethod(_harmony, Log, "Critter", typeof(GameOverHandler), "BeginAirportLoadRPC", Type.EmptyTypes, typeof(CritterHarmonyPatches), "GameOverHandlerBeginAirportLoadRPCPrefix", "GameOverHandler.BeginAirportLoadRPC()"); PatchUtility.TryPatchOptionalMethod(_harmony, Log, "Critter", typeof(EndScreen), "ReturnToAirport", Type.EmptyTypes, typeof(CritterHarmonyPatches), "EndScreenReturnToAirportPrefix", "EndScreen.ReturnToAirport()"); } private static void BindConfig(ConfigFile config) { BindKind(config, CritterKind.Frog, 14f, 14f, 12f, 9f, 6f, 1.2f); BindKind(config, CritterKind.Beetle, 18f, 4.5f, 7f, 6f, 7f, 1f, 1.35f); BindKind(config, CritterKind.Scorpion, 7.5f, 4.2f, 5f, 6f, 7f, 1f, 1.1f); BindKind(config, CritterKind.Coconut, 10f, 8f, 8f, 6f, 5f, 1f, 1.7f); BindKind(config, CritterKind.Bomb, 22f, 18f, 15.65f, 6f, 4f); BindKind(config, CritterKind.Cactus, 18f, 14f, 12f, 6f, 4.5f, 1f, 1.8f); MigrateCritterDefaults(); UnmoddedRoomSupport = config.Bind<bool>("Critter", "UnmoddedRoomSupport", true, "In rooms with unmodded players: pin the critter to the rider's real position on every remote client (vanilla Item.SetKinematicAndResetSyncData RPC) and broadcast the vanilla mob state (Mob.RPC_SyncMobState) so their copies stay controllable and never run the wildlife AI. The owner's local physics feel is unchanged. An unmodded MASTER client's own copy can still fire one AI tongue action — that cannot be patched remotely; the owner's client ignores it, and the pin pulls the visual back within a tick."); JumpKey = config.Bind<KeyCode>("Critter Controls", "JumpKey", (KeyCode)32, "Press to hop/jump while in a critter form (frog leap, beetle/scorpion hop). Bind to a controller button (JoystickButtonN) for gamepad play."); AttackKey = config.Bind<KeyCode>("Critter Controls", "AttackKey", (KeyCode)324, "Press to attack/charge while in a critter form (beetle ram, scorpion sting, coconut slam). Defaults to right mouse; bind to a controller button (JoystickButtonN) for gamepad."); } private static void MigrateCritterDefaults() { ConfigEntry<float> val = _jumpPower[0]; if (val != null && (Mathf.Abs(val.Value - 1.6f) <= 0.001f || Mathf.Abs(val.Value - 0.85f) <= 0.001f)) { val.Value = 1.2f; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Critter] Migrated frog JumpPower to 1.2 for direct launch-speed frog jumping."); } } MigrateIfDefault(_jumpSpeed[0], 6f, 12f, "Frog JumpSpeed"); MigrateIfDefault(_sprintMultiplier[1], 2f, 1.5f, "Beetle SprintMultiplier"); MigrateIfDefault(_movementForce[2], 14f, 10f, "Scorpion MovementForce"); MigrateIfDefault(_maxSpeed[2], 13f, 5.5f, "Scorpion MaxSpeed"); MigrateIfDefault(_jumpSpeed[2], 6f, 5f, "Scorpion JumpSpeed"); MigrateIfDefault(_sprintMultiplier[2], 2f, 1.15f, "Scorpion SprintMultiplier"); MigrateIfDefault(_movementForce[2], 10f, 7.5f, "Scorpion MovementForce"); MigrateIfDefault(_maxSpeed[2], 5.5f, 4.2f, "Scorpion MaxSpeed"); MigrateIfDefault(_sprintMultiplier[2], 1.15f, 1.1f, "Scorpion SprintMultiplier"); MigrateIfDefault(_maxSpeed[1], 5f, 4.5f, "Beetle MaxSpeed"); MigrateIfDefault(_sprintMultiplier[1], 1.5f, 1.35f, "Beetle SprintMultiplier"); MigrateIfDefault(_movementForce[4], 10f, 22f, "Bomb MovementForce"); MigrateIfDefault(_maxSpeed[4], 7f, 18f, "Bomb MaxSpeed"); MigrateIfDefault(_jumpSpeed[4], 7f, 15.65f, "Bomb JumpSpeed"); MigrateIfDefault(_sprintMultiplier[4], 1.7f, 2f, "Bomb SprintMultiplier"); } private static void MigrateIfDefault(ConfigEntry<float> entry, float oldDefault, float newDefault, string label) { if (entry != null && !(Mathf.Abs(entry.Value - oldDefault) > 0.001f)) { entry.Value = newDefault; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("[Critter] Migrated " + label + " to " + newDefault.ToString("0.##") + ".")); } } } private static void BindKind(ConfigFile config, CritterKind kind, float movementForce, float maxSpeed, float jumpSpeed, float cameraDistance, float cameraHeight, float jumpPower = 1f, float sprintMultiplier = 2f) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Expected O, but got Unknown //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Expected O, but got Unknown //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_013b: Expected O, but got Unknown //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Expected O, but got Unknown //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Expected O, but got Unknown //IL_01eb: Unknown result type (might be due to invalid IL or missing references) //IL_01f5: Expected O, but got Unknown string text = Section(kind); _movementForce[(int)kind] = config.Bind<float>(text, "MovementForce", movementForce, new ConfigDescription("How strongly WASD pushes the critter (acceleration, mass-independent). Not used by the frog (hop-only movement); beetle/scorpion use MaxSpeed for direct player control.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 60f), Array.Empty<object>())); _sprintMultiplier[(int)kind] = config.Bind<float>(text, "SprintMultiplier", sprintMultiplier, new ConfigDescription("Force/speed multiplier while holding the sprint key (drains the stamina bar).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>())); _maxSpeed[(int)kind] = config.Bind<float>(text, "MaxSpeed", maxSpeed, new ConfigDescription("Horizontal speed cap for WASD movement. For the frog this is the horizontal leap distance/speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 60f), Array.Empty<object>())); _jumpSpeed[(int)kind] = config.Bind<float>(text, "JumpSpeed", jumpSpeed, new ConfigDescription("Upward hop speed for Space. For the frog this is the direct vertical launch speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>())); _jumpPower[(int)kind] = config.Bind<float>(text, "JumpPower", jumpPower, new ConfigDescription("Multiplier on frog direct launch speeds or hop speed for beetle/scorpion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>())); _attackCooldown[(int)kind] = config.Bind<float>(text, "AttackCooldown", 1.5f, new ConfigDescription("Seconds between attacks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>())); _cameraDistance[(int)kind] = config.Bind<float>(text + " Camera", "Distance", cameraDistance, new ConfigDescription("Third-person critter camera distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 20f), Array.Empty<object>())); _cameraHeight[(int)kind] = config.Bind<float>(text + " Camera", "Height", cameraHeight, new ConfigDescription("Third-person critter camera height above the critter.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 10f), Array.Empty<object>())); _cameraFov[(int)kind] = config.Bind<float>(text + " Camera", "Fov", 78f, new ConfigDescription("Field of view while in this critter form.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 110f), Array.Empty<object>())); } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { try { if (IsActive) { ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Critter] Scene loaded while transformed; exiting critter form."); } ForceExit(); } } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Critter] Exit during scene load failed: " + ex.Message)); } } } internal static void Tick() { try { AdvertiseModPresence(); if ((Object)(object)_controller != (Object)null && _controller.Active && !_controller.IsValid()) { ForceExit(); } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[Critter] Module.Tick: " + ex)); } } } private static void AdvertiseModPresence() { ModPresence.Advertise("ImCritter.Mod", "0.9.10", ref _advertised); } internal static bool PlayerHasMod(Player player) { return ModPresence.PlayerHasMod(player, "ImCritter.Mod"); } internal static bool RoomHasUnmoddedPlayers() { return ModPresence.RoomHasUnmoddedPlayers("ImCritter.Mod"); } internal static IEnumerable<Player> UnmoddedRemotePlayers() { return ModPresence.UnmoddedRemotePlayers("ImCritter.Mod"); } internal static bool MasterHasMod() { return ModPresence.MasterHasMod("ImCritter.Mod"); } internal static void Shutdown() { SceneManager.sceneLoaded -= OnSceneLoaded; try { ForceExit(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Critter] Exit during cleanup failed: " + ex.Message)); } } try { Harmony harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex2) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)("[Critter] Harmony unpatch failed: " + ex2.Message)); } } } internal static bool CanEnter(Character character) { return CanTransform(character); } private static bool CanTransform(Character character) { if (IsActive) { return false; } if (!FormValidation.IsValid(Log, "Critter", FormValidation.ValidateTransformable(character))) { return false; } if (!PhotonNetwork.IsConnected && !PhotonNetwork.OfflineMode) { FormValidation.ReportFailure(Log, "Critter", "[Critter] Critter forms require a Photon room or offline mode."); return false; } return true; } internal static bool Enter(Character character, CritterKind kind) { if (kind == CritterKind.Cactus) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Critter] Cactus form is disabled."); } return false; } if (_switching) { return false; } if (!CanTransform(character)) { return false; } _switching = true; try { _controller = ((Component)character).gameObject.GetComponent<CritterController>(); if ((Object)(object)_controller == (Object)null) { _controller = ((Component)character).gameObject.AddComponent<CritterController>(); } return _controller.EnterCritter(character, kind); } catch (Exception ex) { ManualLogSource log2 = Log; if (log2 != null) { log2.LogError((object)("[Critter] Failed to enter " + kind.ToString() + " form:\n" + ex)); } _controller = null; return false; } finally { _switching = false; } } internal static void Exit() { _switching = true; try { _controller?.ExitCritter(); _controller = null; } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogError((object)("[Critter] Failed to exit critter form: " + ex)); } } finally { _switching = false; } } internal static void ForceExit() { if ((Object)(object)_controller == (Object)null) { return; } try { _controller.ExitCritter(); } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)("[Critter] ForceExit failed: " + ex.Message)); } } _controller = null; } } internal enum CritterKind { Frog, Beetle, Scorpion, Coconut, Bomb, Cactus } [DefaultExecutionOrder(600)] public sealed class CritterController : MonoBehaviour { private const float CameraLookAhead = 2.5f; private const float CameraSmoothTime = 0.08f; private const float CameraRotationSharpness = 12f; private const float DefaultCameraDistance = 6f; private const float DefaultCameraHeight = 2f; private const float DefaultCameraFov = 78f; private const float JumpCooldown = 0.3f; private const float GroundCheckExtra = 0.4f; private const float VoidExitHeight = -80f; private const float JumpStaminaCost = 0.08f; private const float MinSprintStamina = 0.02f; private const float AttackRange = 4f; private const float FrogTongueMinRange = 14f; private const float FrogTongueAimRadius = 3.4f; private const float FrogGroundedVelocityEpsilon = 0.08f; private const float AttackInputBufferSeconds = 0.2f; private const float FrogTongueReadyLength = 0.08f; private const float FrogEmptyLickSeconds = 0.35f; private const float BeetleMoveAcceleration = 18f; private const float ScorpionMoveAcceleration = 12f; private const float ItemRollTorque = 16f; private const float CoconutMaxChargeSeconds = 1.25f; private const float CoconutMinSlamSpeed = 10f; private const float CoconutMaxSlamSpeed = 28f; private const float CoconutSlamRange = 45f; private const float CoconutSlamUpBias = 0.16f; private const float FrogPullStopDistance = 2.6f; private const float BreakRestoreItemRestoreDelaySeconds = 1f; private const float RestoreHeightOffset = 0.6f; private const float ControlledLinearDamping = 0.05f; private const float ControlledAngularDamping = 8f; private const float MovementInputDeadzone = 0.01f; private const float FrogNormalHorizontalLaunchScale = 0.55f; private const float GroundedJumpBufferSeconds = 0.3f; private const float FrogJumpInputBufferSeconds = 0.25f; private static readonly FieldInfo FrogTargetCharacterField = AccessTools.Field(typeof(FrogTongue), "_targetCharacter"); private static readonly FieldInfo FrogTongueLengthField = AccessTools.Field(typeof(FrogTongue), "_tongueLength"); private static readonly FieldInfo FrogIsPullingField = AccessTools.Field(typeof(FrogTongue), "_isPulling"); private static readonly FieldInfo BreakableAlreadyBrokeField = AccessTools.Field(typeof(Breakable), "alreadyBroke"); private static readonly FieldInfo ItemLastThrownCharacterField = AccessTools.Field(typeof(Item), "lastThrownCharacter"); private static readonly FieldInfo ItemLastThrownTimeField = AccessTools.Field(typeof(Item), "lastThrownTime"); private static readonly MethodInfo ItemForceSyncForFramesMethod = AccessTools.Method(typeof(Item), "ForceSyncForFrames", (Type[])null, (Type[])null); private static readonly Dictionary<Type, bool> HasSetKinematicRpcByComponentType = new Dictionary<Type, bool>(); private const float UnmoddedSyncInterval = 0.1f; private const float IntegrityCheckInterval = 0.5f; private const float RespawnThrottleSeconds = 3f; private Character _character; private CritterKind _kind; private GameObject _critterRoot; private Rigidbody _critterRigidbody; private Mob _mob; private FrogTongue _frog; private Beetle _beetle; private Scorpion _scorpion; private Dynamite _dynamite; private Breakable _breakable; private Item _item; private PhotonView _critterView; private Vector3 _prevCenter; private Vector3 _cameraVelocity; private Vector3 _cameraSmoothedPosition; private Quaternion _cameraSmoothedRotation; private bool _cameraHasSmoothedPosition; private float _nextJumpAllowedTime; private float _nextAttackAllowedTime; private float _nextUnmoddedSyncTime; private float _nextIntegrityCheckTime; private float _nextRespawnTime; private float _lastGroundedTime = -10f; private float _frogJumpPressedTime = -10f; private float _attackPressedTime = -10f; private float _frogLocalLickBusyUntil; private float _coconutChargeStartTime = -1f; private float _itemRestoreAt = -1f; private Vector3 _lastKnownCritterPosition; private Vector3 _transformEntryRestorePosition; private Vector3 _lastSafeExitAnchor; private bool _coconutSlamQueued; private bool _bombIgnited; private bool _restoreAtTransformEntryOnExit; private bool _loggedControlledPhysics; private Vector3 _controlledFlatVelocity; private Renderer[] _localRenderers; private readonly Dictionary<Renderer, bool> _localRendererStates = new Dictionary<Renderer, bool>(); private readonly List<KeyValuePair<Rigidbody, RigidbodyInterpolation>> _savedInterpolations = new List<KeyValuePair<Rigidbody, RigidbodyInterpolation>>(); private static readonly Dictionary<int, CritterKind> KindByViewId = new Dictionary<int, CritterKind>(); internal const string NetworkVisualMarker = "ImCritter.Visual"; private static object _walkingMobState; public bool Active { get; private set; } internal CritterKind Kind => _kind; public static Character ActiveCritterCharacter { get; private set; } internal static bool IsCritterView(PhotonView view) { if ((Object)(object)view == (Object)null) { return false; } if (KindByViewId.ContainsKey(view.ViewID)) { return true; } object[] instantiationData = view.InstantiationData; if (instantiationData != null && instantiationData.Length != 0 && instantiationData[0] is string text) { return text == "ImCritter.Visual"; } return false; } internal static bool TryGetKind(PhotonView view, out CritterKind kind) { kind = CritterKind.Frog; if ((Object)(object)view == (Object)null) { return false; } if (KindByViewId.TryGetValue(view.ViewID, out kind)) { return true; } object[] instantiationData = view.InstantiationData; if (instantiationData != null && instantiationData.Length > 1 && instantiationData[0] is string text && text == "ImCritter.Visual" && instantiationData[1] is int num && Enum.IsDefined(typeof(CritterKind), num)) { kind = (CritterKind)num; return true; } return false; } internal static bool IsManualBombIgnitionInProgress(PhotonView view) { try { if ((Object)(object)view == (Object)null || (Object)(object)ActiveCritterCharacter == (Object)null) { return false; } CritterController component = ((Component)ActiveCritterCharacter).GetComponent<CritterController>(); return (Object)(object)component != (Object)null && component.Active && component._kind == CritterKind.Bomb && component._bombIgnited && (Object)(object)component._critterView == (Object)(object)view; } catch { return false; } } internal static bool IsLocalCritterCharacter(Character character) { if ((Object)(object)character != (Object)null && character.IsLocal) { return (Object)(object)ActiveCritterCharacter == (Object)(object)character; } return false; } private static void LogInfo(string message) { ManualLogSource log = CritterPlugin.Log; if (log != null) { log.LogInfo((object)("[Critter] " + message)); } } private static void LogError(string entryPoint, Exception ex) { ManualLogSource log = CritterPlugin.Log; if (log != null) { log.LogError((object)("[Critter] " + entryPoint + ": " + ex)); } } public bool IsValid() { if (!Active || (Object)(object)_character == (Object)null) { return false; } if (ShouldRestoreOnPickupHijack()) { return true; } if (IsBreakRestoreItemForm(_kind)) { return true; } if ((Object)(object)_critterRoot == (Object)null || (Object)(object)_critterRigidbody == (Object)null) { return false; } if (RequiresMob(_kind) && (Object)(object)_mob == (Object)null) { return false; } return true; } private static bool RequiresMob(CritterKind kind) { return !IsBreakRestoreItemForm(kind); } private static bool IsBreakRestoreItemForm(CritterKind kind) { if (kind != CritterKind.Coconut && kind != CritterKind.Bomb) { return kind == CritterKind.Cactus; } return true; } private static bool IsTransformEntryRestoreForm(CritterKind kind) { if (kind != CritterKind.Coconut) { return kind == CritterKind.Bomb; } return true; } private static bool IsPickupRestoreWhenMasterUnmoddedForm(CritterKind kind) { if (kind != CritterKind.Frog && kind != CritterKind.Scorpion && kind != CritterKind.Coconut && kind != CritterKind.Bomb) { return kind == CritterKind.Cactus; } return true; } private bool ShouldRestoreOnPickupHijack() { if (IsPickupRestoreWhenMasterUnmoddedForm(_kind)) { return !CritterPlugin.MasterHasMod(); } return false; } private bool ShouldUseLastKnownRestorePosition() { if (_itemRestoreAt > 0f && ((Vector3)(ref _lastKnownCritterPosition)).sqrMagnitude > 0.0001f) { if (!IsBreakRestoreItemForm(_kind)) { return ShouldRestoreOnPickupHijack(); } return true; } return false; } private bool ShouldRestoreAtTransformEntryPosition() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (_itemRestoreAt > 0f && _restoreAtTransformEntryOnExit && IsTransformEntryRestoreForm(_kind) && IsFiniteVector(_transformEntryRestorePosition)) { return ((Vector3)(ref _transformEntryRestorePosition)).sqrMagnitude > 0.0001f; } return false; } internal static void ForceExitForEndGame() { try { if ((Object)(object)ActiveCritterCharacter != (Object)null) { CritterController component = ((Component)ActiveCritterCharacter).GetComponent<CritterController>(); if ((Object)(object)component != (Object)null && component.Active) { component.ExitCritter(); return; } } CritterController[] array = Object.FindObjectsByType<CritterController>((FindObjectsSortMode)0); foreach (CritterController critterController in array) { if ((Object)(object)critterController != (Object)null && critterController.Active) { critterController.ExitCritter(); break; } } } catch (Exception ex) { LogError("ForceExitForEndGame", ex); } } internal static object GetWalkingMobState() { if (_walkingMobState == null) { Type type = AccessTools.Inner(typeof(Mob), "MobState"); if (type != null && type.IsEnum) { _walkingMobState = Enum.Parse(type, "Walking"); } } return _walkingMobState; } internal bool EnterCritter(Character character, CritterKind kind) { //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_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_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_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) if (Active) { return false; } try { GameObject val = SpawnCritter(character, kind, useLastKnownPosition: false); if ((Object)(object)val == (Object)null) { LogInfo("Failed to spawn critter prefab for " + kind.ToString() + "."); return false; } _character = character; _kind = kind; _prevCenter = character.Center; _cameraVelocity = Vector3.zero; _cameraHasSmoothedPosition = false; _nextJumpAllowedTime = 0f; _nextAttackAllowedTime = 0f; _frogJumpPressedTime = -10f; _attackPressedTime = -10f; _frogLocalLickBusyUntil = 0f; _coconutChargeStartTime = -1f; _itemRestoreAt = -1f; _coconutSlamQueued = false; _bombIgnited = false; _lastKnownCritterPosition = val.transform.position; _transformEntryRestorePosition = character.Center; _lastSafeExitAnchor = character.Center; _restoreAtTransformEntryOnExit = false; Active = true; ActiveCritterCharacter = character; ((Behaviour)this).enabled = true; SetCritterNoClip(enable: true); HideLocalRenderers(); HideHud(); LogInfo("Entered " + kind.ToString() + " form."); return true; } catch (Exception ex) { LogError("EnterCritter(" + kind.ToString() + ")", ex); TearDownCritter(); return false; } } private GameObject SpawnCritter(Character character, CritterKind kind, bool useLastKnownPosition) { //IL_0016: 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_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_0037: 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_0077: 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_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) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((useLastKnownPosition && ((Vector3)(ref _lastKnownCritterPosition)).sqrMagnitude > 0.0001f) ? _lastKnownCritterPosition : (character.Center + Vector3.up * 0.5f)); string[] prefabNameCandidates = GetPrefabNameCandidates(kind); GameObject val2 = null; string text = ((prefabNameCandidates.Length != 0) ? prefabNameCandidates[0] : kind.ToString()); for (int i = 0; i < prefabNameCandidates.Length; i++) { if (!((Object)(object)val2 == (Object)null)) { break; } text = prefabNameCandidates[i]; try { if (PhotonNetwork.InRoom) { val2 = PhotonNetwork.Instantiate("0_Items/" + text, val, Quaternion.identity, (byte)0, new object[2] { "ImCritter.Visual", (int)kind }); continue; } GameObject val3 = Resources.Load<GameObject>("0_Items/" + text); if ((Object)(object)val3 == (Object)null) { val3 = Resources.Load<GameObject>(text); } if ((Object)(object)val3 != (Object)null) { val2 = Object.Instantiate<GameObject>(val3, val, Quaternion.identity); ((Object)val2).name = "CritterLocal_" + text; } } catch (Exception ex) { LogInfo("Spawn candidate 0_Items/" + text + " failed: " + ex.Message); val2 = null; } } if ((Object)(object)val2 == (Object)null) { LogInfo("SpawnCritter returned null for " + kind.ToString() + "."); return null; } _critterRoot = val2; _critterView = val2.GetComponent<PhotonView>(); _item = val2.GetComponent<Item>(); _critterRigidbody = val2.GetComponent<Rigidbody>(); if ((Object)(object)_critterRigidbody == (Object)null && (Object)(object)_item != (Object)null) { _critterRigidbody = _item.rig; } _mob = val2.GetComponent<Mob>(); _frog = val2.GetComponent<FrogTongue>(); _beetle = val2.GetComponent<Beetle>(); _scorpion = val2.GetComponent<Scorpion>(); _dynamite = val2.GetComponent<Dynamite>(); _breakable = val2.GetComponent<Breakable>(); if ((Object)(object)_critterRigidbody == (Object)null || ((Object)(object)_mob == (Object)null && !IsBreakRestoreItemForm(kind))) { LogInfo("Prefab 0_Items/" + text + " has no required Rigidbody/Mob for " + kind.ToString() + "."); return null; } _critterRigidbody.freezeRotation = !IsBreakRestoreItemForm(kind); if (kind == CritterKind.Bomb && (Object)(object)_dynamite != (Object)null) { _dynamite.lightFuseRadius = 0f; } if (kind == CritterKind.Frog) { ConfigureControlledFrogTongue(); } if ((Object)(object)_critterView != (Object)null) { KindByViewId[_critterView.ViewID] = kind; } if ((Object)(object)_mob != (Object)null) { _mob.hasBrain = false; TrySetMobField("forceNoMovement", true); TrySetMobStateWalking(); } _controlledFlatVelocity = Vector3.zero; ApplyControlledRigidbodySettings(logOnce: true); if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.anim != (Object)null) { TrySetMobField("sleeping", false); } if ((Object)(object)_item != (Object)null) { _item.blockInteraction = true; } return val2; } private void ConfigureControlledFrogTongue() { if (!((Object)(object)_frog == (Object)null)) { _frog.extraDragLetGo = 0f; _frog.launchForce = 0f; _frog.liftForce = 0f; _frog.liftDragForce = 0f; _frog.extraDragOther = 0f; _frog.stopPullFriendDistance = Mathf.Max(_frog.stopPullFriendDistance, 2.6f); } } private static string[] GetPrefabNameCandidates(CritterKind kind) { return kind switch { CritterKind.Frog => new string[1] { "Frog" }, CritterKind.Beetle => new string[1] { "Beetle" }, CritterKind.Scorpion => new string[1] { "Scorpion" }, CritterKind.Coconut => new string[5] { "item_coconut", "Item_Coconut", "Coconut", "CocoNut", "CoconutItem" }, CritterKind.Bomb => new string[2] { "Dynamite", "Bomb" }, CritterKind.Cactus => new string[2] { "cactusball", "CactusBall" }, _ => throw new ArgumentOutOfRangeException("kind"), }; } public void ExitCritter() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) if (!Active && (Object)(object)_critterRoot == (Object)null) { return; } try { Active = false; ActiveCritterCharacter = null; ((Behaviour)this).enabled = false; PositionCharacterForExit(); SetCritterNoClip(enable: false); DestroyCritter(); ForceShowLocalRenderers(); _localRenderers = null; RestoreHud(); _lastKnownCritterPosition = Vector3.zero; _transformEntryRestorePosition = Vector3.zero; _lastSafeExitAnchor = Vector3.zero; _restoreAtTransformEntryOnExit = false; LogInfo("Exited " + _kind.ToString() + " form."); } catch (Exception ex) { LogError("ExitCritter", ex); TearDownCritter(); } } private void TearDownCritter() { //IL_0022: 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_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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Active = false; ActiveCritterCharacter = null; ((Behaviour)this).enabled = false; SetCritterNoClip(enable: false); DestroyCritter(); _lastKnownCritterPosition = Vector3.zero; _transformEntryRestorePosition = Vector3.zero; _lastSafeExitAnchor = Vector3.zero; _restoreAtTransformEntryOnExit = false; } private void DestroyCritter() { //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_critterView != (Object)null) { KindByViewId.Remove(_critterView.ViewID); } if ((Object)(object)_critterRoot != (Object)null) { try { if (PhotonNetwork.InRoom && (Object)(object)_critterView != (Object)null && _critterView.IsMine) { PhotonNetwork.Destroy(_critterRoot); } else { Object.Destroy((Object)(object)_critterRoot); } } catch (Exception ex) { LogError("DestroyCritter", ex); } } _critterRoot = null; _critterView = null; _critterRigidbody = null; _mob = null; _item = null; _frog = null; _beetle = null; _breakable = null; _dynamite = null; _controlledFlatVelocity = Vector3.zero; _scorpion = null; _coconutChargeStartTime = -1f; _itemRestoreAt = -1f; _coconutSlamQueued = false; _bombIgnited = false; _loggedControlledPhysics = false; } private void Update() { //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!Active || (Object)(object)_character == (Object)null) { return; } try { ClearNonMovementInput(); KeepPlayerAlive(); UpdatePickupOrBreakRestoreRecovery(); KeepCritterControlled(); UpdateUnmoddedSync(); KeepLocalRenderersHidden(); HideHud(); HandleStamina(); if (!ThirdPartyCameras.ShouldPauseFormControl) { BufferFrogJumpInput(); BufferAttackInput(); } else { ClearBufferedControlInput(); } CheckCritterIntegrity(); if ((Object)(object)_critterRoot != (Object)null && _critterRoot.transform.position.y < -80f) { LogInfo("Critter fell out of the world; exiting form."); ExitCritter(); } } catch (Exception ex) { LogError("CritterController.Update", ex); } } private void CheckCritterIntegrity() { //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < _nextIntegrityCheckTime) { return; } _nextIntegrityCheckTime = Time.unscaledTime + 0.5f; if (IsBreakRestoreItemForm(_kind) || ShouldRestoreOnPickupHijack()) { bool flag = (Object)(object)_critterRoot == (Object)null || (Object)(object)_critterRigidbody == (Object)null || (Object)(object)_critterView == (Object)null || (!IsBreakRestoreItemForm(_kind) && (Object)(object)_mob == (Object)null) || (IsBreakRestoreItemForm(_kind) && IsBreakableAlreadyBroke()); if (flag || ((Object)(object)_item != (Object)null && (int)_item.itemState != 0) || ((Object)(object)_critterView != (Object)null && _critterView.Owner != null && _critterView.Owner != PhotonNetwork.LocalPlayer)) { SchedulePickupOrBreakRestore(IsTransformEntryRestoreForm(_kind) && flag); } } else if ((Object)(object)_critterRoot == (Object)null || (Object)(object)_mob == (Object)null || (Object)(object)_critterView == (Object)null) { LogInfo("Critter object was destroyed (likely picked up by another player); respawning."); RespawnCritter(); } else if (_critterView.Owner != null && _critterView.Owner != PhotonNetwork.LocalPlayer) { LogInfo("Critter ownership was taken; respawning."); RespawnCritter(); } else if ((Object)(object)_item != (Object)null && (int)_item.itemState != 0) { LogInfo("Critter was put in a backpack; respawning."); RespawnCritter(); } } private void RespawnCritter() { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if (!Active || (Object)(object)_character == (Object)null) { return; } if (IsBreakRestoreItemForm(_kind) || ShouldRestoreOnPickupHijack()) { RestorePlayerAfterPickupOrBreak(); } else if (!PhotonNetwork.InRoom) { ExitCritter(); } else { if (Time.unscaledTime < _nextRespawnTime) { return; } _nextRespawnTime = Time.unscaledTime + 3f; try { CritterKind kind = _kind; DestroyCritter(); if ((Object)(object)SpawnCritter(_character, kind, useLastKnownPosition: true) == (Object)null) { LogInfo("Respawn failed; exiting critter form."); ExitCritter(); return; } _prevCenter = _character.Center; _nextJumpAllowedTime = Time.time + 0.3f; _nextAttackAllowedTime = Time.time + 0.5f; _nextUnmoddedSyncTime = 0f; _frogJumpPressedTime = -10f; _attackPressedTime = -10f; _frogLocalLickBusyUntil = 0f; _coconutChargeStartTime = -1f; _itemRestoreAt = -1f; _coconutSlamQueued = false; _bombIgnited = false; LogInfo("Respawned critter form: " + kind); } catch (Exception ex) { LogError("RespawnCritter", ex); } } } private void FixedUpdate() { //IL_0034: 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) if (!Active || (Object)(object)_character == (Object)null) { return; } try { FollowCritterWithCharacterRoot(); if (!ThirdPartyCameras.ShouldPauseFormControl) { DriveCritterPhysics(); return; } ClearBufferedControlInput(); _controlledFlatVelocity = Vector3.zero; } catch (Exception ex) { LogError("CritterController.FixedUpdate", ex); } } private void LateUpdate() { if (!Active || (Object)(object)_character == (Object)null) { return; } try { SyncCharacterData(); UpdateSafeExitAnchor(); RefreshCamera(); } catch (Exception ex) { LogError("CritterController.LateUpdate", ex); } } private void OnDestroy() { if (Active) { Active = false; ActiveCritterCharacter = null; SetCritterNoClip(enable: false); DestroyCritter(); ForceShowLocalRenderers(); RestoreHud(); } } private void KeepCritterControlled() { try { if ((Object)(object)_item != (Object)null && !_item.blockInteraction) { _item.blockInteraction = true; } if ((Object)(object)_critterRigidbody != (Object)null) { ApplyControlledRigidbodySettings(logOnce: false); } if (_kind == CritterKind.Bomb && (Object)(object)_dynamite != (Object)null && _dynamite.lightFuseRadius != 0f) { _dynamite.lightFuseRadius = 0f; } if (!((Object)(object)_mob == (Object)null)) { if (_mob.hasBrain) { _mob.hasBrain = false; } TrySetMobField("forceNoMovement", true); TrySetMobField("sleeping", false); _mob.UpdateAnimation(); } } catch (Exception ex) { LogError("KeepCritterControlled", ex); } } private void ApplyControlledRigidbodySettings(bool logOnce) { //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) if ((Object)(object)_critterRigidbody == (Object)null) { return; } try { _critterRigidbody.isKinematic = false; _critterRigidbody.useGravity = true; _critterRigidbody.detectCollisions = true; _critterRigidbody.constraints = (RigidbodyConstraints)((!IsBreakRestoreItemForm(_kind)) ? 112 : 0); _critterRigidbody.linearDamping = 0.05f; _critterRigidbody.angularDamping = 8f; _critterRigidbody.interpolation = (RigidbodyInterpolation)1; _critterRigidbody.sleepThreshold = 0f; _critterRigidbody.WakeUp(); if (logOnce && !_loggedControlledPhysics) { _loggedControlledPhysics = true; LogInfo("Controlled physics for " + _kind.ToString() + ": linearDamping=" + _critterRigidbody.linearDamping.ToString("0.###") + " angularDamping=" + _critterRigidbody.angularDamping.ToString("0.###") + " constraints=" + ((object)_critterRigidbody.constraints/*cast due to .constrained prefix*/).ToString() + " kinematic=" + _critterRigidbody.isKinematic); } } catch (Exception ex) { LogError("ApplyControlledRigidbodySettings", ex); } } private void TrySetMobField(string fieldName, object value) { try { AccessTools.Field(typeof(Mob), fieldName)?.SetValue(_mob, value); } catch (Exception ex) { LogError("TrySetMobField(" + fieldName + ")", ex); } } private void UpdateUnmoddedSync() { //IL_0076: 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_0082: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_critterView == (Object)null || (Object)(object)_critterRoot == (Object)null || (Object)(object)_critterRigidbody == (Object)null || !PhotonNetwork.InRoom || CritterPlugin.UnmoddedRoomSupport == null || !CritterPlugin.UnmoddedRoomSupport.Value || !CritterPlugin.RoomHasUnmoddedPlayers() || Time.unscaledTime < _nextUnmoddedSyncTime) { return; } _nextUnmoddedSyncTime = Time.unscaledTime + 0.1f; try { Vector3 position = _critterRigidbody.position; Quaternion rotation = _critterRigidbody.rotation; if (!IsFiniteVector(position)) { return; } PhotonView val = (((Object)(object)_item != (Object)null) ? ((MonoBehaviourPun)_item).photonView : _critterView); bool flag = PhotonViewHasRpcMethod(val, "SetKinematicRPC"); foreach (Player item in CritterPlugin.UnmoddedRemotePlayers()) { if (flag) { val.RPC("SetKinematicRPC", item, new object[3] { true, position, rotation }); } if ((Object)(object)_mob != (Object)null) { _critterView.RPC("RPC_SyncMobState", item, new object[1] { 0 }); } } } catch (Exception ex) { LogError("UpdateUnmoddedSync", ex); } } private void ForceCritterPhysicsSync(int frames) { if ((Object)(object)_item == (Object)null || !PhotonNetwork.InRoom || (Object)(object)_critterView == (Object)null || !_critterView.IsMine) { return; } try { ItemForceSyncForFramesMethod?.Invoke(_item, new object[1] { Mathf.Max(1, frames) }); } catch { } } private static bool IsFiniteVector(Vector3 v) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0034: 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) if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z) && !float.IsInfinity(v.x) && !float.IsInfinity(v.y)) { return !float.IsInfinity(v.z); } return false; } private static bool IsFiniteQuaternion(Quaternion q) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: 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_0034: 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_004e: 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) if (!float.IsNaN(q.x) && !float.IsNaN(q.y) && !float.IsNaN(q.z) && !float.IsNaN(q.w) && !float.IsInfinity(q.x) && !float.IsInfinity(q.y) && !float.IsInfinity(q.z)) { return !float.IsInfinity(q.w); } return false; } private void TrySetMobStateWalking() { try { object walkingMobState = GetWalkingMobState(); if (walkingMobState != null) { AccessTools.PropertySetter(typeof(Mob), "mobState")?.Invoke(_mob, new object[1] { walkingMobState }); } } catch (Exception ex) { LogError("TrySetMobStateWalking", ex); } } private void DriveCritterPhysics() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0325: Unknown result type (might be due to invalid IL or missing references) //IL_032a: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023d: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_03d5: Unknown result type (might be due to invalid IL or missing references) //IL_03d6: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03e0: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_034e: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0245: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_01b8: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: 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_01d0: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_036f: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0379: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_038c: 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_039e: Unknown result type (might be due to invalid IL or missing references) //IL_03af: Unknown result type (might be due to invalid IL or missing references) //IL_03b9: Unknown result type (might be due to invalid IL or missing references) //IL_036a: Unknown result type (might be due to invalid IL or missing references) //IL_036b: Unknown result type (might be due to invalid IL or missing references) //IL_0405: Unknown result type (might be due to invalid IL or missing references) //IL_040a: Unknown result type (might be due to invalid IL or missing references) //IL_0414: Unknown result type (might be due to invalid IL or missing references) //IL_0261: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_0275: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) //IL_0666: Unknown result type (might be due to invalid IL or missing references) //IL_0663: Unknown result type (might be due to invalid IL or missing references) //IL_092d: Unknown result type (might be due to invalid IL or missing references) //IL_07c3: Unknown result type (might be due to invalid IL or missing references) //IL_07ba: Unknown result type (might be due to invalid IL or missing references) //IL_0667: Unknown result type (might be due to invalid IL or missing references) //IL_07c8: Unknown result type (might be due to invalid IL or missing references) //IL_0806: Unknown result type (might be due to invalid IL or missing references) //IL_082d: Unknown result type (might be due to invalid IL or missing references) //IL_0832: Unknown result type (might be due to invalid IL or missing references) //IL_0839: Unknown result type (might be due to invalid IL or missing references) //IL_083e: Unknown result type (might be due to invalid IL or missing references) //IL_06a5: Unknown result type (might be due to invalid IL or missing references) //IL_06aa: Unknown result type (might be due to invalid IL or missing references) //IL_052a: Unknown result type (might be due to invalid IL or missing references) //IL_052f: Unknown result type (might be due to invalid IL or missing references) //IL_072d: Unknown result type (might be due to invalid IL or missing references) //IL_0731: Unknown result type (might be due to invalid IL or missing references) //IL_0736: Unknown result type (might be due to invalid IL or missing references) //IL_073d: Unknown result type (might be due to invalid IL or missing references) //IL_0742: Unknown result type (might be due to invalid IL or missing references) //IL_056e: Unknown result type (might be due to invalid IL or missing references) //IL_0573: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_critterRigidbody == (Object)null || TransformState.MenuOpen || ThirdPartyCameras.ShouldPauseFormControl) { return; } ApplyControlledRigidbodySettings(logOnce: false); 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(); } bool flag = IsSprintHeld() && CanSprint(); float num = (flag ? Mathf.Max(1f, CritterPlugin.SprintMultiplier(_kind).Value) : 1f); float num2 = CritterPlugin.MaxSpeed(_kind).Value * num; bool flag2 = _kind == CritterKind.Frog && (Object)(object)_frog != (Object)null; bool flag3 = _kind == CritterKind.Beetle; bool flag4 = IsBreakRestoreItemForm(_kind); bool flag5 = _kind == CritterKind.Coconut; bool flag6 = _kind == CritterKind.Bomb; bool flag7 = _kind == CritterKind.Cactus; if (flag7 && _critterRigidbody.isKinematic) { return; } if (!flag2) { if (flag5 || flag6 || flag7) { if (((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { Vector3 linearVelocity = _critterRigidbody.linearVelocity; Vector3 val3 = default(Vector3); ((Vector3)(ref val3))..ctor(linearVelocity.x, 0f, linearVelocity.z); if (((Vector3)(ref val3)).magnitude < num2) { _critterRigidbody.AddForce(val2 * CritterPlugin.MovementForce(_kind).Value * num, (ForceMode)5); } val = Vector3.Cross(Vector3.up, val2); Vector3 normalized2 = ((Vector3)(ref val)).normalized; _critterRigidbody.AddTorque(normalized2 * 16f * num, (ForceMode)5); ForceCritterPhysicsSync(2); } if (flag && ((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { UseStamina(Time.fixedDeltaTime * 0.035f); } } else { Vector3 linearVelocity2 = _critterRigidbody.linearVelocity; Vector3 val4 = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? (val2 * num2) : Vector3.zero); Vector3 controlledFlatVelocity = _controlledFlatVelocity; float num3 = ((_kind == CritterKind.Beetle) ? 18f : 12f); Vector3 val5 = (_controlledFlatVelocity = Vector3.MoveTowards(controlledFlatVelocity, val4, num3 * Time.fixedDeltaTime)); _critterRigidbody.linearVelocity = new Vector3(0f, linearVelocity2.y, 0f); if (((Vector3)(ref val5)).sqrMagnitude > 1E-06f) { _critterRigidbody.MovePosition(_critterRigidbody.position + val5 * Time.fixedDeltaTime); ForceCritterPhysicsSync(2); } if ((_kind == CritterKind.Beetle || flag4) && flag && ((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { UseStamina(Time.fixedDeltaTime * 0.035f); } } } if (flag3 && IsCritterGrounded() && Vector3.Dot(_critterRoot.transform.up, Vector3.up) < 0.5f) { Vector3 val6 = _critterRoot.transform.forward; val6.y = 0f; if (((Vector3)(ref val6)).sqrMagnitude < 0.0001f) { val6 = flatLookDirection; } Quaternion val7 = Quaternion.LookRotation(((Vector3)(ref val6)).normalized, Vector3.up); _critterRigidbody.MoveRotation(Quaternion.Slerp(_critterRigidbody.rotation, val7, Time.deltaTime * 6f)); Rigidbody critterRigidbody = _critterRigidbody; critterRigidbody.angularVelocity *= 0.5f; } if (!flag4 && ((Vector3)(ref val2)).sqrMagnitude > 0.0001f) { Quaternion val8 = Quaternion.LookRotation(val2, Vector3.up); float num4 = ((_kind == CritterKind.Scorpion) ? 4.5f : 6.5f); _critterRigidbody.MoveRotation(Quaternion.Slerp(_critterRigidbody.rotation, val8, Time.fixedDeltaTime * num4)); } if (flag2 && IsCritterGrounded()) { _lastGroundedTime = Time.time; } if (flag2 && HasBufferedFrogJump()) { if (!(Time.time < _nextJumpAllowedTime)) { if (!CanFrogJumpNow()) { string[] obj = new string[13] { "Frog jump blocked: grounded=", IsCritterGrounded().ToString(), " char.isGrounded=", (_character?.data?.isGrounded == true).ToString(), " rb.kinematic=", (!((Object)(object)_critterRigidbody != (Object)null) || _critterRigidbody.isKinematic).ToString(), " rb.velY=", null, null, null, null, null, null }; object obj2; if (!((Object)(object)_critterRigidbody != (Object)null)) { obj2 = "n/a"; } else { val = _critterRigidbody.linearVelocity; obj2 = val.y.ToString("0.00"); } obj[7] = (string)obj2; obj[8] = " y="; object obj3; if (!((Object)(object)_critterRoot != (Object)null)) { obj3 = "n/a"; } else { val = _critterRoot.transform.position; obj3 = val.y.ToString("0.00"); } obj[9] = (string)obj3; obj[10] = " sinceGround="; obj[11] = (Time.time - _lastGroundedTime).ToString("0.00"); obj[12] = "s"; LogInfo(string.Concat(obj)); ConsumeFrogJumpInput(); } else if (!UseStamina(0.08f)) { Character character = _character; float? obj4; if (character == null) { obj4 = null; } else { CharacterData data = character.data; obj4 = ((data != null) ? new float?(data.currentStamina) : ((float?)null)); } LogInfo("Frog jump blocked: stamina=" + (obj4 ?? (-1f)).ToString("0.00")); ConsumeFrogJumpInput(); } else { ConsumeFrogJumpInput(); _lastGroundedTime = Time.time; Vector3 val9 = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? val2 : flatLookDirection); float value = CritterPlugin.JumpPower(_kind).Value; if ((Object)(object)_mob.anim != (Object)null) { _mob.anim.SetTrigger("Jump"); } val9 = ((Vector3)(ref val9)).normalized; float num5 = (IsSprintHeld() ? Mathf.Max(1f, CritterPlugin.SprintMultiplier(_kind).Value) : 1f); float num6 = Mathf.Clamp(CritterPlugin.MaxSpeed(_kind).Value * value * 0.55f * num5, 2f, 40f); float num7 = Mathf.Clamp(CritterPlugin.JumpSpeed(_kind).Value * value, 4f, 30f); _critterRigidbody.linearVelocity = val9 * num6 + Vector3.up * num7; ForceCritterPhysicsSync(8); _nextJumpAllowedTime = Time.time + 0.3f; } } } else if (flag4 && HasBufferedFrogJump()) { if (Time.time >= _nextJumpAllowedTime && IsCritterGrounded() && UseStamina(0.08f)) { ConsumeFrogJumpInput(); Vector3 val10 = ((((Vector3)(ref val2)).sqrMagnitude > 0.0001f) ? ((Vector3)(ref val2)).normalized : Vector3.zero); float value2 = CritterPlugin.JumpPower(_kind).Value; float num8 = Mathf.Clamp(CritterPlugin.JumpSpeed(_kind).Value * value2, 3f, 20f); _critterRigidbody.linearVelocity = val10 * Mathf.Clamp(CritterPlugin.MaxSpeed(_kind).Value * 0.35f, 0f, 10f) + Vector3.up * num8; ForceCritterPhysicsSync(6); _nextJumpAllowedTime = Time.time + 0.3f; } else if (Time.time >= _nextJumpAllowedTime) { ConsumeFrogJumpInput(); } } if (flag5 && _coconutSlamQueued && Time.time >= _nextAttackAllowedTime) { _coconutSlamQueued = false; if (TryCoconutSlam()) { _nextAttackAllowedTime = Time.time + CritterPlugin.AttackCooldown(_kind).Value; } } else if (flag6 && HasBufferedAttack() && Time.time >= _nextAttackAllowedTime) { ConsumeAttackInput(); if (TryIgniteBomb()) { _nextAttackAllowedTime = Time.time + CritterPlugin.AttackCooldown(_kind).Value; } } else if (HasBufferedAttack() && Time.time >= _nextAttackAllowedTime && (!flag2 || IsFrogTongueReady())) { ConsumeAttackInput(); if (TryAttack(flatLookDirection)) { _nextAttackAllowedTime = Time.time + ((_kind == CritterKind.Frog) ? Mathf.Min(0.1f, CritterPlugin.AttackCooldown(_kind).Value) : CritterPlugin.AttackCooldown(_kind).Value); } } } private bool CanFrogJumpNow() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (IsCritterGrounded() || Time.time - _lastGroundedTime <= 0.3f) { return true; } if ((Object)(object)_critterRigidbody == (Object)null) { return false; } return Mathf.Abs(_critterRigidbody.linearVelocity.y) <= 0.08f; } private bool TryAttack(Vector3 forward) { //IL_002f: 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) return _kind switch { CritterKind.Frog => TryFrogTongue(), CritterKind.Beetle => TryBeetleBonk(forward), CritterKind.Scorpion => TryScorpionSting(forward), CritterKind.Coconut => TryCoconutSlam(), CritterKind.Bomb => TryIgniteBomb(), CritterKind.Cactus => TryCactusLaunch(), _ => false, }; } private static bool PhotonViewHasRpcMethod(PhotonView view, string methodName) { if ((Object)(object)view == (Object)null) { return false; } try { MonoBehaviour[] components = ((Component)view).GetComponents<MonoBehaviour>(); if (components == null) { return false; } foreach (MonoBehaviour val in components) { if (!((Object)(object)val == (Object)null)) { Type type = ((object)val).GetType(); if (!HasSetKinematicRpcByComponentType.TryGetValue(type, out var value)) { value = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null; HasSetKinematicRpcByComponentType[type] = value; } if (value) { return true; } } } } catch { return false; } return false; } private void UpdatePickupOrBreakRestoreRecovery() { //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) bool flag = ShouldRestoreOnPickupHijack(); if (IsBreakRestoreItemForm(_kind) || flag) { if ((Object)(object)_critterRoot != (Object)null) { _lastKnownCritterPosition = _critterRoot.transform.position; } if (_itemRestoreAt > 0f && Time.unscaledTime >= _itemRestoreAt) { RestorePlayerAfterPickupOrBreak(); } else if ((Object)(object)_critterRoot == (Object)null || (Object)(object)_critterRigidbody == (Object)null || (Object)(object)_critterView == (Object)null || (!IsBreakRestoreItemForm(_kind) && (Object)(object)_mob == (Object)null) || (IsBreakRestoreItemForm(_kind) && IsBreakableAlreadyBroke())) { SchedulePickupOrBreakRestore(IsTransformEntryRestoreForm(_kind)); } } } private void SchedulePickupOrBreakRestore(bool restoreAtTransformEntry) { //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) if (!Active) { return; } bool flag = ShouldRestoreOnPickupHijack(); if (IsBreakRestoreItemForm(_kind) || flag) { if ((Object)(object)_critterRoot != (Object)null) { _lastKnownCritterPosition = _critterRoot.transform.position; } if (restoreAtTransformEntry && IsTransformEntryRestoreForm(_kind)) { _restoreAtTransformEntryOnExit = true; } if (!(_itemRestoreAt > 0f)) { _itemRestoreAt = Time.unscaledTime + 1f; _coconutChargeStartTime = -1f; _coconutSlamQueued = false; string text = ((flag && !CritterPlugin.MasterHasMod()) ? "was picked up while the master has no mod" : "broke, exploded, or was removed"); LogInfo(_kind.ToString() + " " + text + "; restoring player in 1 second."); } } } private bool IsBreakableAlreadyBroke() { if ((Object)(object)_breakable == (Object)null || BreakableAlreadyBrokeField == null) { return false; } try { return (bool)BreakableAlreadyBrokeField.GetValue(_breakable); } catch { return false; } } private void RestorePlayerAfterPickupOrBreak() { if (!Active || (!IsBreakRestoreItemForm(_kind) && !ShouldRestoreOnPickupHijack())) { return; } try { string text = (ShouldRestoreAtTransformEntryPosition() ? "transform entry position" : "pickup/destroyed position"); LogInfo("Restoring player at " + _kind.ToString() + " " + text + "."); ExitCritter(); } catch (Exception ex) { LogError("RestorePlayerAfterPickupOrBreak", ex); } } private bool TryCoconutSlam() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_critterRigidbody == (Object)null || (Object)(object)_critterRoot == (Object)null) { return false; } try { float num = Mathf.Clamp01(((_coconutChargeStartTime > 0f) ? Mathf.Clamp(Time.time - _coconutChargeStartTime, 0f, 1.25f) : 0.4375f) / 1.25f); Vector3 crosshairLaunchDirection = GetCrosshairLaunchDirection(45f); float num2 = Mathf.Lerp(10f, 28f, num); _critterRigidbody.linearVelocity = crosshairLaunchDirection * num2; Vector3 val = Vector3.ProjectOnPlane(crosshairLaunchDirection, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = GetFlatLookDirection(); } Rigidbody critterRigidbody = _critterRigidbody; critterRigidbody.angularVelocity += Vector3.Cross(Vector3.up, ((Vector3)(ref val)).normalized) * Mathf.Lerp(4f, 16f, num); ForceCritterPhysicsSync(10); _coconutChargeStartTime = -1f; LogInfo("Coconut slam charged " + num.ToString("0.00") + "."); return true; } catch (Exception ex) { LogError("TryCoconutSlam", ex); return false; } } private bool TryIgniteBomb() { if (_kind != CritterKind.Bomb || _bombIgnited || (Object)(object)_dynamite == (Object)null) { return false; } try { _bombIgnited = true; _dynamite.LightFlare(); ForceCritterPhysicsSync(4); LogInfo("Bomb fuse lit through vanilla Dynamite.LightFlare."); return true; } catch (Exception ex) { _bombIgnited = false; LogError("TryIgniteBomb", ex); return false; } } private bool TryCactusLaunch() { return false; } private Vector3 GetCrosshairLaunchDirection(float range) { //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0010: 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_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_0029: 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_00fd: 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_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_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_007c: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00b3: Unknown result type (might be due to invalid IL or missing references) try { Camera main = Camera.main; if ((Object)(object)main == (Object)null) { Vector3 val = GetFlatLookDirection() + Vector3.up * 0.16f; return ((Vector3)(ref val)).normalized; } Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(((Component)main).transform.position, ((Component)main).transform.forward); Vector3 val3 = ((Ray)(ref val2)).direction; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val2, ref val4, range, -5, (QueryTriggerInteraction)1) && (Object)(object)_critterRigidbody != (Object)null) { Vector3 val5 = ((RaycastHit)(ref val4)).point - _critterRigidbody.position; if (((Vector3)(ref val5)).sqrMagnitude > 1f) { val3 = Vector3.Slerp(val3, ((Vector3)(ref val5)).normalized, 0.25f); } } val3 += Vector3.up * 0.16f; return ((Vector3)(ref val3)).normalized; } catch { Vector3 val6 = GetFlatLookDirection() + Vector3.up * 0.16f; return ((Vector3)(ref val6)).normalized; } } private bool TryFrogTongue() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_frog == (Object)null) { return false; } try { ResetFrogTongueIfIdle(); Character val = FindCrosshairTarget(Mathf.Max(_frog.maxDistance, 14f), 3.4f); if ((Object)(object)val == (Object)null) { if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.anim != (Object)null) { _mob.anim.SetTrigger("Lick"); } TryPlayFrogLickSfx(); _frogLocalLickBusyUntil = Time.time + 0.35f; LogInfo("Frog tongue lashed (no target)."); return true; } ((MonoBehaviourPun)_frog).photonView.RPC("RPCA_FrogAction", (RpcTarget)0, new object[3] { ((MonoBehaviourPun)val).photonView, (object)(FrogActionType)1, Vector3.zero }); LogInfo("Frog tongue fired."); return true; } catch (Exception ex) { LogError("TryFrogTongue", ex); return false; } } private bool IsFrogTongueReady() { if ((Object)(object)_frog == (Object)null) { return true; } if (Time.time < _frogLocalLickBusyUntil) { return false; } try { object? obj = FrogTargetCharacterField?.GetValue(_frog); object? obj2 = ((obj is Character) ? obj : null); bool flag = FrogIsPullingField != null && (bool)FrogIsPullingField.GetValue(_frog); float num = ((FrogTongueLengthField != null) ? ((float)FrogTongueLengthField.GetValue(_frog)) : 0f); return (Object)obj2 == (Object)null && !flag && num <= 0.08f; } catch { return Time.time >= _nextAttackAllowedTime; } } private void TryPlayFrogLickSfx() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_frog == (Object)null) && _frog.lickSFX != null && _frog.lickSFX.Length != 0 && !((Object)(object)_critterRoot == (Object)null)) { SFX_Instance val = _frog.lickSFX[0]; if ((Object)(object)val != (Object)null) { val.Play(_critterRoot.transform.position); } } } private bool TryBeetleBonk(Vector3 forward) { //IL_0027: 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_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_00c3: 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) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: 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_00dd: Unknown result type (might be due to invalid IL or missing references) try { Character val = FindCrosshairTarget(4f); if ((Object)(object)val == (Object)null) { PlayAttackAnimationNetworked(); Rigidbody critterRigidbody = _critterRigidbody; if (critterRigidbody != null) { critterRigidbody.AddForce(forward * 3f + Vector3.up * 1.5f, (ForceMode)2); } return true; } PlayAttackAnimationNetworked(); float ragdollTime = (((Object)(object)_beetle != (Object)null) ? _beetle.ragdollTime : 2f); float num = (((Object)(object)_beetle != (Object)null) ? _beetle.bonkForce : 8f); float num2 = (((Object)(object)_beetle != (Object)null) ? _beetle.bonkForceUp : 6f) * 1.6f; Vector3 force = forward * num + Vector3.up * num2; ApplyKnockback(val, force, ragdollTime); LogInfo("Beetle bonk!"); return true; } catch (Exception ex) { LogError("TryBeetleBonk", ex); return false; } } private bool TryScorpionSting(Vector3 forward) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_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) try { Character val = FindCrosshairTarget(4f); if ((Object)(object)val == (Object)null) { PlayAttackAnimationNetworked(); return true; } PlayAttackAnimationNetworked(); ApplyKnockback(val, forward * 3f + Vector3.up * 2f, 1.5f); ApplyPoison(val); LogInfo("Scorpion sting!"); return true; } catch (Exception ex) { LogError("TryScorpionSting", ex); return false; } } private void PlayAttackAnimation() { if ((Object)(object)_mob != (Object)null && (Object)(object)_mob.anim != (Object)null) { _mob.anim.SetTrigger("Attack"); } } private void PlayAttackAnimationNetworked() { PlayAttackAnimation(); try { if (PhotonNetwork.InRoom && (Object)(object)_critterView != (Object)null && _critterView.IsMine) { _critterView.RPC("RPC_StartAttack", (RpcTarget)1, Array.Empty<object>()); } } catch (Exception ex) { LogInfo("Attack animation RPC failed: " + ex.Message); } } private static void ApplyKnockback(Character target, Vector3 force, float ragdollTime) { //IL_008f: 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) if ((Object)(object)target == (Object)null) { return; } try { PhotonView photonView = ((MonoBehaviourPun)target).photonView; if (photonView != null) { photonView.RPC("RPCA_Fall", (RpcTarget)0, new object[2] { ragdollTime, 0f }); } } catch (Exception ex) { ManualLogSource log = CritterPlugin.Log; if (log != null) { log.LogWarning((object)("[Critter] RPCA_Fall failed: " + ex.Message)); } } try { if ((Object)(object)((MonoBehaviourPun)target).photonView != (Object)null) { ((MonoBehaviourPun)target).photonView.RPC("RPCA_AddForceToBodyPart", (RpcTarget)0, new object[3] { (object)(BodypartType)2, Vector3.zero, force }); } } catch (Exception ex2) { ManualLogSource log2 = CritterPlugin.Log; if (log2 != null) { log2.LogWarning((object)("[Critter] Knockback broadcast failed: " + ex2.Message)); } } } private static void ApplyPoison(Character target) { try { CharacterAfflictions val = ((target.refs != null) ? target.refs.afflictions : null); if (!((Object)(object)val == (Object)null)) { AccessTools.Method(typeof(CharacterAfflictions), "AddStatus", (Type[])null, (Type[])null)?.Invoke(val, new object[6] { 3, 0.15f, false, true, true, false }); Type type = AccessTools.TypeByName("Peak.Afflictions.Affliction_PoisonOverTime"); object obj = ((!(type != null)) ? null : AccessTools.Constructor(type, new Type[3] { typeof(float), typeof(float), typeof(float) }, false)?.Invoke(new object[3] { 10f, 0f, 0.1f })); if (obj != null) { AccessTools.Method(typeof(CharacterAfflictions), "AddAffliction", (Type[])null, (Type[])null)?.Invoke(val, new object[2] { obj, false }); } } } catch (Exception ex) { ManualLogSource log = CritterPlugin.Log; if (log != null) { log.LogWarning((object)("[Critter] Poison affliction failed: " + ex.Message)); } } } private Character FindCrosshairTarget(float range) { return FindCrosshairTarget(range, 2.5f); } private Character FindCrosshairTarget(float range, float aimRadius) { //IL_001f: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: 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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) try { Camera main = Camera.main; if ((Object)(object)main == (Object)null) { return null; } Ray val = default(Ray); ((Ray)(ref val))..ctor(((Component)main).transform.position, ((Component)main).transform.forward); Character result = null; float num = float.MaxValue; List<Character> allCharacters = Character.AllCharacters; for (int i = 0; i < allCharacters.Count; i++) { Character val2 = allCharacters[i]; if ((Object)(object)val2 == (Object)null || (Object)(object)val2 == (Object)(object)_character || (Object)(object)val2.data == (Object)null || val2.data.dead) { continue; } Vector3 center = val2.Center; Vector3 val3 = center - _critterRoot.transform.position; if (((Vector3)(ref val3)).magnitude > range) { continue; } float num2 = Vector3.Dot(center - ((Ray)(ref val)).origin, ((Ray)(ref val)).direction); if (num2 <= 0f) { continue; } float num3 = Vector3.Distance(((Ray)(ref val)).origin + ((Ray)(ref val)).direction * num2, center); float num4 = Mathf.Max(0.65f, GetCharacterAimRadius(val2)); float num5 = Mathf.Max(aimRadius, num4); if (!(num3 > num5)) { float num6 = Mathf.Max(0f, num3 - num4) + ((Vector3)(ref val3)).magnitude * 0.08f; if (num6 < num) { num = num6; result = val2; } } } return result; } catch (Exception ex) { LogError("FindCrosshairTarget", ex); return null; } } private static float GetCharacterAimRadius(Character character) { //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_0031: 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_003e: 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) try { Collider[] componentsInChildren = ((Component)character).GetComponentsInChildren<Collider>(true); float num = 0.65f; foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !val.isTrigger) { Bounds bounds = val.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; num = Mathf.Max(num, Mathf.Min(1.8f, Mathf.Max(extents.x, extents.z))); } } return num; } catch { return 0.65f; } } private void ResetFrogTongueIfIdle() { if ((Object)(object)_frog == (Object)null) { return; } try { object? obj = FrogTargetCharacterField?.GetValue(_frog); object? obj2 = ((obj is Character) ? obj : null); bool flag = FrogIsPullingField != null && (bool)FrogIsPullingField.GetValue(_frog); float num = ((FrogTongueLengthField != null) ? ((float)FrogTongueLengthField.GetValue(_frog)) : 0f); if ((Object)obj2 == (Object)null && !flag && num <= 0.16f && FrogTongueLengthField != null) { FrogTongueLengthField.SetValue(_frog, 0f); } } catch (Exception ex) { LogError("ResetFrogTongueIfIdle", ex); } } private bool IsCritterGrounded() { //IL_0057: 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_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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null && _character.data.isGrounded) { return true; } if ((Object)(object)_critterRoot == (Object)null) { return false; } float critterRadius = GetCritterRadius(); return Physics.CheckSphere(_critterRoot.transform.position - Vector3.up * (critterRadius * 0.8f) + Vector3.down * 0.25f, Mathf.Max(0.08f, critterRadius * 0.5f), -5, (QueryTriggerInteraction)1); } private float GetCritterRadius() { //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_0023: Unknown result type (might be due to invalid IL or missing references) try { Collider componentInChildren = _critterRoot.GetComponentInChildren<Collider>(); if ((Object)(object)componentInChildren != (Object)null) { Bounds bounds = componentInChildren.bounds; return Mathf.Max(0.1f, ((Bounds)(ref bounds)).extents.y); } } catch { } return 0.3f; } private void HandleStamina() { //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) if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return; } CharacterData data = _character.data; if (IsSprintHeld()) { Vector2 movementInput = GetMovementInput(); if (!(((Vector2)(ref movementInput)).sqrMagnitude < 0.0001f)) { return; } } data.currentStamina = Mathf.Min(1f, data.currentStamina + GetStaminaRegen() * Time.deltaTime); } private static bool IsSprintHeld() { if (TransformState.MenuOpen) { return false; } return GameInput.SprintHeld((KeyCode)304); } private bool CanSprint() { if ((Object)(object)_character != (Object)null && (Object)(object)_character.data != (Object)null) { return _character.data.currentStamina > 0.02f; } return false; } private bool UseStamina(float cost) { if ((Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null) { return true; } CharacterData data = _character.data; if (data.currentStamina < cost) { return false; } data.currentStamina = Mathf.Max(0f, data.currentStamina - cost); return true; } private static float GetStaminaRegen() { return Mathf.Clamp(0.18f, 0.01f, 1f); } 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 BufferFrogJumpInput() { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((_kind == CritterKind.Frog || IsBreakRestoreItemForm(_kind)) && !TransformState.MenuOpen && GameInput.JumpPressed(CritterPlugin.JumpKey.Value)) { _frogJumpPressedTime = Time.time; } } private bool HasBufferedFrogJump() { return Time.time - _frogJumpPressedTime <= 0.25f; } private void ConsumeFrogJumpInput() { _frogJumpPressedTime = -10f; } private static bool AttackPressed() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return GameInput.UseSecondaryPressed(CritterPlugin.AttackKey.Value); } private static bool AttackReleased() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return GameInput.UseSecondaryReleased(CritterPlugin.AttackKey.Value); } private void BufferAttackInput() { if (TransformState.MenuOpen || (_kind == CritterKind.Bomb && _bombIgnited)) { return; } if (_kind == CritterKind.Coconut) { if (AttackPressed()) { _coconutChargeStartTime = Time.time; _coconutSlamQueued = false; } if (_coconutChargeStartTime > 0f && (AttackReleased() || Time.time - _coconutChargeStartTime >= 1.25f)) { _coconutSlamQueued = true; } } else if (AttackPressed()) { _attackPressedTime = Time.time; } } private bool HasBufferedAttack() { return Time.time - _attackPressedTime <= 0.2f; } private void ConsumeAttackInput() { _attackPressedTime = -10f; } private void ClearBufferedControlInput() { _frogJumpPressedTime = -10f; _attackPressedTime = -10f; _coconutChargeStartTime = -1f; _coconutSlamQueued = 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_000d: 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_0007: 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 r