using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using UnityEngine;
using UnityEngine.Animations.Rigging;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Controls;
using UnityEngine.InputSystem.LowLevel;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using Zorro.Core;
[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("PeakOdmGear")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("PeakOdmGear")]
[assembly: AssemblyTitle("PeakOdmGear")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
internal sealed class NullableAttribute : Attribute
{
public readonly byte[] NullableFlags;
public NullableAttribute(byte P_0)
{
NullableFlags = new byte[1] { P_0 };
}
public NullableAttribute(byte[] P_0)
{
NullableFlags = P_0;
}
}
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
internal sealed class NullableContextAttribute : Attribute
{
public readonly byte Flag;
public NullableContextAttribute(byte P_0)
{
Flag = P_0;
}
}
[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 PeakOdmGear
{
[BepInPlugin("dev.midor.peak.odmgear", "Omni-Directional Mobility Gear", "0.1.0")]
public sealed class Plugin : BaseUnityPlugin
{
private Vector3 testStart;
private int testStartPulls;
public const string Id = "dev.midor.peak.odmgear";
public const string Version = "0.1.0";
internal static Plugin Instance;
internal Character? owner;
internal bool attached;
internal bool testMode;
internal int shots;
internal int pulls;
internal GameObject? visual;
internal Collider? anchor;
internal Vector3 anchorLocal;
internal float firedAt;
internal float nextShot;
private float nextBind;
private float initialStowUntil;
private Harmony? harmony;
private GameObject? driver;
private LineRenderer? cable;
private Material? cableMaterial;
private Transform? claw;
private Transform? hand;
private Vector3 clawRest;
private Quaternion clawRotation;
private RescueHook? prefab;
private bool enabledGear = true;
private bool faulted;
private string status = "READY";
internal ConfigEntry<float> range;
internal ConfigEntry<float> speed;
private ConfigEntry<bool> showHud;
private Func<Character, bool> canInput;
private Action<Character, Vector3, float, float> addForce;
private IEnumerator IntegrationTest()
{
List<string> report = new List<string>();
string path = Path.Combine(Paths.BepInExRootPath, "ODM-integration.txt");
File.WriteAllText(path, "RUNNING " + DateTime.UtcNow.ToString("O"));
GameObject fixture = null;
GameObject target = null;
GameObject blocker = null;
float timeout = Time.realtimeSinceStartup + 90f;
while (!Object.op_Implicit((Object)(object)Object.FindFirstObjectByType<MainMenu>()) && Time.realtimeSinceStartup < timeout)
{
yield return null;
}
MainMenu menu = Object.FindFirstObjectByType<MainMenu>();
if (!Object.op_Implicit((Object)(object)menu))
{
FinishTest(path, report, "FAIL: Title menu timeout");
yield break;
}
yield return (object)new WaitForSecondsRealtime(2f);
try
{
if (faulted)
{
throw new Exception("Plugin initialization fault");
}
RescueHook val = FindPrefab();
report.Add("PASS native rescue prefab: " + ((Object)val).name + ", mesh count=" + ((Component)val).GetComponentsInChildren<MeshFilter>(true).Length);
AccessTools.Method(typeof(MainMenu), "StartSoloSession", (Type[])null, (Type[])null).Invoke(menu, null);
}
catch (Exception ex)
{
FinishTest(path, report, "FAIL startup: " + ex);
yield break;
}
timeout = Time.realtimeSinceStartup + 90f;
while ((!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)visual)) && Time.realtimeSinceStartup < timeout)
{
yield return null;
}
if (!Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)visual))
{
FinishTest(path, report, "FAIL: local character/equipment timeout");
yield break;
}
yield return (object)new WaitForSecondsRealtime(14f);
ScreenCapture.CaptureScreenshot(Path.Combine(Paths.BepInExRootPath, "ODM-equipped.png"));
yield return (object)new WaitForSecondsRealtime(1f);
try
{
Character val2 = owner;
Scene activeScene = SceneManager.GetActiveScene();
report.Add("PASS automatic equipment: scene=" + ((Scene)(ref activeScene)).name + ", meshes=" + visual.GetComponentsInChildren<MeshRenderer>().Length);
if (visual.GetComponentsInChildren<Collider>().Length != 0 || visual.GetComponentsInChildren<Item>().Length != 0)
{
throw new Exception("Visual contains gameplay components");
}
report.Add("PASS hand visual has no inventory item or collision component");
if (!InputAllowed(val2))
{
throw new Exception("Airport player input unavailable");
}
fixture = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)fixture).name = "ODM Temporary Test Platform";
fixture.layer = LayerMask.NameToLayer("Map");
fixture.transform.position = new Vector3(2000f, 1998f, 2000f);
fixture.transform.localScale = new Vector3(80f, 2f, 80f);
Physics.SyncTransforms();
AccessTools.MethodDelegate<Action<Character, Vector3, bool>>(AccessTools.Method(typeof(Character), "WarpPlayer", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, (Type[])null), (object)null, true)(val2, new Vector3(2000f, 2001f, 2000f), arg3: false);
}
catch (Exception ex2)
{
if (Object.op_Implicit((Object)(object)fixture))
{
Object.Destroy((Object)(object)fixture);
}
FinishTest(path, report, "FAIL fixture: " + ex2);
yield break;
}
yield return (object)new WaitForSeconds(2f);
try
{
Character val3 = owner;
Vector3 val4 = val3.Center + Vector3.up * 2f;
target = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)target).name = "ODM Integration Target";
target.layer = LayerMask.NameToLayer("Map");
target.transform.position = val4 + Vector3.up * 10f;
target.transform.localScale = Vector3.one * 2f;
Physics.SyncTransforms();
Ray ray = default(Ray);
((Ray)(ref ray))..ctor(val4, Vector3.up);
if (!FindHit(ray, out var hit) || (Object)(object)((Component)((RaycastHit)(ref hit)).collider).gameObject != (Object)(object)target)
{
throw new Exception("Ray did not select test target, hit=" + (object)((RaycastHit)(ref hit)).collider);
}
report.Add("PASS actual Unity raycast hit target");
for (int i = 0; i < 100; i++)
{
nextShot = 0f;
if (!Fire(ray))
{
throw new Exception("Repeated shot failed " + i);
}
Release("TEST");
}
report.Add("PASS 100 consecutive shots with unlimited ammunition");
blocker = GameObject.CreatePrimitive((PrimitiveType)3);
blocker.layer = LayerMask.NameToLayer("Map");
blocker.transform.position = val4 + Vector3.up * 4f;
Physics.SyncTransforms();
if (!FindHit(ray, out hit) || (Object)(object)((Component)((RaycastHit)(ref hit)).collider).gameObject != (Object)(object)blocker)
{
throw new Exception("Nearest surface did not block rear target");
}
report.Add("PASS nearest obstruction wins");
blocker.SetActive(false);
Physics.SyncTransforms();
nextShot = 0f;
if (!Fire(ray))
{
throw new Exception("Motion shot failed");
}
testStart = val3.Center;
testStartPulls = pulls;
}
catch (Exception ex3)
{
if (Object.op_Implicit((Object)(object)fixture))
{
Object.Destroy((Object)(object)fixture);
}
if (Object.op_Implicit((Object)(object)target))
{
Object.Destroy((Object)(object)target);
}
if (Object.op_Implicit((Object)(object)blocker))
{
Object.Destroy((Object)(object)blocker);
}
FinishTest(path, report, "FAIL setup: " + ex3);
yield break;
}
yield return (object)new WaitForSeconds(0.8f);
MouseState val7;
try
{
Character val5 = owner;
float num = Vector3.Distance(val5.Center, testStart);
float num2 = val5.Center.y - testStart.y;
if (pulls <= testStartPulls || num2 < 0.2f)
{
throw new Exception("No measured upward pull; moved=" + num + " rose=" + num2 + " ticks=" + (pulls - testStartPulls) + " status=" + status);
}
report.Add("PASS real local Character force: displacement=" + num.ToString("F2") + ", rise=" + num2.ToString("F2") + ", physics ticks=" + (pulls - testStartPulls));
Release("TEST COMPLETE");
if (attached || ((Renderer)cable).enabled)
{
throw new Exception("Release left cable active");
}
report.Add("PASS release clears attachment and cable");
nextShot = 0f;
if (Fire(new Ray(new Vector3(30000f, 30000f, 30000f), Vector3.up)))
{
throw new Exception("Miss attached a cable");
}
report.Add("PASS miss does not attach");
Mouse val6 = InputSystem.AddDevice<Mouse>((string)null);
try
{
val7 = default(MouseState);
InputSystem.QueueStateEvent<MouseState>((InputDevice)(object)val6, ((MouseState)(ref val7)).WithButton((MouseButton)0, true), -1.0);
InputSystem.Update();
AccessTools.Method(typeof(CharacterInput), "Sample", (Type[])null, (Type[])null).Invoke(val5.input, new object[1] { true });
if (!val5.input.usePrimaryIsPressed || val5.input.useSecondaryIsPressed)
{
throw new Exception("LMB/RMB routing failed");
}
report.Add("PASS synthetic LMB through native sampler preserves climb input");
Camera component = ((Component)MainCamera.instance).GetComponent<Camera>();
target.transform.position = ((Component)component).transform.position + ((Component)component).transform.forward * 7f;
Physics.SyncTransforms();
nextShot = 0f;
int num3 = shots;
val7 = default(MouseState);
InputSystem.QueueStateEvent<MouseState>((InputDevice)(object)val6, ((MouseState)(ref val7)).WithButton((MouseButton)1, true), -1.0);
InputSystem.Update();
AccessTools.Method(typeof(CharacterInput), "Sample", (Type[])null, (Type[])null).Invoke(val5.input, new object[1] { true });
if (val5.input.useSecondaryIsPressed || val5.input.useSecondaryWasPressed)
{
throw new Exception("RMB native secondary not suppressed");
}
report.Add("PASS synthetic RMB suppresses native secondary-use conflict");
if (shots != num3 + 1 || !attached)
{
throw new Exception("RMB did not fire through native input sampler");
}
report.Add("PASS synthetic RMB fires aimed hook through native input sampler");
enabledGear = false;
val5.input.useSecondaryIsPressed = true;
Sample(val5.input, movementActive: true);
if (!val5.input.useSecondaryIsPressed)
{
throw new Exception("Disabled gear intercepted normal controls");
}
enabledGear = true;
report.Add("PASS disabled gear restores native input");
target.SetActive(false);
PhysicsTick();
if (attached)
{
throw new Exception("Destroyed/disabled anchor did not release");
}
report.Add("PASS lost anchor releases cable");
val7 = default(MouseState);
InputSystem.QueueStateEvent<MouseState>((InputDevice)(object)val6, val7, -1.0);
InputSystem.Update();
}
finally
{
InputSystem.RemoveDevice((InputDevice)(object)val6);
}
report.Add("INFO physics suite complete; beginning wall-climb test.");
if (Object.op_Implicit((Object)(object)target))
{
Object.Destroy((Object)(object)target);
}
if (Object.op_Implicit((Object)(object)blocker))
{
Object.Destroy((Object)(object)blocker);
}
AccessTools.MethodDelegate<Action<Character, Vector3, bool>>(AccessTools.Method(typeof(Character), "WarpPlayer", new Type[2]
{
typeof(Vector3),
typeof(bool)
}, (Type[])null), (object)null, true)(val5, new Vector3(2000f, 2001f, 2000f), arg3: false);
}
catch (Exception ex4)
{
if (Object.op_Implicit((Object)(object)fixture))
{
Object.Destroy((Object)(object)fixture);
}
if (Object.op_Implicit((Object)(object)target))
{
Object.Destroy((Object)(object)target);
}
if (Object.op_Implicit((Object)(object)blocker))
{
Object.Destroy((Object)(object)blocker);
}
FinishTest(path, report, "FAIL motion: " + ex4);
yield break;
}
yield return (object)new WaitForSeconds(2f);
Mouse climbMouse = null;
GameObject wall = null;
try
{
Character? obj = owner;
Camera component2 = ((Component)MainCamera.instance).GetComponent<Camera>();
Vector3 val8 = Vector3.ProjectOnPlane(obj.data.lookDirection, Vector3.up);
Vector3 normalized = ((Vector3)(ref val8)).normalized;
wall = GameObject.CreatePrimitive((PrimitiveType)3);
((Object)wall).name = "ODM Climb Transfer Test Wall";
wall.layer = LayerMask.NameToLayer("Map");
wall.transform.position = ((Component)component2).transform.position + normalized * 0.9f;
wall.transform.rotation = Quaternion.LookRotation(normalized);
wall.transform.localScale = new Vector3(8f, 10f, 0.2f);
Physics.SyncTransforms();
climbMouse = InputSystem.AddDevice<Mouse>((string)null);
Mouse obj2 = climbMouse;
val7 = default(MouseState);
InputSystem.QueueStateEvent<MouseState>((InputDevice)(object)obj2, ((MouseState)(ref val7)).WithButton((MouseButton)0, true), -1.0);
InputSystem.Update();
}
catch (Exception ex5)
{
if (Object.op_Implicit((Object)(object)fixture))
{
Object.Destroy((Object)(object)fixture);
}
if (Object.op_Implicit((Object)(object)wall))
{
Object.Destroy((Object)(object)wall);
}
if (climbMouse != null)
{
InputSystem.RemoveDevice((InputDevice)(object)climbMouse);
}
FinishTest(path, report, "FAIL climb setup: " + ex5);
yield break;
}
yield return (object)new WaitForSeconds(0.5f);
Character val9 = owner;
RaycastHit val10 = default(RaycastHit);
Physics.Raycast(new Ray(((Component)MainCamera.instance).transform.position, val9.data.lookDirection), ref val10, 1.25f, LayerMask.op_Implicit(HelperFunctions.terrainMapMask));
string[] obj3 = new string[18]
{
"INFO climb state primary=",
val9.input.usePrimaryIsPressed.ToString(),
" item=",
((object)val9.data.currentItem)?.ToString(),
" sincePress=",
val9.data.sincePressClimb.ToString(),
" sinceClimb=",
val9.data.sinceClimb.ToString(),
" ragdoll=",
val9.data.currentRagdollControll.ToString(),
" alive=",
Ready(val9).ToString(),
" hit=",
((object)((RaycastHit)(ref val10)).collider)?.ToString(),
" mouse=",
null,
null,
null
};
Mouse current = Mouse.current;
obj3[15] = ((current != null) ? ((InputControl)current).name : null);
obj3[16] = " held=";
obj3[17] = climbMouse.leftButton.isPressed.ToString();
report.Add(string.Concat(obj3));
bool climbed = Object.op_Implicit((Object)(object)owner) && owner.data.isClimbing;
report.Add((climbed ? "PASS" : "FAIL") + " actual LMB held starts native wall climbing");
Mouse obj4 = climbMouse;
val7 = default(MouseState);
InputSystem.QueueStateEvent<MouseState>((InputDevice)(object)obj4, val7, -1.0);
yield return (object)new WaitForSeconds(0.3f);
bool flag = Object.op_Implicit((Object)(object)owner) && !owner.data.isClimbing;
report.Add((flag ? "PASS" : "FAIL") + " releasing LMB ends native wall climbing");
InputSystem.RemoveDevice((InputDevice)(object)climbMouse);
if (Object.op_Implicit((Object)(object)fixture))
{
Object.Destroy((Object)(object)fixture);
}
if (Object.op_Implicit((Object)(object)wall))
{
Object.Destroy((Object)(object)wall);
}
report.Add("NOT TESTED: physical mouse clicks, multiplayer, full-run endurance.");
FinishTest(path, report, (climbed && flag) ? "PASS automated game-engine integration" : "FAIL wall-climb integration");
}
private void FinishTest(string path, List<string> report, string outcome)
{
Release("READY");
report.Add(outcome);
report.Add("gameMvid=" + typeof(Character).Module.ModuleVersionId);
report.Add("unity=" + Application.unityVersion);
File.WriteAllLines(path, report);
((BaseUnityPlugin)this).Logger.LogInfo((object)("ODM_TEST " + outcome));
if (Environment.GetCommandLineArgs().Contains("--odm-test-quit"))
{
Application.Quit();
}
else
{
testMode = false;
}
}
private void Awake()
{
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_003f: Expected O, but got Unknown
//IL_0073: Unknown result type (might be due to invalid IL or missing references)
//IL_007d: Expected O, but got Unknown
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: Expected O, but got Unknown
//IL_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0140: Expected O, but got Unknown
Instance = this;
range = ((BaseUnityPlugin)this).Config.Bind<float>("Gear", "Range", 40f, new ConfigDescription("Maximum hook distance in game units.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 120f), Array.Empty<object>()));
speed = ((BaseUnityPlugin)this).Config.Bind<float>("Gear", "PullSpeed", 16f, new ConfigDescription("Target pull speed.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(4f, 30f), Array.Empty<object>()));
showHud = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowHud", true, "Show English controls and hook status.");
try
{
canInput = AccessTools.MethodDelegate<Func<Character, bool>>(AccessTools.Method(typeof(Character), "CanDoInput", (Type[])null, (Type[])null), (object)null, true);
addForce = AccessTools.MethodDelegate<Action<Character, Vector3, float, float>>(AccessTools.Method(typeof(Character), "AddForce", new Type[3]
{
typeof(Vector3),
typeof(float),
typeof(float)
}, (Type[])null), (object)null, true);
harmony = new Harmony("dev.midor.peak.odmgear");
harmony.PatchAll();
driver = new GameObject("ODM Gear Runtime");
Object.DontDestroyOnLoad((Object)(object)driver);
driver.AddComponent<GearDriver>();
SceneManager.activeSceneChanged += SceneChanged;
((BaseUnityPlugin)this).Logger.LogInfo((object)("ODM_READY version=0.1.0 gameMvid=" + typeof(Character).Module.ModuleVersionId));
testMode = Environment.GetCommandLineArgs().Contains("--odm-integration-test");
if (testMode)
{
Application.runInBackground = true;
((MonoBehaviour)this).StartCoroutine(IntegrationTest());
}
}
catch (Exception e)
{
Fail(e);
}
}
internal void Fail(Exception e)
{
if (!faulted)
{
faulted = true;
Release("ERROR - check BepInEx log");
((BaseUnityPlugin)this).Logger.LogError((object)e);
}
}
private void SceneChanged(Scene oldScene, Scene newScene)
{
Cleanup();
nextBind = 0f;
}
internal bool Ready(Character? c)
{
if (!faulted && enabledGear && Object.op_Implicit((Object)(object)c) && c.IsLocal && Object.op_Implicit((Object)(object)c.data) && !c.data.dead && !c.data.passedOut && !c.data.fullyPassedOut && !c.warping && !c.data.isCarried && !Object.op_Implicit((Object)(object)c.data.carrier) && !Object.op_Implicit((Object)(object)c.data.carrierCondor))
{
return !Object.op_Implicit((Object)(object)c.data.grabJoint);
}
return false;
}
internal bool InputAllowed(Character? c)
{
if (Ready(c) && Object.op_Implicit((Object)(object)GUIManager.instance) && canInput(c) && Time.timeScale > 0f)
{
if (!testMode)
{
return Application.isFocused;
}
return true;
}
return false;
}
internal bool OwnsInput(CharacterInput input)
{
if (Object.op_Implicit((Object)(object)owner) && (Object)(object)owner.input == (Object)(object)input)
{
return InputAllowed(owner);
}
return false;
}
internal void Sample(CharacterInput input, bool movementActive)
{
//IL_006d: 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)
if (!OwnsInput(input) || !movementActive)
{
return;
}
Mouse current = Mouse.current;
if (current != null)
{
input.useSecondaryWasPressed = false;
input.useSecondaryIsPressed = false;
input.useSecondaryWasReleased = false;
if (Object.op_Implicit((Object)(object)owner.data.currentItem) && (current.leftButton.wasPressedThisFrame || current.rightButton.wasPressedThisFrame))
{
owner.refs.items.EquipSlot(Optionable<byte>.None);
}
if (!Object.op_Implicit((Object)(object)owner.data.currentItem))
{
input.usePrimaryWasPressed = current.leftButton.wasPressedThisFrame;
input.usePrimaryIsPressed = current.leftButton.isPressed;
input.usePrimaryWasReleased = current.leftButton.wasReleasedThisFrame;
}
if (current.rightButton.wasPressedThisFrame && Object.op_Implicit((Object)(object)MainCamera.instance))
{
Fire(((Component)MainCamera.instance).GetComponent<Camera>().ViewportPointToRay(new Vector3(0.5f, 0.5f, 0f)));
}
}
}
internal void Tick()
{
//IL_0105: 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 (faulted)
{
return;
}
Character localCharacter = Character.localCharacter;
if ((Object)(object)localCharacter != (Object)(object)owner && Time.unscaledTime >= nextBind)
{
nextBind = Time.unscaledTime + 0.5f;
Cleanup();
if (Object.op_Implicit((Object)(object)localCharacter) && localCharacter.refs != null && Object.op_Implicit((Object)(object)localCharacter.refs.ragdoll) && Object.op_Implicit((Object)(object)localCharacter.refs.ikRight))
{
owner = localCharacter;
initialStowUntil = Time.time + 4f;
CreateVisual();
ManualLogSource logger = ((BaseUnityPlugin)this).Logger;
Scene activeScene = SceneManager.GetActiveScene();
logger.LogInfo((object)("ODM_EQUIPPED " + ((Scene)(ref activeScene)).name));
}
}
if (Object.op_Implicit((Object)(object)owner))
{
if (enabledGear && Time.time < initialStowUntil && Object.op_Implicit((Object)(object)owner.data.currentItem))
{
owner.refs.items.EquipSlot(Optionable<byte>.None);
initialStowUntil = 0f;
}
if (!testMode && Application.isFocused && Keyboard.current != null && ((ButtonControl)Keyboard.current.f6Key).wasPressedThisFrame)
{
enabledGear = !enabledGear;
Release(enabledGear ? "READY" : "DISABLED");
}
if (!InputAllowed(owner) && attached)
{
Release("READY");
}
if (!testMode && attached && Keyboard.current != null && ((ButtonControl)Keyboard.current.spaceKey).wasPressedThisFrame)
{
Release("RELEASED");
}
if (Object.op_Implicit((Object)(object)visual))
{
visual.SetActive(Ready(owner));
}
}
}
internal bool FindHit(Ray ray, out RaycastHit hit)
{
//IL_0001: 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_0019: 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_00af: Unknown result type (might be due to invalid IL or missing references)
//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
hit = default(RaycastHit);
float num = float.PositiveInfinity;
RaycastHit[] array = Physics.RaycastAll(ray, range.Value, LayerMask.op_Implicit(HelperFunctions.AllPhysicalExceptDefault), (QueryTriggerInteraction)1);
Item val2 = default(Item);
for (int i = 0; i < array.Length; i++)
{
RaycastHit val = array[i];
if (Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).collider) && (!Object.op_Implicit((Object)(object)owner) || !((Component)((RaycastHit)(ref val)).collider).transform.IsChildOf(((Component)owner).transform)) && (!Object.op_Implicit((Object)(object)((RaycastHit)(ref val)).rigidbody) || !((Component)((RaycastHit)(ref val)).rigidbody).TryGetComponent<Item>(ref val2) || !((Object)(object)val2.holderCharacter == (Object)(object)owner)) && ((RaycastHit)(ref val)).distance < num)
{
hit = val;
num = ((RaycastHit)(ref val)).distance;
}
}
if (Object.op_Implicit((Object)(object)((RaycastHit)(ref hit)).collider) && ((RaycastHit)(ref hit)).distance >= 1f && !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Character>()))
{
return !Object.op_Implicit((Object)(object)((Component)((RaycastHit)(ref hit)).collider).GetComponentInParent<Item>());
}
return false;
}
internal bool Fire(Ray ray)
{
//IL_003a: 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_00e1: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
if (!InputAllowed(owner) || Time.time < nextShot)
{
return false;
}
nextShot = Time.time + 0.22f;
Release("NO SURFACE IN RANGE");
if (!FindHit(ray, out var hit))
{
return false;
}
Character val = owner;
if (val.data.isRopeClimbing || val.data.isVineClimbing || Object.op_Implicit((Object)(object)val.data.currentClimbHandle))
{
status = "RELEASE CLIMB HANDLE FIRST";
return false;
}
if (val.data.isClimbing)
{
val.refs.view.RPC("StopClimbingRpc", (RpcTarget)0, new object[1] { 0f });
}
anchor = ((RaycastHit)(ref hit)).collider;
anchorLocal = ((Component)anchor).transform.InverseTransformPoint(((RaycastHit)(ref hit)).point);
attached = true;
firedAt = Time.time;
shots++;
status = "PULLING";
if (Object.op_Implicit((Object)(object)cable))
{
((Renderer)cable).enabled = true;
}
if (Object.op_Implicit((Object)(object)prefab))
{
SFX_Instance[] rescueShot = prefab.rescueShot;
foreach (SFX_Instance val2 in rescueShot)
{
if ((Object)(object)val2 != (Object)null)
{
val2.Play(val.Center);
}
}
}
((BaseUnityPlugin)this).Logger.LogInfo((object)("ODM_FIRE shot=" + shots + " distance=" + ((RaycastHit)(ref hit)).distance.ToString("F1")));
return true;
}
internal void PhysicsTick()
{
//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_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_0090: Unknown result type (might be due to invalid IL or missing references)
//IL_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_0108: Unknown result type (might be due to invalid IL or missing references)
//IL_0123: Unknown result type (might be due to invalid IL or missing references)
//IL_0128: Unknown result type (might be due to invalid IL or missing references)
//IL_01da: Unknown result type (might be due to invalid IL or missing references)
//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
//IL_01f0: Unknown result type (might be due to invalid IL or missing references)
//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
//IL_0209: Unknown result type (might be due to invalid IL or missing references)
//IL_020e: Unknown result type (might be due to invalid IL or missing references)
//IL_0218: Unknown result type (might be due to invalid IL or missing references)
//IL_021d: Unknown result type (might be due to invalid IL or missing references)
//IL_0225: Unknown result type (might be due to invalid IL or missing references)
if (!attached)
{
return;
}
if (!InputAllowed(owner) || !Object.op_Implicit((Object)(object)anchor) || !anchor.enabled || !((Component)anchor).gameObject.activeInHierarchy)
{
Release("READY");
return;
}
Character val = owner;
if (val.data.isClimbingAnything)
{
Release("CLIMBING");
return;
}
Vector3 val2 = ((Component)anchor).transform.TransformPoint(anchorLocal) - val.Center;
if (((Vector3)(ref val2)).magnitude < 1.4f)
{
Release("ARRIVED - LMB TO CLIMB");
return;
}
if (((Vector3)(ref val2)).magnitude > range.Value * 1.5f || Time.time - firedAt > 6f)
{
Release("READY");
return;
}
RaycastHit[] array = Physics.RaycastAll(val.Center, ((Vector3)(ref val2)).normalized, Mathf.Max(0f, ((Vector3)(ref val2)).magnitude - 0.15f), LayerMask.op_Implicit(HelperFunctions.AllPhysicalExceptDefault), (QueryTriggerInteraction)1);
for (int i = 0; i < array.Length; i++)
{
RaycastHit val3 = array[i];
if (!((Object)(object)((RaycastHit)(ref val3)).collider == (Object)(object)anchor) && !((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(((Component)val).transform))
{
Item componentInParent = ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent<Item>();
if (!((Object)(object)((componentInParent != null) ? componentInParent.holderCharacter : null) == (Object)(object)val))
{
Release("CABLE BLOCKED");
return;
}
}
}
if (!(Time.time - firedAt < 0.1f))
{
float num = Mathf.Min(speed.Value, Mathf.Sqrt(50f * Mathf.Max(0f, ((Vector3)(ref val2)).magnitude - 1f)));
Vector3 arg = Vector3.ClampMagnitude((((Vector3)(ref val2)).normalized * num - val.data.avarageVelocity) * 7f + Vector3.up * 12f, 90f);
addForce(val, arg, 1f, 1f);
val.data.sinceGrounded = 0f;
pulls++;
}
}
internal void Release(string message)
{
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
//IL_0053: Unknown result type (might be due to invalid IL or missing references)
attached = false;
anchor = null;
status = message;
if (Object.op_Implicit((Object)(object)cable))
{
((Renderer)cable).enabled = false;
}
if (Object.op_Implicit((Object)(object)claw))
{
claw.localPosition = clawRest;
claw.localRotation = clawRotation;
}
}
internal void RenderTick()
{
//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
//IL_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_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_008c: Unknown result type (might be due to invalid IL or missing references)
//IL_011b: Unknown result type (might be due to invalid IL or missing references)
//IL_0120: Unknown result type (might be due to invalid IL or missing references)
//IL_0125: 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_0136: Unknown result type (might be due to invalid IL or missing references)
//IL_0150: Unknown result type (might be due to invalid IL or missing references)
//IL_0151: Unknown result type (might be due to invalid IL or missing references)
//IL_0154: Unknown result type (might be due to invalid IL or missing references)
//IL_0159: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Unknown result type (might be due to invalid IL or missing references)
//IL_016f: Unknown result type (might be due to invalid IL or missing references)
//IL_0189: Unknown result type (might be due to invalid IL or missing references)
//IL_0196: Unknown result type (might be due to invalid IL or missing references)
//IL_0198: Unknown result type (might be due to invalid IL or missing references)
//IL_0199: Unknown result type (might be due to invalid IL or missing references)
//IL_019e: 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_01a7: Unknown result type (might be due to invalid IL or missing references)
if (!Object.op_Implicit((Object)(object)visual) || !Object.op_Implicit((Object)(object)owner) || !Object.op_Implicit((Object)(object)MainCamera.instance))
{
return;
}
Character val = owner;
if (Ready(val) && !Object.op_Implicit((Object)(object)val.data.currentItem) && !val.data.isClimbingAnything)
{
Transform transform = ((Component)((Component)MainCamera.instance).GetComponent<Camera>()).transform;
visual.transform.SetPositionAndRotation(transform.TransformPoint(new Vector3(0.34f, -0.29f, 0.68f)), transform.rotation);
}
else if (Object.op_Implicit((Object)(object)hand))
{
visual.transform.SetPositionAndRotation(hand.position, hand.rotation * Quaternion.Euler(0f, 90f, 0f));
}
if (attached && Object.op_Implicit((Object)(object)anchor) && Object.op_Implicit((Object)(object)cable))
{
Vector3 val2 = ((Component)anchor).transform.TransformPoint(anchorLocal);
Vector3 position = visual.transform.position;
float num = Mathf.Clamp01((Time.time - firedAt) / 0.1f);
Vector3 val3 = Vector3.Lerp(position, val2, num);
cable.SetPosition(0, position);
cable.SetPosition(1, val3);
if (Object.op_Implicit((Object)(object)claw))
{
claw.position = val3;
Transform? obj = claw;
Vector3 val4 = val3 - position;
obj.rotation = Quaternion.LookRotation(((Vector3)(ref val4)).normalized);
}
}
}
internal void Pose(CharacterAnimations animations)
{
//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
//IL_00be: Unknown result type (might be due to invalid IL or missing references)
//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
//IL_00d8: 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)
if (Object.op_Implicit((Object)(object)owner) && !((Object)(object)owner.refs.animations != (Object)(object)animations) && Ready(owner) && !Object.op_Implicit((Object)(object)owner.data.currentItem) && !owner.data.isClimbingAnything && Object.op_Implicit((Object)(object)MainCamera.instance))
{
CharacterRefs refs = owner.refs;
refs.ikRig.weight = 1f;
((RigConstraint<TwoBoneIKConstraintJob, TwoBoneIKConstraintData, TwoBoneIKConstraintJobBinder<TwoBoneIKConstraintData>>)(object)refs.ikRight).weight = 1f;
Transform transform = ((Component)((Component)MainCamera.instance).GetComponent<Camera>()).transform;
refs.IKHandTargetRight.SetPositionAndRotation(transform.TransformPoint(new Vector3(0.31f, -0.32f, 0.57f)), transform.rotation * Quaternion.Euler(-30f, -90f, -70f));
}
}
internal RescueHook FindPrefab()
{
GameObject[] array = Resources.LoadAll<GameObject>("0_Items");
for (int i = 0; i < array.Length; i++)
{
RescueHook component = array[i].GetComponent<RescueHook>();
if (Object.op_Implicit((Object)(object)component))
{
return component;
}
}
throw new InvalidOperationException("Installed game has no RescueHook prefab in 0_Items.");
}
private void CreateVisual()
{
//IL_0032: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected O, but got Unknown
//IL_006d: 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_00d7: Unknown result type (might be due to invalid IL or missing references)
//IL_00dd: Expected O, but got Unknown
//IL_00b7: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
//IL_0158: Unknown result type (might be due to invalid IL or missing references)
//IL_0162: Expected O, but got Unknown
//IL_019a: Unknown result type (might be due to invalid IL or missing references)
//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
prefab = FindPrefab();
hand = ((TwoBoneIKConstraintData)(ref ((RigConstraint<TwoBoneIKConstraintJob, TwoBoneIKConstraintData, TwoBoneIKConstraintJobBinder<TwoBoneIKConstraintData>>)(object)owner.refs.ikRight).data)).tip;
visual = new GameObject("ODM Right Hand Rescue Launcher");
CopyMeshes(((Component)prefab).transform, visual.transform, ((Component)prefab).transform);
visual.transform.localScale = Vector3.one * 0.55f;
claw = ((IEnumerable<Transform>)visual.GetComponentsInChildren<Transform>()).FirstOrDefault((Func<Transform, bool>)((Transform t) => ((Object)t).name == ((Object)prefab.claw).name));
if (Object.op_Implicit((Object)(object)claw))
{
clawRest = claw.localPosition;
clawRotation = claw.localRotation;
}
GameObject val = new GameObject("ODM Cable");
val.transform.SetParent(visual.transform, false);
cable = val.AddComponent<LineRenderer>();
cable.positionCount = 2;
cable.useWorldSpace = true;
cable.startWidth = 0.018f;
cable.endWidth = 0.012f;
Shader val2 = Shader.Find("Sprites/Default");
if (!Object.op_Implicit((Object)(object)val2))
{
throw new InvalidOperationException("Cable shader unavailable");
}
cableMaterial = new Material(val2);
((Renderer)cable).sharedMaterial = cableMaterial;
LineRenderer? obj = cable;
LineRenderer? obj2 = cable;
Color val3 = default(Color);
((Color)(ref val3))..ctor(0.22f, 0.25f, 0.27f, 1f);
obj2.endColor = val3;
obj.startColor = val3;
((Renderer)cable).shadowCastingMode = (ShadowCastingMode)0;
((Renderer)cable).enabled = false;
((BaseUnityPlugin)this).Logger.LogInfo((object)("ODM_VISUAL meshes=" + visual.GetComponentsInChildren<MeshRenderer>().Length + " native=" + ((Object)prefab).name));
}
private static void CopyMeshes(Transform source, Transform target, Transform root)
{
//IL_0060: Unknown result type (might be due to invalid IL or missing references)
//IL_0066: Expected O, but got Unknown
//IL_006c: Unknown result type (might be due to invalid IL or missing references)
//IL_0084: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_009e: Unknown result type (might be due to invalid IL or missing references)
MeshFilter component = ((Component)source).GetComponent<MeshFilter>();
MeshRenderer component2 = ((Component)source).GetComponent<MeshRenderer>();
if (Object.op_Implicit((Object)(object)component) && Object.op_Implicit((Object)(object)component2))
{
((Component)target).gameObject.AddComponent<MeshFilter>().sharedMesh = component.sharedMesh;
MeshRenderer obj = ((Component)target).gameObject.AddComponent<MeshRenderer>();
((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials;
((Renderer)obj).shadowCastingMode = (ShadowCastingMode)0;
}
foreach (Transform item in source)
{
Transform val = item;
Transform transform = new GameObject(((Object)val).name).transform;
transform.SetParent(target, false);
transform.localPosition = val.localPosition;
transform.localRotation = val.localRotation;
transform.localScale = val.localScale;
CopyMeshes(val, transform, root);
}
}
internal void Draw()
{
//IL_002f: Unknown result type (might be due to invalid IL or missing references)
if (showHud.Value && Object.op_Implicit((Object)(object)owner))
{
GUI.Box(new Rect(16f, 65f, 570f, 65f), "OMNI-DIRECTIONAL MOBILITY GEAR | UNLIMITED\nRMB: Fire & pull LMB: Climb Space: Release F6: Toggle\n" + status);
}
}
private void Cleanup()
{
Release("READY");
if (Object.op_Implicit((Object)(object)visual))
{
Object.Destroy((Object)(object)visual);
}
if (Object.op_Implicit((Object)(object)cableMaterial))
{
Object.Destroy((Object)(object)cableMaterial);
}
visual = null;
cable = null;
claw = null;
owner = null;
}
private void OnDestroy()
{
SceneManager.activeSceneChanged -= SceneChanged;
Cleanup();
Harmony? obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
if (Object.op_Implicit((Object)(object)driver))
{
Object.Destroy((Object)(object)driver);
}
Instance = null;
}
}
public sealed class GearDriver : MonoBehaviour
{
private void Update()
{
try
{
Plugin.Instance?.Tick();
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
private void FixedUpdate()
{
try
{
Plugin.Instance?.PhysicsTick();
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
private void LateUpdate()
{
try
{
Plugin.Instance?.RenderTick();
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
private void OnGUI()
{
Plugin.Instance?.Draw();
}
}
[HarmonyPatch(typeof(CharacterInput), "Sample")]
internal static class InputPatch
{
private static void Postfix(CharacterInput __instance, bool playerMovementActive)
{
try
{
Plugin.Instance?.Sample(__instance, playerMovementActive);
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
}
[HarmonyPatch(typeof(CharacterAnimations), "HandleIK")]
internal static class HandWeightPatch
{
private static void Postfix(CharacterAnimations __instance)
{
try
{
Plugin.Instance?.Pose(__instance);
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
}
[HarmonyPatch(typeof(CharacterAnimations), "ConfigureIK")]
internal static class HandPosePatch
{
private static void Postfix(CharacterAnimations __instance)
{
try
{
Plugin.Instance?.Pose(__instance);
}
catch (Exception e)
{
Plugin.Instance?.Fail(e);
}
}
}
}