using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Peak;
using Photon.Pun;
using UnityEngine;
using UnityEngine.SceneManagement;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("Thanks.I_am_a_BigGhost")]
[assembly: AssemblyDescription("Client-side controllable big-ghost form for PEAK. Press B in the Airport lobby to become the big ghost that rises from the misty swamp.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Thanks")]
[assembly: AssemblyProduct("I'm a Ghost")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("3a7b9c51-4d2e-4f6a-8b10-2c3d4e5f6a7b")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace ImGhost
{
[BepInPlugin("com.github.Thanks.ImGhost", "I'm a Ghost", "0.1.0")]
public sealed class GhostPlugin : BaseUnityPlugin
{
public const string Id = "com.github.Thanks.ImGhost";
public const string Name = "I'm a Ghost";
public const string Version = "0.1.0";
public const string LobbySceneName = "Airport";
internal static ManualLogSource Log;
internal static ConfigEntry<KeyCode> ToggleKey;
internal static ConfigEntry<KeyCode> AttackKey;
internal static ConfigEntry<KeyCode> UpKey;
internal static ConfigEntry<KeyCode> DownKey;
internal static ConfigEntry<KeyCode> SprintKey;
internal static ConfigEntry<float> MovementSpeed;
internal static ConfigEntry<float> VerticalSpeed;
internal static ConfigEntry<float> SprintMultiplier;
internal static ConfigEntry<float> AttackChargeSeconds;
internal static ConfigEntry<float> AttackRevertSeconds;
internal static ConfigEntry<float> AttackRadius;
internal static ConfigEntry<float> KnockbackForce;
internal static ConfigEntry<float> CameraDistance;
internal static ConfigEntry<float> CameraHeight;
internal static ConfigEntry<float> CameraFov;
internal static ConfigEntry<bool> ShowGhostVisual;
private readonly Harmony _harmony = new Harmony("com.github.Thanks.ImGhost");
private GhostController _controller;
private bool _switching;
private bool _lastTogglePressed;
internal static bool IsInLobby()
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
try
{
Scene activeScene = SceneManager.GetActiveScene();
return ((Scene)(ref activeScene)).name == "Airport";
}
catch
{
return false;
}
}
private void Awake()
{
//IL_0107: Unknown result type (might be due to invalid IL or missing references)
//IL_0111: Expected O, but got Unknown
//IL_0144: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Expected O, but got Unknown
//IL_0181: Unknown result type (might be due to invalid IL or missing references)
//IL_018b: Expected O, but got Unknown
//IL_01be: Unknown result type (might be due to invalid IL or missing references)
//IL_01c8: Expected O, but got Unknown
//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
//IL_0205: Expected O, but got Unknown
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Expected O, but got Unknown
//IL_0275: Unknown result type (might be due to invalid IL or missing references)
//IL_027f: Expected O, but got Unknown
//IL_02b2: Unknown result type (might be due to invalid IL or missing references)
//IL_02bc: Expected O, but got Unknown
//IL_02ef: Unknown result type (might be due to invalid IL or missing references)
//IL_02f9: Expected O, but got Unknown
//IL_032c: Unknown result type (might be due to invalid IL or missing references)
//IL_0336: Expected O, but got Unknown
Log = ((BaseUnityPlugin)this).Logger;
_harmony.PatchAll(typeof(GhostHarmonyPatches).Assembly);
ConfigureOptionalCharacterPatches();
ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleKey", (KeyCode)98, "Press to become the big ghost (only in the Airport lobby). Press again to return to normal.");
AttackKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "AttackKey", (KeyCode)324, "Right-click while in ghost form to trigger the ghost explosion attack. The player reverts after the attack.");
UpKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "UpKey", (KeyCode)32, "Hold Space to fly up while in ghost form.");
DownKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "DownKey", (KeyCode)306, "Hold Ctrl to fly down while in ghost form.");
SprintKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "SprintKey", (KeyCode)304, "Hold Shift to sprint (move faster) while in ghost form.");
MovementSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "MovementSpeed", 14f, new ConfigDescription("How fast the ghost glides with WASD.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
VerticalSpeed = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "VerticalSpeed", 12f, new ConfigDescription("How fast the ghost rises and sinks.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 30f), Array.Empty<object>()));
SprintMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "SprintMultiplier", 2f, new ConfigDescription("Speed multiplier while holding the sprint key.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
AttackChargeSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "AttackChargeSeconds", 0.8f, new ConfigDescription("How long the ghost glows before exploding after the attack is triggered.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 3f), Array.Empty<object>()));
AttackRevertSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "AttackRevertSeconds", 1f, new ConfigDescription("Seconds after the explosion until the player automatically reverts to normal.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.3f, 6f), Array.Empty<object>()));
AttackRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "AttackRadius", 10f, new ConfigDescription("Radius in which nearby players are knocked down by the ghost explosion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 30f), Array.Empty<object>()));
KnockbackForce = ((BaseUnityPlugin)this).Config.Bind<float>("Ghost", "KnockbackForce", 15f, new ConfigDescription("How strongly nearby players are launched by the ghost explosion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 40f), Array.Empty<object>()));
CameraDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Distance", 16f, new ConfigDescription("Third-person ghost camera distance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 30f), Array.Empty<object>()));
CameraHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Height", 5f, new ConfigDescription("Third-person ghost camera height above the player.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(2f, 14f), Array.Empty<object>()));
CameraFov = ((BaseUnityPlugin)this).Config.Bind<float>("Camera", "Fov", 80f, new ConfigDescription("Field of view while in ghost form.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(60f, 110f), Array.Empty<object>()));
ShowGhostVisual = ((BaseUnityPlugin)this).Config.Bind<bool>("Ghost", "ShowGhostVisual", true, "Show the big ghost visual while transformed.");
((BaseUnityPlugin)this).Logger.LogInfo((object)"[I'm a Ghost] Loaded version 0.1.0.");
}
private void ConfigureOptionalCharacterPatches()
{
TryPatchOptionalCharacterMethod("RPCA_Die", Type.EmptyTypes, "CharacterRpcDiePrefix", "Character.RPCA_Die()");
TryPatchOptionalCharacterMethod("RPCA_SetDead", Type.EmptyTypes, "CharacterRpcSetDeadPrefix", "Character.RPCA_SetDead()");
TryPatchOptionalCharacterMethod("RPCA_PassOut", Type.EmptyTypes, "CharacterRpcPassOutPrefix", "Character.RPCA_PassOut()");
TryPatchOptionalCharacterMethod("DieInstantly", Type.EmptyTypes, "CharacterDieInstantlyPrefix", "Character.DieInstantly()");
TryPatchOptionalCharacterMethod("HandleDeath", Type.EmptyTypes, "CharacterHandleDeathPrefix", "Character.HandleDeath()");
TryPatchOptionalCharacterMethod("WarpPlayerRPC", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, "CharacterWarpPlayerRpcPrefix", "Character.WarpPlayerRPC(Vector3,bool)");
TryPatchOptionalCharacterMethod("WarpPlayer", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, "CharacterWarpPlayerPrefix", "Character.WarpPlayer(Vector3,bool)");
TryPatchOptionalCharacterMethod("Fall", new Type[2]
{
typeof(float),
typeof(float)
}, "CharacterFallPrefix", "Character.Fall(float,float)");
TryPatchOptionalCharacterMethod("RPCA_Fall", new Type[2]
{
typeof(float),
typeof(float)
}, "CharacterRpcFallPrefix", "Character.RPCA_Fall(float,float)");
}
private void TryPatchOptionalCharacterMethod(string methodName, Type[] parameterTypes, string prefixName, string description)
{
//IL_007c: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: Expected O, but got Unknown
try
{
MethodInfo methodInfo = AccessTools.Method(typeof(Character), methodName, parameterTypes, (Type[])null);
if (methodInfo == null)
{
((BaseUnityPlugin)this).Logger.LogInfo((object)("[I'm a Ghost] Optional " + description + " patch skipped; method is not present in this game build."));
return;
}
MethodInfo methodInfo2 = AccessTools.Method(typeof(GhostHarmonyPatches), prefixName, (Type[])null, (Type[])null);
if (methodInfo2 == null)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Ghost] Optional " + description + " patch skipped; prefix method was not found."));
}
else
{
_harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
}
}
catch (Exception ex)
{
((BaseUnityPlugin)this).Logger.LogWarning((object)("[I'm a Ghost] Optional " + description + " patch failed: " + ex.Message));
}
}
private void Update()
{
//IL_0005: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
try
{
if ((int)ToggleKey.Value != 0)
{
bool key = Input.GetKey(ToggleKey.Value);
if (key && !_lastTogglePressed)
{
ToggleGhostForm();
}
_lastTogglePressed = key;
if ((Object)(object)_controller != (Object)null && _controller.Active && !_controller.IsValid())
{
ForceExit();
}
if ((Object)(object)_controller != (Object)null && _controller.Active && !IsInLobby())
{
ForceExit();
}
}
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Ghost] Plugin.Update: " + ex));
}
}
}
private void OnDestroy()
{
try
{
ForceExit();
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[I'm a Ghost] Exit during cleanup failed: " + ex.Message));
}
}
try
{
_harmony.UnpatchSelf();
}
catch (Exception ex2)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)("[I'm a Ghost] Harmony unpatch failed (non-fatal): " + ex2.Message));
}
}
}
private void ToggleGhostForm()
{
if (_switching)
{
return;
}
if ((Object)(object)_controller != (Object)null && _controller.Active)
{
ExitGhost();
return;
}
Character localCharacter = Character.localCharacter;
if (CanTransform(localCharacter))
{
_switching = true;
((MonoBehaviour)this).StartCoroutine(EnterGhostRoutine(localCharacter));
}
}
private static bool CanTransform(Character character)
{
if (!IsInLobby())
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)"[I'm a Ghost] Ghost form is only available in the Airport lobby.");
}
return false;
}
if ((Object)(object)character == (Object)null)
{
ManualLogSource log2 = Log;
if (log2 != null)
{
log2.LogWarning((object)"[I'm a Ghost] No local character found.");
}
return false;
}
if (GhostController.IsLocalGhostCharacter(character))
{
ManualLogSource log3 = Log;
if (log3 != null)
{
log3.LogWarning((object)"[I'm a Ghost] Already in ghost form.");
}
return false;
}
if (character.isZombie || character.isBot || character.isScoutmaster)
{
ManualLogSource log4 = Log;
if (log4 != null)
{
log4.LogWarning((object)"[I'm a Ghost] Cannot transform while in another special form.");
}
return false;
}
if ((Object)(object)character.data == (Object)null || character.refs == null || (Object)(object)((MonoBehaviourPun)character).photonView == (Object)null)
{
ManualLogSource log5 = Log;
if (log5 != null)
{
log5.LogWarning((object)"[I'm a Ghost] Local character is not ready yet.");
}
return false;
}
if (character.data.dead || character.data.passedOut || character.data.fullyPassedOut || character.data.fallSeconds > 0f || character.data.isClimbing || character.data.isRopeClimbing || character.data.isVineClimbing)
{
ManualLogSource log6 = Log;
if (log6 != null)
{
log6.LogWarning((object)"[I'm a Ghost] Local character is not in a valid state to transform.");
}
return false;
}
return true;
}
private IEnumerator EnterGhostRoutine(Character character)
{
try
{
_controller = ((Component)character).gameObject.GetComponent<GhostController>();
if ((Object)(object)_controller == (Object)null)
{
_controller = ((Component)character).gameObject.AddComponent<GhostController>();
}
_controller.EnterGhost(character);
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Ghost] Failed to enter ghost form:\n" + ex));
}
_controller = null;
}
finally
{
_switching = false;
}
yield break;
}
private void ExitGhost()
{
_switching = true;
try
{
_controller?.ExitGhost();
_controller = null;
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogError((object)("[I'm a Ghost] Failed to exit ghost form:\n" + ex));
}
}
finally
{
_switching = false;
}
}
private void ForceExit()
{
if ((Object)(object)_controller == (Object)null)
{
return;
}
try
{
_controller.ExitGhost();
}
catch (Exception ex)
{
ManualLogSource log = Log;
if (log != null)
{
log.LogWarning((object)("[I'm a Ghost] ForceExit failed: " + ex.Message));
}
}
_controller = null;
}
}
[DefaultExecutionOrder(600)]
public sealed class GhostController : MonoBehaviour
{
private const float VelocitySharpness = 7f;
private const float MaxVelocity = 55f;
private const float AngularVelocityDamping = 0.92f;
private const float MaxAngularVelocity = 10f;
private const float GroundClearanceMin = 0.8f;
private const float BallFaceMoveSharpness = 6f;
private const float CameraLookAhead = 4f;
private const float CameraCollisionRadius = 0.35f;
private const float CameraTerrainClearance = 0.8f;
private const float CameraSmoothTime = 0.08f;
private const float CameraRotationSharpness = 12f;
private const float DefaultCameraDistance = 16f;
private const float DefaultCameraHeight = 5f;
private const float DefaultCameraFov = 80f;
private Character _character;
private Vector3 _prevCenter;
private Vector3 _cameraVelocity;
private Vector3 _cameraSmoothedPosition;
private Quaternion _cameraSmoothedRotation;
private bool _cameraHasSmoothedPosition;
private Vector3 _moveDirection;
private GameObject _ghostVisualRoot;
private GhostBall _ghostBall;
private PhotonView _ghostPhotonView;
private Rigidbody _ghostRigidbody;
private Animator _ghostAnimator;
private bool _ghostIsNetworked;
private bool _attacking;
private float _attackStartedAt;
private bool _attackExploded;
internal const string NetworkVisualMarker = "ImGhost.Visual";
private static readonly FieldInfo ReadyToExplodeField = typeof(GhostBall).GetField("_readyToExplode", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo ExplodingField = typeof(GhostBall).GetField("exploding", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly FieldInfo TickUntilDespawnField = typeof(GhostBall).GetField("tickUntilDespawn", BindingFlags.Instance | BindingFlags.NonPublic);
private static readonly int AnReadyToExplode = Animator.StringToHash("ReadyToExplode");
private static readonly int AnFadeOut = Animator.StringToHash("FadeOut");
private static readonly int AnExploded = Animator.StringToHash("Exploded");
private readonly Dictionary<GameObject, bool> _hiddenHudStates = new Dictionary<GameObject, bool>();
public static GhostBall ActiveGhostBall { get; private set; }
public static Character ActiveGhostCharacter { get; private set; }
public bool Active { get; private set; }
public Character CharacterRef => _character;
public bool IsValid()
{
if (!Active || (Object)(object)_character == (Object)null || (Object)(object)_character.data == (Object)null)
{
return false;
}
if (!_character.data.dead)
{
return !_character.data.fullyPassedOut;
}
return false;
}
private static void LogInfo(string message)
{
ManualLogSource log = GhostPlugin.Log;
if (log != null)
{
log.LogInfo((object)("[I'm a Ghost] " + message));
}
}
private static void LogError(string entryPoint, Exception ex)
{
ManualLogSource log = GhostPlugin.Log;
if (log != null)
{
log.LogError((object)("[I'm a Ghost] " + entryPoint + ": " + ex));
}
}
public static bool IsLocalGhostCharacter(Character character)
{
if ((Object)(object)character == (Object)null || !character.IsLocal)
{
return false;
}
GhostController component = ((Component)character).GetComponent<GhostController>();
if ((Object)(object)component != (Object)null)
{
return component.Active;
}
return false;
}
public void EnterGhost(Character character)
{
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
_character = character;
_prevCenter = character.Center;
_cameraVelocity = Vector3.zero;
_cameraHasSmoothedPosition = false;
_attacking = false;
_attackExploded = false;
_attackStartedAt = 0f;
Active = true;
ActiveGhostCharacter = character;
((Behaviour)this).enabled = true;
BuildGhostVisual();
HideHud();
LogInfo("Entered ghost form.");
}
public void ExitGhost()
{
if (Active || !((Object)(object)_ghostVisualRoot == (Object)null))
{
Active = false;
ActiveGhostCharacter = null;
((Behaviour)this).enabled = false;
_attacking = false;
_attackExploded = false;
_attackStartedAt = 0f;
DestroyGhostVisual();
RestoreHud();
LogInfo("Exited ghost form.");
}
}
private void Update()
{
if (!Active || (Object)(object)_character == (Object)null)
{
return;
}
try
{
ClearNonMovementInput();
KeepPlayerAlive();
UpdateAttack();
if (Active)
{
UpdateGhostVisual();
HideHud();
}
}
catch (Exception ex)
{
LogError("GhostController.Update", ex);
}
}
private void FixedUpdate()
{
if (!Active || (Object)(object)_character == (Object)null || _character.refs == null || (Object)(object)_character.refs.ragdoll == (Object)null)
{
return;
}
try
{
ApplyMovementVelocity();
StabilizeRagdoll();
}
catch (Exception ex)
{
LogError("GhostController.FixedUpdate", ex);
}
}
private void LateUpdate()
{
if (!Active || (Object)(object)_character == (Object)null)
{
return;
}
try
{
SyncCharacterData();
RefreshCamera();
}
catch (Exception ex)
{
LogError("GhostController.LateUpdate", ex);
}
}
private void OnDestroy()
{
if (Active)
{
Active = false;
ActiveGhostCharacter = null;
DestroyGhostVisual();
RestoreHud();
}
}
private void HideHud()
{
if (_hiddenHudStates.Count < 2)
{
TryHideCanvas("Canvas_HUD");
TryHideCanvas("Canvas_Names");
}
}
private void TryHideCanvas(string canvasName)
{
GameObject val = GameObject.Find(canvasName);
if (!((Object)(object)val == (Object)null) && !_hiddenHudStates.ContainsKey(val))
{
_hiddenHudStates[val] = val.activeSelf;
if (val.activeSelf)
{
val.SetActive(false);
}
}
}
private void RestoreHud()
{
if (_hiddenHudStates.Count == 0)
{
return;
}
foreach (KeyValuePair<GameObject, bool> hiddenHudState in _hiddenHudStates)
{
if ((Object)(object)hiddenHudState.Key != (Object)null)
{
hiddenHudState.Key.SetActive(hiddenHudState.Value);
}
}
_hiddenHudStates.Clear();
}
private void ClearNonMovementInput()
{
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.input == (Object)null))
{
_character.input.jumpWasPressed = false;
_character.input.jumpIsPressed = false;
_character.input.sprintIsPressed = false;
_character.input.sprintWasPressed = false;
_character.input.sprintToggleWasPressed = false;
_character.input.usePrimaryWasPressed = false;
_character.input.usePrimaryIsPressed = false;
_character.input.useSecondaryWasPressed = false;
_character.input.useSecondaryIsPressed = false;
_character.input.crouchWasPressed = false;
_character.input.crouchIsPressed = false;
_character.input.crouchToggleWasPressed = false;
_character.input.dropWasPressed = false;
_character.input.dropIsPressed = false;
_character.input.interactWasPressed = false;
_character.input.interactIsPressed = false;
}
}
private void KeepPlayerAlive()
{
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null))
{
_character.data.dead = false;
_character.data.zombified = false;
_character.data.passedOut = false;
_character.data.fullyPassedOut = false;
_character.data.fallSeconds = 0f;
_character.data.isSprinting = false;
}
}
private Vector2 GetMovementInput()
{
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_003a: Unknown result type (might be due to invalid IL or missing references)
//IL_0056: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_character == (Object)null || (Object)(object)_character.input == (Object)null)
{
return Vector2.zero;
}
Vector2 movementInput = _character.input.movementInput;
movementInput.x = Mathf.Clamp(movementInput.x, -1f, 1f);
movementInput.y = Mathf.Clamp(movementInput.y, -1f, 1f);
return movementInput;
}
private void ApplyMovementVelocity()
{
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: 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_00ba: 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_00f6: Unknown result type (might be due to invalid IL or missing references)
//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0105: Unknown result type (might be due to invalid IL or missing references)
//IL_010a: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Unknown result type (might be due to invalid IL or missing references)
//IL_0126: Unknown result type (might be due to invalid IL or missing references)
//IL_012b: Unknown result type (might be due to invalid IL or missing references)
//IL_012c: Unknown result type (might be due to invalid IL or missing references)
//IL_0131: Unknown result type (might be due to invalid IL or missing references)
//IL_0135: Unknown result type (might be due to invalid IL or missing references)
//IL_013a: Unknown result type (might be due to invalid IL or missing references)
//IL_013b: Unknown result type (might be due to invalid IL or missing references)
//IL_013c: Unknown result type (might be due to invalid IL or missing references)
//IL_0142: Unknown result type (might be due to invalid IL or missing references)
//IL_0147: Unknown result type (might be due to invalid IL or missing references)
//IL_0148: Unknown result type (might be due to invalid IL or missing references)
//IL_014e: Unknown result type (might be due to invalid IL or missing references)
//IL_0153: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0119: Unknown result type (might be due to invalid IL or missing references)
//IL_011e: Unknown result type (might be due to invalid IL or missing references)
//IL_017a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
//IL_0186: Unknown result type (might be due to invalid IL or missing references)
//IL_01cf: 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_0071: Unknown result type (might be due to invalid IL or missing references)
//IL_0076: Unknown result type (might be due to invalid IL or missing references)
//IL_0083: Unknown result type (might be due to invalid IL or missing references)
//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
//IL_0208: Unknown result type (might be due to invalid IL or missing references)
//IL_020d: Unknown result type (might be due to invalid IL or missing references)
//IL_021f: Unknown result type (might be due to invalid IL or missing references)
//IL_0224: Unknown result type (might be due to invalid IL or missing references)
//IL_022b: Unknown result type (might be due to invalid IL or missing references)
//IL_0230: Unknown result type (might be due to invalid IL or missing references)
//IL_01db: 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_029f: Unknown result type (might be due to invalid IL or missing references)
//IL_0298: Unknown result type (might be due to invalid IL or missing references)
//IL_025d: Unknown result type (might be due to invalid IL or missing references)
//IL_02a0: 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_02f7: Unknown result type (might be due to invalid IL or missing references)
//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
//IL_0309: Unknown result type (might be due to invalid IL or missing references)
//IL_030e: Unknown result type (might be due to invalid IL or missing references)
//IL_0312: Unknown result type (might be due to invalid IL or missing references)
//IL_0319: Unknown result type (might be due to invalid IL or missing references)
if (_attacking)
{
_moveDirection = Vector3.zero;
Vector3 zero = Vector3.zero;
{
foreach (Bodypart part in _character.refs.ragdoll.partList)
{
Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null);
if (!((Object)(object)val == (Object)null) && !val.isKinematic)
{
val.linearVelocity = Vector3.Lerp(val.linearVelocity, zero, Time.fixedDeltaTime * 7f);
}
}
return;
}
}
Vector3 val2 = (((Object)(object)_character.data != (Object)null) ? _character.data.lookDirection_Flat : Vector3.zero);
if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
{
val2 = Vector3.ProjectOnPlane(((Component)this).transform.forward, Vector3.up);
}
Vector3 val3 = Vector3.ProjectOnPlane(val2, Vector3.up);
val2 = ((Vector3)(ref val3)).normalized;
if (((Vector3)(ref val2)).sqrMagnitude < 0.0001f)
{
val2 = Vector3.forward;
}
Vector2 movementInput = GetMovementInput();
val3 = Vector3.Cross(Vector3.up, val2);
Vector3 normalized = ((Vector3)(ref val3)).normalized;
Vector3 val4 = val2 * movementInput.y + normalized * movementInput.x;
if (((Vector3)(ref val4)).sqrMagnitude > 1f)
{
((Vector3)(ref val4)).Normalize();
}
float num = 0f;
if ((int)GhostPlugin.UpKey.Value != 0 && Input.GetKey(GhostPlugin.UpKey.Value))
{
num += 1f;
}
if ((int)GhostPlugin.DownKey.Value != 0 && Input.GetKey(GhostPlugin.DownKey.Value))
{
num -= 1f;
}
float num2 = 1f;
if ((int)GhostPlugin.SprintKey.Value != 0 && Input.GetKey(GhostPlugin.SprintKey.Value))
{
num2 = Mathf.Max(1f, GhostPlugin.SprintMultiplier.Value);
}
Vector3 val5 = (val4 * GhostPlugin.MovementSpeed.Value + Vector3.up * (num * GhostPlugin.VerticalSpeed.Value)) * num2;
if (num < 0f)
{
float groundHeight = GetGroundHeight(_character.Center);
if (!float.IsNaN(groundHeight) && _character.Center.y <= groundHeight + 0.8f)
{
val5.y = Mathf.Max(val5.y, 0f);
}
}
_moveDirection = ((((Vector3)(ref val4)).sqrMagnitude > 0.0001f) ? val4 : Vector3.zero);
foreach (Bodypart part2 in _character.refs.ragdoll.partList)
{
Rigidbody val6 = (((Object)(object)part2 != (Object)null) ? part2.Rig : null);
if (!((Object)(object)val6 == (Object)null) && !val6.isKinematic)
{
Vector3 val7 = Vector3.Lerp(val6.linearVelocity, val5, Time.fixedDeltaTime * 7f);
val6.linearVelocity = Vector3.ClampMagnitude(val7, 55f);
}
}
}
private float GetGroundHeight(Vector3 position)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_000b: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Unknown result type (might be due to invalid IL or missing references)
//IL_0050: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0077: Unknown result type (might be due to invalid IL or missing references)
try
{
RaycastHit groundPosRaycast = HelperFunctions.GetGroundPosRaycast(position + Vector3.up * 400f, (LayerType)2, 0f);
if ((Object)(object)((RaycastHit)(ref groundPosRaycast)).transform != (Object)null)
{
return ((RaycastHit)(ref groundPosRaycast)).point.y;
}
}
catch
{
}
try
{
RaycastHit groundPosRaycast2 = HelperFunctions.GetGroundPosRaycast(position + Vector3.up * 400f, (LayerType)1, 0f);
if ((Object)(object)((RaycastHit)(ref groundPosRaycast2)).transform != (Object)null)
{
return ((RaycastHit)(ref groundPosRaycast2)).point.y;
}
}
catch
{
}
return float.NaN;
}
private void StabilizeRagdoll()
{
//IL_0073: 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_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_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
//IL_00aa: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
if ((Object)(object)_character.refs.ragdoll == (Object)null)
{
return;
}
foreach (Bodypart part in _character.refs.ragdoll.partList)
{
Rigidbody val = (((Object)(object)part != (Object)null) ? part.Rig : null);
if (!((Object)(object)val == (Object)null) && !val.isKinematic)
{
val.useGravity = false;
part.forcesToAdd = Vector3.zero;
val.angularVelocity *= 0.92f;
Vector3 angularVelocity = val.angularVelocity;
if (((Vector3)(ref angularVelocity)).magnitude > 10f)
{
val.angularVelocity = Vector3.ClampMagnitude(val.angularVelocity, 10f);
}
if (val.linearVelocity.y < -55f)
{
Vector3 linearVelocity = val.linearVelocity;
linearVelocity.y = -55f;
val.linearVelocity = linearVelocity;
}
}
}
}
private void SyncCharacterData()
{
//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_0047: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
//IL_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0067: 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_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_008a: 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_009b: Unknown result type (might be due to invalid IL or missing references)
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
//IL_00bc: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_character == (Object)null) && !((Object)(object)_character.data == (Object)null))
{
Vector3 center = _character.Center;
Vector3 avarageVelocity = ((((Vector3)(ref _prevCenter)).sqrMagnitude > 0f) ? ((center - _prevCenter) / Mathf.Max(Time.deltaTime, 0.0001f)) : Vector3.zero);
_prevCenter = center;
_character.data.avarageLastFrameVelocity = _character.data.avarageVelocity;
_character.data.avarageVelocity = avarageVelocity;
_character.data.worldMovementInput = (_character.data.worldMovementInput_Grounded = Vector3.zero);
_character.data.sinceGrounded = Mathf.Min(_character.data.sinceGrounded, 0.1f);
}
}
private void UpdateAttack()
{
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
if (!_attacking)
{
if ((int)GhostPlugin.AttackKey.Value != 0 && Input.GetKeyDown(GhostPlugin.AttackKey.Value))
{
StartAttack();
}
return;
}
float num = Time.unscaledTime - _attackStartedAt;
if (!_attackExploded && num >= GhostPlugin.AttackChargeSeconds.Value)
{
_attackExploded = true;
DoExplode();
}
if (num >= GhostPlugin.AttackChargeSeconds.Value + GhostPlugin.AttackRevertSeconds.Value)
{
ExitGhost();
}
}
private void StartAttack()
{
_attacking = true;
_attackExploded = false;
_attackStartedAt = Time.unscaledTime;
SetGhostValue(ReadyToExplodeField, true);
if ((Object)(object)_ghostAnimator != (Object)null)
{
_ghostAnimator.SetBool(AnReadyToExplode, true);
}
LogInfo("Ghost attack charging...");
}
private void DoExplode()
{
//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)
LogInfo("Ghost attack exploded!");
if ((Object)(object)_ghostBall != (Object)null && (Object)(object)_ghostBall.explosionPrefab != (Object)null)
{
try
{
Object.Instantiate<GameObject>(_ghostBall.explosionPrefab, _character.Center, Quaternion.identity);
}
catch (Exception ex)
{
LogError("GhostController.DoExplode (explosion prefab)", ex);
}
}
SetGhostValue(ExplodingField, true);
if ((Object)(object)_ghostAnimator != (Object)null)
{
_ghostAnimator.SetBool(AnExploded, true);
}
KnockDownNearbyPlayers();
}
private void KnockDownNearbyPlayers()
{
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
//IL_00ad: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
//IL_00d6: Unknown result type (might be due to invalid IL or missing references)
//IL_00db: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
//IL_010d: Unknown result type (might be due to invalid IL or missing references)
//IL_0117: Unknown result type (might be due to invalid IL or missing references)
float value = GhostPlugin.AttackRadius.Value;
float value2 = GhostPlugin.KnockbackForce.Value;
Vector3 center = _character.Center;
foreach (Character allCharacter in Character.AllCharacters)
{
if ((Object)(object)allCharacter == (Object)null || (Object)(object)allCharacter == (Object)(object)_character || (Object)(object)allCharacter.data == (Object)null || !allCharacter.data.fullyConscious || allCharacter.refs == null || (Object)(object)allCharacter.refs.view == (Object)null)
{
continue;
}
Vector3 val = allCharacter.Center - center;
float magnitude = ((Vector3)(ref val)).magnitude;
if (!(magnitude > value) && !(magnitude < 0.001f))
{
Vector3 val2 = val / magnitude * value2 + Vector3.up * (value2 * 0.55f);
try
{
allCharacter.refs.view.RPC("RPCA_AddForceAtPosition", (RpcTarget)0, new object[3] { val2, center, value });
}
catch (Exception ex)
{
LogError("GhostController.KnockDownNearbyPlayers (force)", ex);
}
try
{
allCharacter.refs.view.RPC("RPCA_Fall", (RpcTarget)0, new object[2] { 1.2f, 0.25f });
}
catch (Exception ex2)
{
LogError("GhostController.KnockDownNearbyPlayers (fall)", ex2);
}
}
}
}
private static void SetGhostValue(FieldInfo field, object value)
{
try
{
if (field != null && (Object)(object)ActiveGhostBall != (Object)null)
{
field.SetValue(ActiveGhostBall, value);
}
}
catch
{
}
}
private void BuildGhostVisual()
{
if ((Object)(object)_ghostVisualRoot != (Object)null || (Object)(object)_character == (Object)null)
{
return;
}
try
{
GameObject val = Resources.Load<GameObject>("GhostBall");
if ((Object)(object)val == (Object)null)
{
LogInfo("Resources.Load(\"GhostBall\") returned null; no ghost visual will be shown.");
}
else if (PhotonNetwork.InRoom && (Object)(object)((MonoBehaviourPun)_character).photonView != (Object)null && ((MonoBehaviourPun)_character).photonView.ViewID > 0)
{
BuildNetworkedGhost(val);
}
else
{
BuildLocalGhost(val);
}
}
catch (Exception ex)
{
LogError("GhostController.BuildGhostVisual", ex);
DestroyGhostVisual();
}
}
private void BuildNetworkedGhost(GameObject prefab)
{
//IL_000b: 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)
GameObject val = PhotonNetwork.Instantiate("GhostBall", _character.Center, Quaternion.identity, (byte)0, new object[2]
{
"ImGhost.Visual",
((MonoBehaviourPun)_character).photonView.ViewID
});
((Object)val).name = "ImGhostNetworked";
_ghostVisualRoot = val;
_ghostIsNetworked = true;
_ghostBall = val.GetComponent<GhostBall>();
ActiveGhostBall = _ghostBall;
_ghostPhotonView = val.GetComponent<PhotonView>();
_ghostRigidbody = val.GetComponent<Rigidbody>();
_ghostAnimator = val.GetComponent<Animator>();
if ((Object)(object)_ghostRigidbody != (Object)null)
{
_ghostRigidbody.isKinematic = true;
}
KeepGhostAliveIndefinitely();
val.SetActive(GhostPlugin.ShowGhostVisual.Value);
LogInfo("Spawned networked ghost visual with vanilla GhostBall prefab.");
}
private void BuildLocalGhost(GameObject prefab)
{
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_000c: Unknown result type (might be due to invalid IL or missing references)
GameObject val = Object.Instantiate<GameObject>(prefab, _character.Center, Quaternion.identity);
((Object)val).name = "ImGhostLocal";
_ghostVisualRoot = val;
_ghostIsNetworked = false;
_ghostBall = val.GetComponent<GhostBall>();
ActiveGhostBall = _ghostBall;
_ghostRigidbody = val.GetComponent<Rigidbody>();
_ghostAnimator = val.GetComponent<Animator>();
if ((Object)(object)_ghostBall != (Object)null)
{
((Behaviour)_ghostBall).enabled = false;
}
if ((Object)(object)_ghostRigidbody != (Object)null)
{
_ghostRigidbody.isKinematic = true;
}
IgnoreCollisionWithOwnRagdoll(val);
KeepGhostAliveIndefinitely();
val.SetActive(GhostPlugin.ShowGhostVisual.Value);
LogInfo("Spawned local-only ghost visual (offline / single-player).");
}
private void KeepGhostAliveIndefinitely()
{
SetGhostValue(TickUntilDespawnField, -1000f);
if ((Object)(object)_ghostBall != (Object)null)
{
_ghostBall.lifetime = 9999f;
}
}
private static void IgnoreCollisionWithOwnRagdoll(GameObject ghostRoot)
{
Character activeGhostCharacter = ActiveGhostCharacter;
if ((Object)(object)activeGhostCharacter == (Object)null || activeGhostCharacter.refs == null || (Object)(object)activeGhostCharacter.refs.ragdoll == (Object)null)
{
return;
}
Collider[] componentsInChildren = ghostRoot.GetComponentsInChildren<Collider>(true);
if (componentsInChildren.Length == 0)
{
return;
}
foreach (Bodypart part in activeGhostCharacter.refs.ragdoll.partList)
{
if ((Object)(object)part == (Object)null)
{
continue;
}
Collider[] componentsInChildren2 = ((Component)part).GetComponentsInChildren<Collider>(true);
Collider[] array = componentsInChildren;
foreach (Collider val in array)
{
Collider[] array2 = componentsInChildren2;
foreach (Collider val2 in array2)
{
if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && val.enabled && val2.enabled)
{
try
{
Physics.IgnoreCollision(val, val2, true);
}
catch
{
}
}
}
}
}
}
internal static void IgnoreCollisionWithCharacter(GameObject ghostRoot, Character character)
{
if ((Object)(object)ghostRoot == (Object)null || (Object)(object)character == (Object)null || character.refs == null || (Object)(object)character.refs.ragdoll == (Object)null)
{
return;
}
Collider[] componentsInChildren = ghostRoot.GetComponentsInChildren<Collider>(true);
if (componentsInChildren.Length == 0)
{
return;
}
foreach (Bodypart part in character.refs.ragdoll.partList)
{
if ((Object)(object)part == (Object)null)
{
continue;
}
Collider[] componentsInChildren2 = ((Component)part).GetComponentsInChildren<Collider>(true);
Collider[] array = componentsInChildren;
foreach (Collider val in array)
{
Collider[] array2 = componentsInChildren2;
foreach (Collider val2 in array2)
{
if ((Object)(object)val != (Object)null && (Object)(object)val2 != (Object)null && val.enabled && val2.enabled)
{
try
{
Physics.IgnoreCollision(val, val2, true);
}
catch
{
}
}
}
}
}
}
private void UpdateGhostVisual()
{
//IL_005a: 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_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)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_009d: Unknown result type (might be due to invalid IL or missing references)
//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
if (!((Object)(object)_ghostVisualRoot == (Object)null) && !((Object)(object)_character == (Object)null))
{
if (_ghostVisualRoot.activeSelf != GhostPlugin.ShowGhostVisual.Value)
{
_ghostVisualRoot.SetActive(GhostPlugin.ShowGhostVisual.Value);
}
_ghostVisualRoot.transform.position = _character.Center;
if (((Vector3)(ref _moveDirection)).sqrMagnitude > 0.01f)
{
Quaternion val = Quaternion.LookRotation(_moveDirection, Vector3.up);
_ghostVisualRoot.transform.rotation = Quaternion.Slerp(_ghostVisualRoot.transform.rotation, val, Time.deltaTime * 6f);
}
}
}
private void DestroyGhostVisual()
{
ActiveGhostBall = null;
if ((Object)(object)_ghostVisualRoot != (Object)null)
{
if (_ghostIsNetworked && PhotonNetwork.InRoom)
{
try
{
PhotonNetwork.Destroy(_ghostVisualRoot);
}
catch
{
}
}
else
{
Object.Destroy((Object)(object)_ghostVisualRoot);
}
}
_ghostVisualRoot = null;
_ghostBall = null;
_ghostPhotonView = null;
_ghostRigidbody = null;
_ghostAnimator = null;
_ghostIsNetworked = false;
}
private void RefreshCamera()
{
//IL_001a: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
//IL_0070: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Unknown result type (might be due to invalid IL or missing references)
//IL_007b: Unknown result type (might be due to invalid IL or missing references)
//IL_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0081: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
//IL_00a9: 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_003c: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
//IL_004a: Unknown result type (might be due to invalid IL or missing references)
//IL_004f: Unknown result type (might be due to invalid IL or missing references)
//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
try
{
Camera main = Camera.main;
if (!((Object)(object)main == (Object)null))
{
Vector3 thirdPersonCameraLookTarget = GetThirdPersonCameraLookTarget(_character);
Vector3 val = ResolveCameraCollision(thirdPersonCameraLookTarget, GetThirdPersonCameraPosition(_character));
if (!_cameraHasSmoothedPosition)
{
_cameraSmoothedPosition = val;
_cameraSmoothedRotation = GetCameraRotation(_cameraSmoothedPosition, thirdPersonCameraLookTarget);
_cameraHasSmoothedPosition = true;
}
else
{
_cameraSmoothedPosition = Vector3.SmoothDamp(_cameraSmoothedPosition, val, ref _cameraVelocity, 0.08f);
Quaternion cameraRotation = GetCameraRotation(_cameraSmoothedPosition, thirdPersonCameraLookTarget);
float num = 1f - Mathf.Exp(-12f * Time.deltaTime);
_cameraSmoothedRotation = Quaternion.Slerp(_cameraSmoothedRotation, cameraRotation, num);
}
((Component)main).transform.SetPositionAndRotation(_cameraSmoothedPosition, _cameraSmoothedRotation);
main.fieldOfView = Mathf.Lerp(main.fieldOfView, GetCameraFov(), Time.deltaTime * 4f);
}
}
catch (Exception ex)
{
LogError("GhostController.RefreshCamera", ex);
}
}
private static Vector3 GetThirdPersonCameraPosition(Character character)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
//IL_0022: Unknown result type (might be due to invalid IL or missing references)
//IL_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)
Vector3 cameraForward = GetCameraForward(character);
return character.Center + Vector3.up * (GetCameraHeight() + 2f) - cameraForward * GetCameraDistance();
}
private static Vector3 GetThirdPersonCameraLookTarget(Character character)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0015: 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_0043: 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_005a: Unknown result type (might be due to invalid IL or missing references)
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
//IL_0065: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
Vector3 cameraForward = GetCameraForward(character);
float num = Mathf.Clamp((((Object)(object)character.data != (Object)null) ? ((Vector3)(ref character.data.lookDirection)).normalized : cameraForward).y, -0.35f, 0.65f);
return character.Center + Vector3.up * (GetCameraHeight() + num * 3f) + cameraForward * 4f;
}
private static float GetCameraDistance()
{
return Mathf.Clamp((GhostPlugin.CameraDistance != null) ? GhostPlugin.CameraDistance.Value : 16f, 8f, 30f);
}
private static float GetCameraHeight()
{
return Mathf.Clamp((GhostPlugin.CameraHeight != null) ? GhostPlugin.CameraHeight.Value : 5f, 2f, 14f);
}
private static float GetCameraFov()
{
return Mathf.Clamp((GhostPlugin.CameraFov != null) ? GhostPlugin.CameraFov.Value : 80f, 60f, 110f);
}
private static Vector3 GetCameraForward(Character character)
{
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0021: Unknown result type (might be due to invalid IL or missing references)
//IL_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_002c: Unknown result type (might be due to invalid IL or missing references)
//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_0080: Unknown result type (might be due to invalid IL or missing references)
//IL_0085: Unknown result type (might be due to invalid IL or missing references)
//IL_0052: Unknown result type (might be due to invalid IL or missing references)
//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_0061: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0099: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = (((Object)(object)character.data != (Object)null) ? character.data.lookDirection_Flat : Vector3.zero);
val = Vector3.ProjectOnPlane(val, Vector3.up);
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f && (Object)(object)Camera.main != (Object)null)
{
val = Vector3.ProjectOnPlane(((Component)Camera.main).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.ProjectOnPlane(((Component)character).transform.forward, Vector3.up);
}
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.forward;
}
return ((Vector3)(ref val)).normalized;
}
private Vector3 ResolveCameraCollision(Vector3 lookTarget, Vector3 desiredPosition)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000e: 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_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_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_003b: Unknown result type (might be due to invalid IL or missing references)
//IL_006a: Unknown result type (might be due to invalid IL or missing references)
//IL_004d: Unknown result type (might be due to invalid IL or missing references)
RaycastHit val = HelperFunctions.LineCheck(lookTarget, desiredPosition, (LayerType)1, 0.35f, (QueryTriggerInteraction)1);
if ((Object)(object)((RaycastHit)(ref val)).transform != (Object)null)
{
desiredPosition = ((RaycastHit)(ref val)).point + ((RaycastHit)(ref val)).normal * 0.8f;
}
float groundHeight = GetGroundHeight(desiredPosition);
if (!float.IsNaN(groundHeight) && desiredPosition.y < groundHeight + 0.8f)
{
desiredPosition.y = groundHeight + 0.8f;
}
return desiredPosition;
}
private static Quaternion GetCameraRotation(Vector3 cameraPosition, Vector3 lookTarget)
{
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_001e: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Unknown result type (might be due to invalid IL or missing references)
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Unknown result type (might be due to invalid IL or missing references)
Vector3 val = lookTarget - cameraPosition;
if (((Vector3)(ref val)).sqrMagnitude < 0.0001f)
{
val = Vector3.forward;
}
return Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up);
}
}
[HarmonyPatch]
public static class GhostHarmonyPatches
{
private static readonly HashSet<int> CollisionIgnoredInstances = new HashSet<int>();
private static bool IsGhostVisual(GhostBall ghostBall)
{
if ((Object)(object)ghostBall == (Object)null)
{
return false;
}
PhotonView component = ((Component)ghostBall).GetComponent<PhotonView>();
object[] array = (((Object)(object)component != (Object)null) ? component.InstantiationData : null);
if (array != null && array.Length != 0 && array[0] is string text)
{
return text == "ImGhost.Visual";
}
return false;
}
private static bool IsGhost(Character character)
{
return GhostController.IsLocalGhostCharacter(character);
}
[HarmonyPatch(typeof(GhostBall), "Update")]
[HarmonyPrefix]
private static bool GhostBallUpdatePrefix(GhostBall __instance)
{
if (!IsGhostVisual(__instance))
{
return true;
}
return false;
}
[HarmonyPatch(typeof(GhostBall), "FixedUpdate")]
[HarmonyPrefix]
private static bool GhostBallFixedUpdatePrefix(GhostBall __instance)
{
if (!IsGhostVisual(__instance))
{
return true;
}
TrySetupCollisionIgnore(__instance);
return false;
}
private static void TrySetupCollisionIgnore(GhostBall ghostBall)
{
try
{
GameObject gameObject = ((Component)ghostBall).gameObject;
int instanceID = ((Object)gameObject).GetInstanceID();
if (CollisionIgnoredInstances.Contains(instanceID))
{
return;
}
PhotonView component = ((Component)ghostBall).GetComponent<PhotonView>();
object[] array = (((Object)(object)component != (Object)null) ? component.InstantiationData : null);
if (array != null && array.Length >= 2 && array[1] is int num)
{
PhotonView val = PhotonView.Find(num);
Character val2 = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponent<Character>() : null);
if (!((Object)(object)val2 == (Object)null))
{
GhostController.IgnoreCollisionWithCharacter(gameObject, val2);
CollisionIgnoredInstances.Add(instanceID);
}
}
}
catch
{
}
}
internal static bool CharacterRpcDiePrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterRpcSetDeadPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterRpcPassOutPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterDieInstantlyPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterHandleDeathPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterWarpPlayerRpcPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterWarpPlayerPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterFallPrefix(Character __instance)
{
return !IsGhost(__instance);
}
internal static bool CharacterRpcFallPrefix(Character __instance)
{
return !IsGhost(__instance);
}
}
}