using System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Reflection.Emit; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Cryptography; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using Dawn; using DunGen; using GameNetcodeStuff; using HarmonyLib; using LethalCompanyInputUtils.Api; using LethalCompanyInputUtils.Config; using LethalCompanyInputUtils.Data; using Microsoft.CodeAnalysis; using TMPro; using Unity.Collections; using Unity.Netcode; using UnityEngine; using UnityEngine.AI; using UnityEngine.Animations.Rigging; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.InputSystem.Utilities; using UnityEngine.Networking; using UnityEngine.Rendering; using UnityEngine.Rendering.HighDefinition; using UnityEngine.SceneManagement; using UnityEngine.UI; using Y4NGZInteractions.InteractionAnimationApi; using Y4NGZUpgrades; using Y4NGZUpgrades.Config; using Y4NGZUpgrades.Effects; using Y4NGZUpgrades.Gui; using Y4NGZUpgrades.HUD; using Y4NGZUpgrades.Interactive; using Y4NGZUpgrades.Interactive.Feedback; using Y4NGZUpgrades.Interactive.Hud; using Y4NGZUpgrades.Interactive.Patches; using Y4NGZUpgrades.Lucky8; using Y4NGZUpgrades.Patches; using Y4NGZUpgrades.UITheme; using Y4NGZUpgrades.Upgrades; using cakeslice; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("AmazingAssets.TerrainToMesh")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp-firstpass")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: IgnoresAccessChecksTo("ClientNetworkTransform")] [assembly: IgnoresAccessChecksTo("com.olegknyazev.softmask")] [assembly: IgnoresAccessChecksTo("DissonanceVoip")] [assembly: IgnoresAccessChecksTo("DunGen")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.ASPP")] [assembly: IgnoresAccessChecksTo("DunGen.Integration.UnityNav")] [assembly: IgnoresAccessChecksTo("EasyTextEffects")] [assembly: IgnoresAccessChecksTo("Facepunch Transport for Netcode for GameObjects")] [assembly: IgnoresAccessChecksTo("Facepunch.Steamworks.Win64")] [assembly: IgnoresAccessChecksTo("Unity.AI.Navigation")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging")] [assembly: IgnoresAccessChecksTo("Unity.Animation.Rigging.DocCodeExamples")] [assembly: IgnoresAccessChecksTo("Unity.Burst")] [assembly: IgnoresAccessChecksTo("Unity.Burst.Unsafe")] [assembly: IgnoresAccessChecksTo("Unity.Collections")] [assembly: IgnoresAccessChecksTo("Unity.Collections.LowLevel.ILSupport")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem")] [assembly: IgnoresAccessChecksTo("Unity.InputSystem.ForUI")] [assembly: IgnoresAccessChecksTo("Unity.Jobs")] [assembly: IgnoresAccessChecksTo("Unity.Mathematics")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.Common")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.MetricTypes")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStats")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Component")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsMonitor.Implementation")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetStatsReporting")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkProfiler.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Multiplayer.Tools.NetworkSolutionInterface")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Components")] [assembly: IgnoresAccessChecksTo("Unity.Netcode.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.Networking.Transport")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Csg")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.KdTree")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Poly2Tri")] [assembly: IgnoresAccessChecksTo("Unity.ProBuilder.Stl")] [assembly: IgnoresAccessChecksTo("Unity.Profiling.Core")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.Core.ShaderLibrary")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Config.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.HighDefinition.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.RenderPipelines.ShaderGraph.ShaderGraphLibrary")] [assembly: IgnoresAccessChecksTo("Unity.Services.Authentication")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Analytics")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Components")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Configuration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Device")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Environments.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Internal")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Networking")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Registration")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Scheduler")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Telemetry")] [assembly: IgnoresAccessChecksTo("Unity.Services.Core.Threading")] [assembly: IgnoresAccessChecksTo("Unity.Services.QoS")] [assembly: IgnoresAccessChecksTo("Unity.Services.Relay")] [assembly: IgnoresAccessChecksTo("Unity.TextMeshPro")] [assembly: IgnoresAccessChecksTo("Unity.Timeline")] [assembly: IgnoresAccessChecksTo("Unity.VisualEffectGraph.Runtime")] [assembly: IgnoresAccessChecksTo("Unity.XR.CoreUtils")] [assembly: IgnoresAccessChecksTo("Unity.XR.Management")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.ConformanceAutomation")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MetaQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.MockRuntime")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.OculusQuestSupport")] [assembly: IgnoresAccessChecksTo("Unity.XR.OpenXR.Features.RuntimeDebugger")] [assembly: IgnoresAccessChecksTo("UnityEngine.ARModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.NVIDIAModule")] [assembly: IgnoresAccessChecksTo("UnityEngine.SpatialTracking")] [assembly: IgnoresAccessChecksTo("UnityEngine.UI")] [assembly: IgnoresAccessChecksTo("UnityEngine.XR.LegacyInputHelpers")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("Y4NGZUpgrades")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Native Y4NGZ progression and upgrade framework spine")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+aa6e1cd1ef880d5a03be519cbac8a321e9211d53")] [assembly: AssemblyProduct("Y4NGZUpgrades")] [assembly: AssemblyTitle("Y4NGZUpgrades")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [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 cakeslice { public sealed class LinkedSet : IEnumerable, IEnumerable { private readonly LinkedList _list = new LinkedList(); private readonly Dictionary> _dictionary = new Dictionary>(); public int Count => _list.Count; public bool Add(T item) { if (_dictionary.ContainsKey(item)) { return false; } LinkedListNode value = _list.AddLast(item); _dictionary.Add(item, value); return true; } public bool Remove(T item) { if (!_dictionary.TryGetValue(item, out var value)) { return false; } _dictionary.Remove(item); _list.Remove(value); return true; } public bool Contains(T item) { return _dictionary.ContainsKey(item); } public LinkedList.Enumerator GetEnumerator() { return _list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return _list.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return ((IEnumerable)this).GetEnumerator(); } } [RequireComponent(typeof(Renderer))] public sealed class Outline : MonoBehaviour { private static readonly Material[] EmptyMaterials = (Material[])(object)new Material[0]; private Material[] _sharedMaterials; public int color; public bool eraseRenderer; public Renderer Renderer { get; private set; } public SpriteRenderer SpriteRenderer { get; private set; } public SkinnedMeshRenderer SkinnedMeshRenderer { get; private set; } public MeshFilter MeshFilter { get; private set; } public Material[] SharedMaterials { get { if (_sharedMaterials == null && (Object)(object)Renderer != (Object)null) { _sharedMaterials = Renderer.sharedMaterials; } return _sharedMaterials ?? EmptyMaterials; } } private void Awake() { Renderer = ((Component)this).GetComponent(); SkinnedMeshRenderer = ((Component)this).GetComponent(); SpriteRenderer = ((Component)this).GetComponent(); MeshFilter = ((Component)this).GetComponent(); } private void OnEnable() { OutlineEffect.Instance?.AddOutline(this); } private void OnDisable() { OutlineEffect.Instance?.RemoveOutline(this); } } [DisallowMultipleComponent] [RequireComponent(typeof(Camera))] public sealed class OutlineEffect : MonoBehaviour { public sealed class Y4NGZHDRPOutlinePass : CustomPass { internal OutlineEffect Owner; public override void Execute(CustomPassContext ctx) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0021: 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_0069: 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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) OutlineEffect owner = Owner; if ((Object)(object)owner == (Object)null || ctx.cmd == null || ctx.hdCamera == null) { return; } Camera camera = ctx.hdCamera.camera; if ((Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)owner.ResolveSourceCamera()) { return; } if (!owner.HasActiveOutlines(out var activeOutlineCount)) { owner.ResetHdrpCompositeTrace(); return; } int width = Mathf.Max(1, ctx.hdCamera.actualWidth); int height = Mathf.Max(1, ctx.hdCamera.actualHeight); owner.sourceCamera = camera; if (!owner.RenderOutlineBuffer(ctx.cmd)) { owner.ResetHdrpCompositeTrace(); return; } if ((Object)(object)owner.outlineOverlayMaterial == (Object)null || (Object)(object)owner.renderTexture == (Object)null || !owner._outlineTextureValid) { owner.ResetHdrpCompositeTrace(); return; } owner.outlineOverlayMaterial.SetTexture(OutlineSourceId, (Texture)(object)owner.renderTexture); HDUtils.DrawFullScreen(ctx.cmd, owner.outlineOverlayMaterial, ctx.cameraColorBuffer, ctx.cameraDepthBuffer, (MaterialPropertyBlock)null, 0); owner.TraceHdrpComposite(width, height, activeOutlineCount); } } private readonly LinkedSet _outlines = new LinkedSet(); private readonly List _materialBuffer = new List(); [Range(1f, 6f)] public float lineThickness = 1.25f; [Range(0f, 10f)] public float lineIntensity = 0.5f; [Range(0f, 1f)] public float fillAmount = 0.2f; public Color lineColor0 = Color.red; public Color lineColor1 = Color.green; public Color lineColor2 = Color.blue; public bool additiveRendering; public bool backfaceCulling = true; public Color fillColor = Color.blue; public bool useFillColor; public bool cornerOutlines; public bool addLinesBetweenColors; public bool scaleWithScreenSize = true; [Range(0f, 1f)] public float alphaCutoff = 0.5f; public bool flipY; public Camera sourceCamera; public bool autoEnableOutlines; public Camera outlineCamera; public Material outlineShaderMaterial; private Material outlineOverlayMaterial; public RenderTexture renderTexture; public RenderTexture extraRenderTexture; private Material _outline1Material; private Material _outline2Material; private Material _outline3Material; private Material _outlineEraseMaterial; private Material _fallback1Material; private Material _fallback2Material; private Material _fallback3Material; private Shader _outlineShader; private Shader _outlineBufferShader; private Shader _outlineOverlayShader; private Shader _maskShader; private CommandBuffer _immediateCommandBuffer; private GameObject _customPassVolumeObject; private CustomPassVolume _customPassVolume; private Y4NGZHDRPOutlinePass _customPass; private bool _renderNextFrame; private bool _pipelineCallbacksRegistered; private bool _outlineTextureValid; private float _nextFallbackWarningAt; private float _nextHdrpWarningAt; private bool _hdrpTraceActive; private int _lastHdrpTraceActiveCount = int.MinValue; private int _lastHdrpTraceWidth; private int _lastHdrpTraceHeight; private static readonly int CompositeTempId = Shader.PropertyToID("_Y4NGZOutlineCompositeTemp"); private static readonly int OutlineSourceId = Shader.PropertyToID("_OutlineSource"); private static readonly string[] MaskPassNames = new string[4] { "ForwardOnly", "Forward", "SRPDefaultUnlit", "DepthForwardOnly" }; public static OutlineEffect Instance { get; private set; } private void Awake() { if ((Object)(object)Instance != (Object)null && (Object)(object)Instance != (Object)(object)this) { Object.Destroy((Object)(object)Instance); } Instance = this; } private void Start() { CreateMaterialsIfNeeded(); UpdateMaterialsPublicProperties(); if ((Object)(object)sourceCamera == (Object)null) { sourceCamera = ((Component)this).GetComponent() ?? Camera.main; } RecreateRenderTexturesIfNeeded(); EnsureHdrpCustomPass(); } private void OnEnable() { if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null) { EnsureHdrpCustomPass(); } else { RegisterPipelineCallbacks(); } Outline[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && !_outlines.Contains(array[i])) { _outlines.Add(array[i]); } } } private void OnDisable() { UnregisterPipelineCallbacks(); if ((Object)(object)_customPassVolume != (Object)null) { ((Behaviour)_customPassVolume).enabled = false; } ResetHdrpCompositeTrace(); } private void OnPreRender() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (!((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null)) { if (_immediateCommandBuffer == null) { _immediateCommandBuffer = new CommandBuffer { name = "Y4NGZ Outline Buffer" }; } _immediateCommandBuffer.Clear(); if (RenderOutlineBuffer(_immediateCommandBuffer)) { Graphics.ExecuteCommandBuffer(_immediateCommandBuffer); } } } [ImageEffectOpaque] private void OnRenderImage(RenderTexture source, RenderTexture destination) { if ((Object)(object)outlineShaderMaterial == (Object)null || (Object)(object)renderTexture == (Object)null || !_outlineTextureValid) { Graphics.Blit((Texture)(object)source, destination); return; } outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)renderTexture); if (addLinesBetweenColors && (Object)(object)extraRenderTexture != (Object)null) { Graphics.Blit((Texture)(object)source, extraRenderTexture, outlineShaderMaterial, 0); outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)extraRenderTexture); } Graphics.Blit((Texture)(object)source, destination, outlineShaderMaterial, 1); } private void OnDestroy() { if ((Object)(object)Instance == (Object)(object)this) { Instance = null; } UnregisterPipelineCallbacks(); if ((Object)(object)_customPassVolumeObject != (Object)null) { Object.Destroy((Object)(object)_customPassVolumeObject); _customPassVolumeObject = null; _customPassVolume = null; _customPass = null; } if (_immediateCommandBuffer != null) { _immediateCommandBuffer.Release(); _immediateCommandBuffer = null; } if ((Object)(object)renderTexture != (Object)null) { renderTexture.Release(); } if ((Object)(object)extraRenderTexture != (Object)null) { extraRenderTexture.Release(); } DestroyMaterials(); } public void AddOutline(Outline outline) { if (!((Object)(object)outline == (Object)null)) { _outlines.Add(outline); EnsureHdrpCustomPass(); } } public void RemoveOutline(Outline outline) { if ((Object)(object)outline != (Object)null) { _outlines.Remove(outline); } } private bool HasActiveOutlines(out int activeOutlineCount) { activeOutlineCount = 0; if (_outlines.Count == 0) { return false; } foreach (Outline outline in _outlines) { if ((Object)(object)outline != (Object)null && ((Behaviour)outline).enabled && (Object)(object)outline.Renderer != (Object)null && outline.Renderer.enabled) { activeOutlineCount++; } } return activeOutlineCount > 0; } private void EnsureHdrpCustomPass() { //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_0085: Expected O, but got Unknown //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)GraphicsSettings.currentRenderPipeline == (Object)null) { return; } Camera val = ResolveSourceCamera(); if ((Object)(object)val == (Object)null) { return; } if ((Object)(object)_customPassVolume != (Object)null && _customPass != null) { _customPass.Owner = this; _customPassVolume.targetCamera = val; ((Behaviour)_customPassVolume).enabled = ((Behaviour)this).isActiveAndEnabled; return; } if ((Object)(object)_customPassVolumeObject == (Object)null) { _customPassVolumeObject = new GameObject("Y4NGZ_OutlineCustomPassVolume") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_customPassVolumeObject); } _customPassVolume = _customPassVolumeObject.GetComponent(); if ((Object)(object)_customPassVolume == (Object)null) { _customPassVolume = _customPassVolumeObject.AddComponent(); } _customPassVolume.isGlobal = true; _customPassVolume.priority = 1000f; _customPassVolume.injectionPoint = (CustomPassInjectionPoint)3; _customPassVolume.targetCamera = val; _customPassVolume.customPasses.Clear(); CustomPass val2 = _customPassVolume.AddPassOfType(typeof(Y4NGZHDRPOutlinePass)); _customPass = val2 as Y4NGZHDRPOutlinePass; if (_customPass == null) { if (Time.unscaledTime >= _nextHdrpWarningAt) { _nextHdrpWarningAt = Time.unscaledTime + 10f; ManualLogSource log = Y4NGZUpgrades.Plugin.Log; if (log != null) { log.LogWarning((object)"OutlineEffect: failed to register HDRP custom pass; outlines may be invisible."); } } return; } ((CustomPass)_customPass).name = "Y4NGZ Outline Composite"; ((CustomPass)_customPass).enabled = true; ((CustomPass)_customPass).targetColorBuffer = (TargetBuffer)0; ((CustomPass)_customPass).targetDepthBuffer = (TargetBuffer)0; ((CustomPass)_customPass).clearFlags = (ClearFlag)0; _customPass.Owner = this; ((Behaviour)_customPassVolume).enabled = ((Behaviour)this).isActiveAndEnabled; ManualLogSource log2 = Y4NGZUpgrades.Plugin.Log; if (log2 != null) { log2.LogInfo((object)("OutlineEffect: HDRP custom pass registered on '" + ((Object)val).name + "'.")); } } private void TraceHdrpComposite(int width, int height, int activeOutlineCount) { if (!_hdrpTraceActive || _lastHdrpTraceActiveCount != activeOutlineCount || _lastHdrpTraceWidth != width || _lastHdrpTraceHeight != height) { _hdrpTraceActive = true; _lastHdrpTraceActiveCount = activeOutlineCount; _lastHdrpTraceWidth = width; _lastHdrpTraceHeight = height; ManualLogSource log = Y4NGZUpgrades.Plugin.Log; if (log != null) { log.LogDebug((object)$"OutlineEffect: HDRP custom pass compositing {activeOutlineCount} outline renderer(s) at {width}x{height}."); } } } private void ResetHdrpCompositeTrace() { _hdrpTraceActive = false; _lastHdrpTraceActiveCount = int.MinValue; _lastHdrpTraceWidth = 0; _lastHdrpTraceHeight = 0; } public void UpdateMaterialsPublicProperties() { if (CreateMaterialsIfNeeded() && !((Object)(object)outlineShaderMaterial == (Object)null)) { float num = 1f; if (scaleWithScreenSize) { num = (float)Screen.height / 360f; } float thicknessScale = ((scaleWithScreenSize && num >= 1f) ? num : 1f); ApplyMaterialProperties(outlineShaderMaterial, thicknessScale, legacyComposite: true); if ((Object)(object)outlineOverlayMaterial != (Object)null) { ApplyMaterialProperties(outlineOverlayMaterial, thicknessScale, legacyComposite: false); } Shader.SetGlobalFloat("_OutlineAlphaCutoff", alphaCutoff); } } private void ApplyMaterialProperties(Material material, float thicknessScale, bool legacyComposite) { //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_006d: 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_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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: 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) if (!((Object)(object)material == (Object)null)) { material.SetFloat("_LineThicknessX", thicknessScale * (lineThickness / Mathf.Max(1f, (float)Screen.width))); material.SetFloat("_LineThicknessY", thicknessScale * (lineThickness / Mathf.Max(1f, (float)Screen.height))); material.SetFloat("_LineIntensity", lineIntensity); material.SetColor("_LineColor1", legacyComposite ? (lineColor0 * lineColor0) : lineColor0); material.SetColor("_LineColor2", legacyComposite ? (lineColor1 * lineColor1) : lineColor1); material.SetColor("_LineColor3", legacyComposite ? (lineColor2 * lineColor2) : lineColor2); material.SetInt("_CornerOutlines", cornerOutlines ? 1 : 0); if (legacyComposite) { material.SetFloat("_FillAmount", fillAmount); material.SetColor("_FillColor", fillColor); material.SetFloat("_UseFillColor", useFillColor ? 1f : 0f); material.SetInt("_FlipY", flipY ? 1 : 0); material.SetInt("_Dark", (!additiveRendering) ? 1 : 0); } } } private void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null || (Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera()) { return; } CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Buffer"); try { if (RenderOutlineBuffer(val)) { ((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val); } } finally { CommandBufferPool.Release(val); } } private void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { //IL_0098: 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_00b9: 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) if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null || (Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera() || (Object)(object)outlineShaderMaterial == (Object)null || (Object)(object)renderTexture == (Object)null || !_outlineTextureValid) { return; } int num = Mathf.Max(1, camera.pixelWidth); int num2 = Mathf.Max(1, camera.pixelHeight); CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Composite"); try { outlineShaderMaterial.SetTexture("_OutlineSource", (Texture)(object)renderTexture); val.GetTemporaryRT(CompositeTempId, num, num2, 0, (FilterMode)1, (RenderTextureFormat)7); val.Blit(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2), RenderTargetIdentifier.op_Implicit(CompositeTempId), outlineShaderMaterial, 1); val.Blit(RenderTargetIdentifier.op_Implicit(CompositeTempId), RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2)); val.ReleaseTemporaryRT(CompositeTempId); ((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val); } finally { CommandBufferPool.Release(val); } } private void DrawFallbackSilhouettes(ScriptableRenderContext context, Camera camera) { if ((Object)(object)camera == (Object)null || (Object)(object)camera != (Object)(object)ResolveSourceCamera()) { return; } CommandBuffer val = CommandBufferPool.Get("Y4NGZ Outline Fallback"); try { DrawFallbackSilhouettes(val); ((ScriptableRenderContext)(ref context)).ExecuteCommandBuffer(val); } finally { CommandBufferPool.Release(val); } } private void DrawImmediateFallback() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Expected O, but got Unknown if (_outlines.Count != 0) { if (_immediateCommandBuffer == null) { _immediateCommandBuffer = new CommandBuffer { name = "Y4NGZ Outline Buffer" }; } _immediateCommandBuffer.Clear(); DrawFallbackSilhouettes(_immediateCommandBuffer); Graphics.ExecuteCommandBuffer(_immediateCommandBuffer); } } private bool RenderOutlineBuffer(CommandBuffer commandBuffer) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00bf: Unknown result type (might be due to invalid IL or missing references) if (commandBuffer == null) { return false; } if ((Object)(object)ResolveSourceCamera() == (Object)null) { return false; } if (_outlines.Count == 0) { if (!_renderNextFrame) { return false; } _renderNextFrame = false; } else { _renderNextFrame = true; } if (!CreateMaterialsIfNeeded()) { return false; } RecreateRenderTexturesIfNeeded(); UpdateMaterialsPublicProperties(); if ((Object)(object)renderTexture == (Object)null) { return false; } commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((Texture)(object)renderTexture)); commandBuffer.SetViewport(new Rect(0f, 0f, (float)((Texture)renderTexture).width, (float)((Texture)renderTexture).height)); commandBuffer.ClearRenderTarget(true, true, Color.clear); commandBuffer.SetViewProjectionMatrices(sourceCamera.worldToCameraMatrix, sourceCamera.projectionMatrix); foreach (Outline outline in _outlines) { DrawOutline(commandBuffer, outline); } _outlineTextureValid = true; return true; } private Camera ResolveSourceCamera() { if ((Object)(object)sourceCamera == (Object)null) { sourceCamera = ((Component)this).GetComponent() ?? Camera.main; } return sourceCamera; } private void RegisterPipelineCallbacks() { if (!_pipelineCallbacksRegistered) { RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; RenderPipelineManager.endCameraRendering += OnEndCameraRendering; _pipelineCallbacksRegistered = true; } } private void UnregisterPipelineCallbacks() { if (_pipelineCallbacksRegistered) { RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; _pipelineCallbacksRegistered = false; } } private void DrawOutline(CommandBuffer commandBuffer, Outline outline) { if ((Object)(object)outline == (Object)null || (Object)(object)outline.Renderer == (Object)null || !((Behaviour)outline).enabled) { return; } Material[] sharedMaterials = outline.SharedMaterials; for (int i = 0; i < sharedMaterials.Length; i++) { Material val = ResolveBufferMaterial(outline, sharedMaterials[i]); if ((Object)(object)val == (Object)null) { continue; } if (val.HasProperty("_Culling")) { val.SetInt("_Culling", backfaceCulling ? 2 : 0); } if (val.HasProperty("_Cull")) { val.SetInt("_Cull", backfaceCulling ? 2 : 0); } MeshFilter meshFilter = outline.MeshFilter; SkinnedMeshRenderer skinnedMeshRenderer = outline.SkinnedMeshRenderer; SpriteRenderer spriteRenderer = outline.SpriteRenderer; int num = ResolveMaskMaterialPass(val); if ((Object)(object)meshFilter != (Object)null && (Object)(object)meshFilter.sharedMesh != (Object)null) { if (i < meshFilter.sharedMesh.subMeshCount) { commandBuffer.DrawRenderer(outline.Renderer, val, i, num); } } else if ((Object)(object)skinnedMeshRenderer != (Object)null && (Object)(object)skinnedMeshRenderer.sharedMesh != (Object)null) { if (i < skinnedMeshRenderer.sharedMesh.subMeshCount) { commandBuffer.DrawRenderer(outline.Renderer, val, i, num); } } else if ((Object)(object)spriteRenderer != (Object)null) { commandBuffer.DrawRenderer(outline.Renderer, val, i, num); } } } private void DrawFallbackSilhouettes(CommandBuffer commandBuffer) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) if (commandBuffer == null || _outlines.Count == 0 || !CreateFallbackMaterialsIfNeeded()) { return; } commandBuffer.SetRenderTarget(RenderTargetIdentifier.op_Implicit((BuiltinRenderTextureType)2)); foreach (Outline outline in _outlines) { DrawFallbackSilhouette(commandBuffer, outline); } } private void DrawFallbackSilhouettes(CommandBuffer commandBuffer, RTHandle colorBuffer, RTHandle depthBuffer) { if (commandBuffer == null || colorBuffer == null || _outlines.Count == 0 || !CreateFallbackMaterialsIfNeeded()) { return; } CoreUtils.SetRenderTarget(commandBuffer, colorBuffer, depthBuffer, (ClearFlag)0, 0, (CubemapFace)(-1), -1); foreach (Outline outline in _outlines) { DrawFallbackSilhouette(commandBuffer, outline); } } private void DrawFallbackSilhouette(CommandBuffer commandBuffer, Outline outline) { if ((Object)(object)outline == (Object)null || (Object)(object)outline.Renderer == (Object)null || !((Behaviour)outline).enabled) { return; } Material fallbackMaterialFromId = GetFallbackMaterialFromId(outline.color); if (!((Object)(object)fallbackMaterialFromId == (Object)null)) { Material[] sharedMaterials = outline.SharedMaterials; int num = ResolveMaskMaterialPass(fallbackMaterialFromId); for (int i = 0; i < sharedMaterials.Length; i++) { commandBuffer.DrawRenderer(outline.Renderer, fallbackMaterialFromId, i, num); } } } private Material ResolveBufferMaterial(Outline outline, Material sourceMaterial) { if ((Object)(object)outline == (Object)null) { return null; } if (!outline.eraseRenderer) { return GetMaterialFromId(outline.color); } return _outlineEraseMaterial; } private Material GetMaterialFromId(int id) { return (Material)(id switch { 1 => _outline2Material, 2 => _outline3Material, _ => _outline1Material, }); } private Material GetFallbackMaterialFromId(int id) { return (Material)(id switch { 1 => _fallback2Material, 2 => _fallback3Material, _ => _fallback1Material, }); } private void EnsureOutlineCamera() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Expected O, but got Unknown if ((Object)(object)sourceCamera == (Object)null || (Object)(object)outlineCamera != (Object)null) { return; } Camera[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null && ((Object)componentsInChildren[i]).name == "Outline Camera") { outlineCamera = componentsInChildren[i]; ((Behaviour)outlineCamera).enabled = false; return; } } GameObject val = new GameObject("Outline Camera"); val.transform.SetParent(((Component)sourceCamera).transform, false); outlineCamera = val.AddComponent(); ((Behaviour)outlineCamera).enabled = false; } private void RecreateRenderTexturesIfNeeded() { //IL_00a5: 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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Expected O, but got Unknown //IL_00c3: 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_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown if ((Object)(object)sourceCamera == (Object)null) { return; } int num = Mathf.Max(1, sourceCamera.pixelWidth); int num2 = Mathf.Max(1, sourceCamera.pixelHeight); if ((Object)(object)renderTexture == (Object)null || ((Texture)renderTexture).width != num || ((Texture)renderTexture).height != num2) { if ((Object)(object)renderTexture != (Object)null) { renderTexture.Release(); } if ((Object)(object)extraRenderTexture != (Object)null) { extraRenderTexture.Release(); } _outlineTextureValid = false; renderTexture = new RenderTexture(num, num2, 16, (RenderTextureFormat)0) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; extraRenderTexture = new RenderTexture(num, num2, 16, (RenderTextureFormat)0) { filterMode = (FilterMode)0, wrapMode = (TextureWrapMode)1 }; if ((Object)(object)outlineCamera != (Object)null) { outlineCamera.targetTexture = renderTexture; } } } private bool CreateMaterialsIfNeeded() { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_0107: 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_00e3: Expected O, but got Unknown //IL_013a: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_outlineShader == (Object)null) { _outlineShader = OutlineRuntimeAssets.LoadShader("OutlineShader"); } if ((Object)(object)_outlineBufferShader == (Object)null) { _outlineBufferShader = OutlineRuntimeAssets.LoadShader("OutlineBufferShader"); } if ((Object)(object)_outlineOverlayShader == (Object)null) { _outlineOverlayShader = OutlineRuntimeAssets.LoadShader("Y4NGZOutlineOverlayShader"); } if ((Object)(object)_outlineShader == (Object)null) { return false; } if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null && (Object)(object)_outlineOverlayShader == (Object)null) { return false; } if ((Object)(object)outlineShaderMaterial == (Object)null) { outlineShaderMaterial = new Material(_outlineShader) { hideFlags = (HideFlags)61 }; } if ((Object)(object)outlineOverlayMaterial == (Object)null && (Object)(object)_outlineOverlayShader != (Object)null) { outlineOverlayMaterial = new Material(_outlineOverlayShader) { hideFlags = (HideFlags)61 }; } if ((Object)(object)_outlineEraseMaterial == (Object)null) { _outlineEraseMaterial = CreateMaterial(new Color(0f, 0f, 0f, 0f)); } if ((Object)(object)_outline1Material == (Object)null) { _outline1Material = CreateMaterial(new Color(1f, 0f, 0f, 1f)); } if ((Object)(object)_outline2Material == (Object)null) { _outline2Material = CreateMaterial(new Color(0f, 1f, 0f, 1f)); } if ((Object)(object)_outline3Material == (Object)null) { _outline3Material = CreateMaterial(new Color(0f, 0f, 1f, 1f)); } if ((Object)(object)outlineShaderMaterial != (Object)null && ((Object)(object)GraphicsSettings.currentRenderPipeline == (Object)null || (Object)(object)outlineOverlayMaterial != (Object)null) && (Object)(object)_outlineEraseMaterial != (Object)null && (Object)(object)_outline1Material != (Object)null && (Object)(object)_outline2Material != (Object)null) { return (Object)(object)_outline3Material != (Object)null; } return false; } private bool CreateFallbackMaterialsIfNeeded() { //IL_0011: 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_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fallback1Material == (Object)null) { _fallback1Material = CreateFallbackMaterial(lineColor0); } if ((Object)(object)_fallback2Material == (Object)null) { _fallback2Material = CreateFallbackMaterial(lineColor1); } if ((Object)(object)_fallback3Material == (Object)null) { _fallback3Material = CreateFallbackMaterial(lineColor2); } if ((Object)(object)_fallback1Material != (Object)null && (Object)(object)_fallback2Material != (Object)null) { return (Object)(object)_fallback3Material != (Object)null; } return false; } private Material CreateMaterial(Color emissionColor) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Expected O, but got Unknown //IL_0033: Expected O, but got Unknown Shader val = ResolveMaskShader(); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val) { hideFlags = (HideFlags)61, renderQueue = 2500 }; ConfigureMaskMaterial(val2, emissionColor); return val2; } private Shader ResolveMaskShader() { if ((Object)(object)_maskShader != (Object)null) { return _maskShader; } if ((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null) { _maskShader = Shader.Find("HDRP/Unlit") ?? Shader.Find("Hidden/Internal-Colored") ?? Shader.Find("Unlit/Color"); } if ((Object)(object)_maskShader == (Object)null) { _maskShader = _outlineBufferShader; } return _maskShader; } private static void ConfigureMaskMaterial(Material material, Color color) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { SetColorIfPresent(material, "_Color", color); SetColorIfPresent(material, "_BaseColor", color); SetColorIfPresent(material, "_UnlitColor", color); SetColorIfPresent(material, "_EmissiveColor", color); SetFloatIfPresent(material, "_SurfaceType", 0f); SetFloatIfPresent(material, "_AlphaCutoffEnable", 0f); SetFloatIfPresent(material, "_ZWrite", 0f); SetFloatIfPresent(material, "_ZTestDepthEqualForOpaque", 8f); SetIntIfPresent(material, "_SrcBlend", 1); SetIntIfPresent(material, "_DstBlend", 0); SetIntIfPresent(material, "_Cull", 0); SetIntIfPresent(material, "_Culling", 0); material.DisableKeyword("_ALPHATEST_ON"); material.DisableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } } private static int ResolveMaskMaterialPass(Material material) { if ((Object)(object)material == (Object)null) { return 0; } for (int i = 0; i < MaskPassNames.Length; i++) { int num = material.FindPass(MaskPassNames[i]); if (num >= 0) { return num; } } return 0; } private static void SetColorIfPresent(Material material, string name, Color value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(name)) { material.SetColor(name, value); } } private static void SetFloatIfPresent(Material material, string name, float value) { if (material.HasProperty(name)) { material.SetFloat(name, value); } } private static void SetIntIfPresent(Material material, string name, int value) { if (material.HasProperty(name)) { material.SetInt(name, value); } } private Material CreateFallbackMaterial(Color color) { //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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00ac: Expected O, but got Unknown Shader val = (((Object)(object)GraphicsSettings.currentRenderPipeline != (Object)null) ? (Shader.Find("HDRP/Unlit") ?? Shader.Find("Hidden/Internal-Colored")) : Shader.Find("Hidden/Internal-Colored")); if ((Object)(object)val == (Object)null) { if (Time.unscaledTime >= _nextFallbackWarningAt) { _nextFallbackWarningAt = Time.unscaledTime + 10f; ManualLogSource log = Y4NGZUpgrades.Plugin.Log; if (log != null) { log.LogWarning((object)"OutlineEffect: Hidden/Internal-Colored shader unavailable; through-wall fallback silhouettes disabled."); } } return null; } Material val2 = new Material(val) { hideFlags = (HideFlags)61, renderQueue = 5000 }; ConfigureOverlayMaterial(val2, new Color(color.r, color.g, color.b, 0.32f)); return val2; } private static void ConfigureOverlayMaterial(Material material, Color color) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { SetColorIfPresent(material, "_Color", color); SetColorIfPresent(material, "_BaseColor", color); SetColorIfPresent(material, "_UnlitColor", color); SetColorIfPresent(material, "_EmissiveColor", color); SetFloatIfPresent(material, "_SurfaceType", 1f); SetFloatIfPresent(material, "_BlendMode", 0f); SetFloatIfPresent(material, "_AlphaCutoffEnable", 0f); SetFloatIfPresent(material, "_ZWrite", 0f); SetFloatIfPresent(material, "_TransparentZWrite", 0f); SetFloatIfPresent(material, "_ZTest", 8f); SetFloatIfPresent(material, "_ZTestTransparent", 8f); SetFloatIfPresent(material, "_ZTestDepthEqualForOpaque", 8f); SetIntIfPresent(material, "_SrcBlend", 5); SetIntIfPresent(material, "_DstBlend", 10); SetIntIfPresent(material, "_AlphaSrcBlend", 1); SetIntIfPresent(material, "_AlphaDstBlend", 10); SetIntIfPresent(material, "_Cull", 0); SetIntIfPresent(material, "_CullMode", 0); SetIntIfPresent(material, "_CullModeForward", 0); material.EnableKeyword("_SURFACE_TYPE_TRANSPARENT"); material.EnableKeyword("_BLENDMODE_ALPHA"); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); } } private void UpdateOutlineCameraFromSource() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)outlineCamera == (Object)null) && !((Object)(object)sourceCamera == (Object)null)) { outlineCamera.CopyFrom(sourceCamera); outlineCamera.renderingPath = (RenderingPath)1; outlineCamera.backgroundColor = new Color(0f, 0f, 0f, 0f); outlineCamera.clearFlags = (CameraClearFlags)2; outlineCamera.rect = new Rect(0f, 0f, 1f, 1f); outlineCamera.cullingMask = 0; outlineCamera.targetTexture = renderTexture; ((Behaviour)outlineCamera).enabled = false; outlineCamera.allowHDR = false; } } private void DestroyMaterials() { for (int i = 0; i < _materialBuffer.Count; i++) { if ((Object)(object)_materialBuffer[i] != (Object)null) { Object.Destroy((Object)(object)_materialBuffer[i]); } } _materialBuffer.Clear(); if ((Object)(object)outlineShaderMaterial != (Object)null) { Object.Destroy((Object)(object)outlineShaderMaterial); } if ((Object)(object)outlineOverlayMaterial != (Object)null) { Object.Destroy((Object)(object)outlineOverlayMaterial); } if ((Object)(object)_outlineEraseMaterial != (Object)null) { Object.Destroy((Object)(object)_outlineEraseMaterial); } if ((Object)(object)_outline1Material != (Object)null) { Object.Destroy((Object)(object)_outline1Material); } if ((Object)(object)_outline2Material != (Object)null) { Object.Destroy((Object)(object)_outline2Material); } if ((Object)(object)_outline3Material != (Object)null) { Object.Destroy((Object)(object)_outline3Material); } if ((Object)(object)_fallback1Material != (Object)null) { Object.Destroy((Object)(object)_fallback1Material); } if ((Object)(object)_fallback2Material != (Object)null) { Object.Destroy((Object)(object)_fallback2Material); } if ((Object)(object)_fallback3Material != (Object)null) { Object.Destroy((Object)(object)_fallback3Material); } } } } namespace Y4NGZUpgrades { internal static class ArmoryBridge { private const string ArmoryPluginGuid = "com.y4ngz.betterarmory"; private const string PrizeApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryPrizeApi"; private const string AmmoApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi"; private const string PresentationApiTypeName = "Y4NGZUpgrades.Weapons.ArmoryPresentationApi"; private static readonly string[] NoIds = new string[0]; private static readonly Type[] OneString = new Type[1] { typeof(string) }; private static bool _presenceResolved; private static bool _present; private static readonly Lazy WeaponPrizeIds = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponPrizeIds", Type.EmptyTypes); private static readonly Lazy WeaponDisplayName = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponDisplayName", OneString); private static readonly Lazy WeaponPrizePrefab = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponPrizePrefab", OneString); private static readonly Lazy WeaponItem = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponItem", OneString); private static readonly Lazy WeaponFingerprint = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetWeaponFingerprintTokens", Type.EmptyTypes); private static readonly Lazy WeaponPrizeInit = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "InitializeWeaponPrize", new Type[2] { typeof(GameObject), typeof(string) }); private static readonly Lazy AmmoPrizeIds = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoPrizeIds", Type.EmptyTypes); private static readonly Lazy AmmoDisplayName = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoDisplayName", OneString); private static readonly Lazy AmmoPrizePrefab = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoPrizePrefab", OneString); private static readonly Lazy AmmoItem = Method("Y4NGZUpgrades.Weapons.ArmoryPrizeApi", "GetAmmoItem", OneString); private static readonly Lazy AmmoFamilyIds = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyIds", Type.EmptyTypes); private static readonly Lazy AmmoFamilyLabel = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyLabel", OneString); private static readonly Lazy AmmoFamilyReserve = Method("Y4NGZUpgrades.Weapons.ArmoryAmmoReserveApi", "GetAmmoFamilyReserve", OneString); private static readonly Lazy StopPresentation = Method("Y4NGZUpgrades.Weapons.ArmoryPresentationApi", "StopPresentationForHeldItemStow", new Type[1] { typeof(PlayerControllerB) }); private static readonly HashSet Warned = new HashSet(StringComparer.Ordinal); internal static bool IsArmoryPresent { get { if (_presenceResolved) { return _present; } _presenceResolved = true; try { _present = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("com.y4ngz.betterarmory"); } catch { _present = false; } return _present; } } internal static string[] GetWeaponPrizeIds() { return Strings(WeaponPrizeIds); } internal static string GetWeaponDisplayName(string weaponId) { return (Invoke(WeaponDisplayName, weaponId) as string) ?? weaponId; } internal static GameObject GetWeaponPrizePrefab(string weaponId) { object obj = Invoke(WeaponPrizePrefab, weaponId); return (GameObject)((obj is GameObject) ? obj : null); } internal static Item GetWeaponItem(string weaponId) { object obj = Invoke(WeaponItem, weaponId); return (Item)((obj is Item) ? obj : null); } internal static string[] GetWeaponFingerprintTokens() { return Strings(WeaponFingerprint); } internal static void InitializeWeaponPrize(GameObject instance, string weaponId) { MethodInfo methodInfo = Resolve(WeaponPrizeInit); if (methodInfo == null || (Object)(object)instance == (Object)null) { return; } try { methodInfo.Invoke(null, new object[2] { instance, weaponId }); } catch (Exception ex) { Warn("InitializeWeaponPrize", ex); } } internal static string[] GetAmmoPrizeIds() { return Strings(AmmoPrizeIds); } internal static string GetAmmoDisplayName(string pickupId) { return (Invoke(AmmoDisplayName, pickupId) as string) ?? pickupId; } internal static GameObject GetAmmoPrizePrefab(string pickupId) { object obj = Invoke(AmmoPrizePrefab, pickupId); return (GameObject)((obj is GameObject) ? obj : null); } internal static Item GetAmmoItem(string pickupId) { object obj = Invoke(AmmoItem, pickupId); return (Item)((obj is Item) ? obj : null); } internal static string[] GetAmmoFamilyIds() { return Strings(AmmoFamilyIds); } internal static string GetAmmoFamilyLabel(string familyId) { return (Invoke(AmmoFamilyLabel, familyId) as string) ?? familyId; } internal static int GetAmmoFamilyReserve(string familyId) { object obj = Invoke(AmmoFamilyReserve, familyId); if (obj is int) { return (int)obj; } return 0; } internal static void StopPresentationForHeldItemStow(PlayerControllerB player) { MethodInfo methodInfo = Resolve(StopPresentation); if (methodInfo == null || (Object)(object)player == (Object)null) { return; } try { methodInfo.Invoke(null, new object[1] { player }); } catch (Exception ex) { Warn("StopPresentationForHeldItemStow", ex); } } private static Lazy Method(string typeName, string methodName, Type[] parameters) { return new Lazy(delegate { Type type = FindType(typeName); if (type == null) { return (MethodInfo)null; } MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public, null, parameters, null); if (method == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ArmoryBridge] " + typeName + "." + methodName + " was not found. That bridge is disabled for this session.")); } } return method; }); } private static MethodInfo Resolve(Lazy lazy) { try { return lazy.Value; } catch { return null; } } private static object Invoke(Lazy lazy, string argument) { MethodInfo methodInfo = Resolve(lazy); if (methodInfo == null) { return null; } try { return methodInfo.Invoke(null, new object[1] { argument }); } catch (Exception ex) { Warn(methodInfo.Name, ex); return null; } } private static string[] Strings(Lazy lazy) { MethodInfo methodInfo = Resolve(lazy); if (methodInfo == null) { return NoIds; } try { return (methodInfo.Invoke(null, null) as string[]) ?? NoIds; } catch (Exception ex) { Warn(methodInfo.Name, ex); return NoIds; } } private static void Warn(string member, Exception ex) { if (Warned.Add(member)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ArmoryBridge] " + member + " failed safely: " + ex.Message)); } } } private static Type FindType(string fullName) { if (!IsArmoryPresent) { return null; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } catch { } } if (IsArmoryPresent) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ArmoryBridge] Better Armory is installed but '" + fullName + "' was not found. That bridge is disabled for this session.")); } } return null; } } internal static class ArmoryItemProbe { private const string WeaponNamespacePrefix = "Y4NGZUpgrades.Weapons."; internal static bool IsArmoryWeapon(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return false; } Component[] components = ((Component)item).GetComponents(); foreach (Component val in components) { if (!((Object)(object)val == (Object)null)) { string fullName = ((object)val).GetType().FullName; if (fullName != null && fullName.StartsWith("Y4NGZUpgrades.Weapons.", StringComparison.Ordinal)) { return true; } } } return false; } } public static class ClutchXpPolicy { public static bool IsEligible(bool localEnteredFacility, bool localExtractedAlive, int otherFacilityEntrants, int deadOtherFacilityEntrants) { if (localEnteredFacility && localExtractedAlive && otherFacilityEntrants > 0) { return deadOtherFacilityEntrants == otherFacilityEntrants; } return false; } } internal static class CompanyQuotaTokenIntegration { [HarmonyPatch(typeof(StartOfRound), "Awake")] private static class StartOfRoundAwakePatch { private static void Postfix() { EnsureRegistered(); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] private static class DisconnectPatch { private static void Prefix() { Shutdown(); } } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnGrantMessage; } private const string CompanyApiTypeName = "Y4NGZCompany.Core.QuotaProgressionApi"; private const string GrantMessageName = "Y4NGZUpgrades.CompanyQuotaTokenGrant.v1"; private const string CompanyProtocolVersionMember = "TokenGrantProtocolVersion"; private const int MaxActionIdCharacters = 120; private const int LegacyCompanyProtocolVersion = 1; private static NetworkManager _registeredNetworkManager; private static object _companyHandler; private static MethodInfo _companyUnregister; private static bool _loggedRequestShapeError; internal static bool IsCompanyProviderRegistered => _companyHandler != null; internal static void EnsureRegistered() { RegisterNetworkHandler(); RegisterCompanyHandler(); } internal static void Shutdown() { UnregisterCompanyHandler(); UnregisterNetworkHandler(); } private static void RegisterCompanyHandler() { if (_companyHandler != null) { return; } Type type = FindType("Y4NGZCompany.Core.QuotaProgressionApi"); if (type == null || !IsCompanyProtocolCompatible(type)) { return; } MethodInfo method = type.GetMethod("RegisterTokenGrantHandler", BindingFlags.Static | BindingFlags.Public); _companyUnregister = type.GetMethod("UnregisterTokenGrantHandler", BindingFlags.Static | BindingFlags.Public); ParameterInfo[] array = method?.GetParameters(); if (array == null || array.Length != 1) { return; } Type parameterType = array[0].ParameterType; MethodInfo method2 = parameterType.GetMethod("Invoke"); ParameterInfo[] array2 = method2?.GetParameters(); if (method2 == null || method2.ReturnType != typeof(bool) || array2 == null || array2.Length != 1 || !HasRequiredRequestFields(array2[0].ParameterType)) { return; } try { ParameterExpression parameterExpression = Expression.Parameter(array2[0].ParameterType, "request"); MethodInfo method3 = typeof(CompanyQuotaTokenIntegration).GetMethod("HandleCompanyRequest", BindingFlags.Static | BindingFlags.NonPublic); _companyHandler = Expression.Lambda(parameterType, Expression.Call(method3, Expression.Convert(parameterExpression, typeof(object))), parameterExpression).Compile(); method.Invoke(null, new object[1] { _companyHandler }); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[QuotaTokens] Registered Company quota token provider."); } } catch (Exception ex) { _companyHandler = null; _companyUnregister = null; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[QuotaTokens] Company provider registration failed: " + ex.Message)); } } } private static void UnregisterCompanyHandler() { if (_companyHandler == null) { return; } try { _companyUnregister?.Invoke(null, new object[1] { _companyHandler }); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Company provider unregister failed: " + ex.Message)); } } _companyHandler = null; _companyUnregister = null; } private static bool IsCompanyProtocolCompatible(Type apiType) { FieldInfo field = apiType.GetField("TokenGrantProtocolVersion", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy); int num; if (field == null) { num = 1; } else { if (!(field.GetValue(null) is int num2)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Not registering: Company TokenGrantProtocolVersion is not an int " + $"(Upgrades protocol {1}). Update Y4NGZUpgrades and Y4NGZCompany together.")); } return false; } num = num2; } if (num == 1) { return true; } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[QuotaTokens] Not registering: token-grant protocol mismatch " + $"(Y4NGZUpgrades {1}, Y4NGZCompany {num}). " + "Quota token rewards are disabled until both mods are updated together.")); } return false; } private static bool HasRequiredRequestFields(Type requestType) { string empty = string.Empty; empty = AppendMissing(empty, requestType, "CompletedQuota", typeof(int)); empty = AppendMissing(empty, requestType, "TokensPerPlayer", typeof(int)); empty = AppendMissing(empty, requestType, "ActionId", typeof(string)); if (empty.Length == 0) { return true; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Not registering: Company request type '" + requestType.FullName + "' is missing expected field(s): " + empty + ". Quota token rewards are disabled until both mods are updated together.")); } return false; } private static string AppendMissing(string missing, Type requestType, string name, Type expected) { FieldInfo field = requestType.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == expected) { return missing; } string text = ((field == null) ? name : (name + " (expected " + expected.Name + ", found " + field.FieldType.Name + ")")); if (missing.Length != 0) { return missing + ", " + text; } return text; } private static bool HandleCompanyRequest(object request) { NetworkManager singleton = NetworkManager.Singleton; if (request == null || (Object)(object)singleton == (Object)null || !singleton.IsServer) { return false; } try { Type type = request.GetType(); if (!TryReadIntField(type, request, "CompletedQuota", out var value) || !TryReadIntField(type, request, "TokensPerPlayer", out var value2) || !TryReadStringField(type, request, "ActionId", out var value3)) { return false; } bool isReplay = ReadOptionalBoolField(type, request, "IsReplay"); if (value < 1 || value2 < 1 || string.IsNullOrWhiteSpace(value3)) { return false; } return TryGrantConnectedPlayers(new ExternalTokenGrantRequest(value2, "Y4NGZCompany", $"quota:{value}", value3), isReplay); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Company grant failed: " + ex.Message)); } return false; } } internal static bool TryGrantConnectedPlayers(ExternalTokenGrantRequest request) { return TryGrantConnectedPlayers(request, isReplay: false); } internal unsafe static bool TryGrantConnectedPlayers(ExternalTokenGrantRequest request, bool isReplay) { //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_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_0126: 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_015e: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || request.AmountPerPlayer < 1) { return false; } string text = (string.IsNullOrWhiteSpace(request.Source) ? "external" : request.Source.Trim()); string text2 = (string.IsNullOrWhiteSpace(request.ActionId) ? string.Empty : request.ActionId.Trim()); string text3 = text + ":" + text2; int completedQuota = ParseQuota(request.MilestoneId); if (text2.Length == 0) { return false; } try { if (text3.Length > 120) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Rejected " + text + " grant with oversized action ID.")); } return false; } bool result = ApplyLocalGrant(completedQuota, request.AmountPerPlayer, text3, isReplay); CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return result; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(256, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref completedQuota, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref request.AmountPerPlayer, default(ForPrimitives)); FixedString128Bytes val2 = new FixedString128Bytes(text3); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId != singleton.LocalClientId) { customMessagingManager.SendNamedMessage("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1", connectedClientsId, val, (NetworkDelivery)4); } } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } return true; } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[QuotaTokens] " + text + " grant failed: " + ex.Message)); } return false; } } private static bool ApplyLocalGrant(int completedQuota, int tokensPerPlayer, string actionId, bool isReplay = false) { if (!ProgressionManager.TryApplyExternalTokenGrant(actionId, tokensPerPlayer, out var alreadyApplied)) { return false; } if (alreadyApplied) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)string.Format("[QuotaTokens] Quota {0} grant already in this save's ledger ({1}); ignoring{2}.", completedQuota, actionId, isReplay ? " replay" : string.Empty)); } return true; } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)string.Format("[QuotaTokens] Quota {0} grant accepted{1}: +{2} tokens ({3}).", completedQuota, isReplay ? " (replay)" : string.Empty, tokensPerPlayer, actionId)); } return true; } private static void RegisterNetworkHandler() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || (Object)(object)_registeredNetworkManager == (Object)(object)singleton) { return; } UnregisterNetworkHandler(); try { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnGrantMessage; if (obj == null) { HandleNamedMessageDelegate val = OnGrantMessage; <>O.<0>__OnGrantMessage = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1", (HandleNamedMessageDelegate)obj); _registeredNetworkManager = singleton; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Network handler registration failed: " + ex.Message)); } } } private static void UnregisterNetworkHandler() { NetworkManager registeredNetworkManager = _registeredNetworkManager; if (((registeredNetworkManager != null) ? registeredNetworkManager.CustomMessagingManager : null) != null) { try { _registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZUpgrades.CompanyQuotaTokenGrant.v1"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Network handler unregister failed: " + ex.Message)); } } } _registeredNetworkManager = null; } private unsafe static void OnGrantMessage(ulong senderClientId, FastBufferReader reader) { //IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || senderClientId != 0L) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); FixedString128Bytes val = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); if (num >= 1 && num2 >= 1 && !((FixedString128Bytes)(ref val)).IsEmpty) { ApplyLocalGrant(num, num2, ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString()); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[QuotaTokens] Malformed grant from server: " + ex.Message)); } } } private static Type FindType(string fullName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { Type type = assembly.GetType(fullName, throwOnError: false); if (type != null) { return type; } } catch { } } return null; } private static bool TryReadIntField(Type type, object instance, string name, out int value) { value = 0; if (type.GetField(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(instance) is int num) { value = num; return true; } LogRequestShapeError(type, name, "int"); return false; } private static bool TryReadStringField(Type type, object instance, string name, out string value) { value = string.Empty; FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public); if (field != null && field.FieldType == typeof(string)) { value = (field.GetValue(instance) as string) ?? string.Empty; return true; } LogRequestShapeError(type, name, "string"); return false; } private static bool ReadOptionalBoolField(Type type, object instance, string name) { object obj = type.GetField(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(instance); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static void LogRequestShapeError(Type type, string name, string expected) { if (!_loggedRequestShapeError) { _loggedRequestShapeError = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("[QuotaTokens] Company request type '" + type.FullName + "' has no readable " + expected + " field '" + name + "'. " + $"Quota token grants are being dropped; Y4NGZUpgrades expects token-grant protocol {1}. " + "Update Y4NGZUpgrades and Y4NGZCompany together.")); } } } private static int ParseQuota(string milestoneId) { if (string.IsNullOrWhiteSpace(milestoneId)) { return 0; } int num = milestoneId.LastIndexOf(':'); if (!int.TryParse((num >= 0) ? milestoneId.Substring(num + 1) : milestoneId, out var result)) { return 0; } return Math.Max(0, result); } } internal static class ContractEventAttribution { internal const string CrewFanOutMarker = ".crew."; internal static bool IsIndividuallyAttributed(string eventId, ulong creditedClientId) { if (string.IsNullOrEmpty(eventId)) { return false; } if (!eventId.EndsWith("." + creditedClientId, StringComparison.Ordinal)) { return false; } return eventId.IndexOf(".crew.", StringComparison.Ordinal) < 0; } } internal sealed class CumulativeCountTracker { private readonly Dictionary _deltaByTotal = new Dictionary(); private int _highWater; internal int Observe(int cumulativeTotal) { if (cumulativeTotal <= 0) { return 1; } if (cumulativeTotal > _highWater) { int num = cumulativeTotal - _highWater; _highWater = cumulativeTotal; _deltaByTotal[cumulativeTotal] = num; return num; } if (!_deltaByTotal.TryGetValue(cumulativeTotal, out var value)) { return 0; } return value; } } internal static class DawnLibCompat { internal const string ItemNamespace = "y4ngz_upgrades"; [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void RegisterNetworkPrefab(GameObject prefab) { DawnLib.RegisterNetworkPrefab(prefab); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void FixMixerGroups(GameObject prefab) { DawnLib.FixMixerGroups(prefab); } [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)] internal static void RegisterItem(string itemKey, Item item) { if (!((Object)(object)item == (Object)null) && !string.IsNullOrWhiteSpace(itemKey)) { DawnLib.DefineItem(NamespacedKey.From("y4ngz_upgrades", itemKey), item, (Action)delegate { }); } } } internal sealed class DeliveryAttributionLedger { internal const ulong UnattributedHandler = ulong.MaxValue; private readonly Dictionary _lastHandlerByKey = new Dictionary(); private readonly HashSet _preexistingInsideKeys = new HashSet(); internal int PreexistingInsideCount => _preexistingInsideKeys.Count; internal void Reset() { _lastHandlerByKey.Clear(); _preexistingInsideKeys.Clear(); } internal void MarkPreexistingInside(ulong key) { _preexistingInsideKeys.Add(key); } internal void RecordBoundaryCrossing(ulong key, ulong handlerClientId, bool nowInside) { if (nowInside) { _lastHandlerByKey[key] = handlerClientId; } else { _lastHandlerByKey.Remove(key); } } internal static bool SuppressOutwardTransition(bool nowInside, bool handlerKnown, bool handlerIsDead, bool handlerIsInsideShip) { if (!nowInside && handlerKnown) { return handlerIsDead || handlerIsInsideShip; } return false; } internal static bool ShouldPayBodyRetrieval(bool lastHandlerIsPayee, bool bodyIsInShip, bool bodyDeactivated, bool ownerResolved, bool payeeOwnsBody) { if (lastHandlerIsPayee && bodyIsInShip && !bodyDeactivated && ownerResolved) { return !payeeOwnsBody; } return false; } internal bool TryGetDeliveryHandler(ulong key, out ulong handlerClientId) { return _lastHandlerByKey.TryGetValue(key, out handlerClientId); } internal bool ShouldPayDelivery(ulong key, bool insideAtRoundEnd, ulong localClientId) { if (insideAtRoundEnd && !_preexistingInsideKeys.Contains(key) && _lastHandlerByKey.TryGetValue(key, out var value) && value != ulong.MaxValue) { return value == localClientId; } return false; } } internal static class EffectiveConfigInventory { private readonly struct InventoryRow { internal string FileName { get; } internal ConfigEntryBase Entry { get; } internal InventoryRow(string fileName, ConfigEntryBase entry) { FileName = fileName; Entry = entry; } } internal static string ReportPath => Path.Combine(Paths.ConfigPath, "Y4NGZUpgrades", "effective-config.tsv"); internal static void Write(IEnumerable configs) { if (configs == null) { return; } try { List list = new List(); foreach (ConfigFile config in configs) { if (config == null) { continue; } string fileName = Path.GetFileName(config.ConfigFilePath); foreach (KeyValuePair item in config) { list.Add(new InventoryRow(fileName, item.Value)); } } list.Sort(delegate(InventoryRow left, InventoryRow right) { int num2 = string.Compare(left.FileName, right.FileName, StringComparison.OrdinalIgnoreCase); if (num2 != 0) { return num2; } int num3 = string.Compare(left.Entry.Definition.Section, right.Entry.Definition.Section, StringComparison.OrdinalIgnoreCase); return (num3 == 0) ? string.Compare(left.Entry.Definition.Key, right.Entry.Definition.Key, StringComparison.OrdinalIgnoreCase) : num3; }); StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("file\tsection\tkey\ttype\tdefault\teffective\tdescription"); for (int num = 0; num < list.Count; num++) { InventoryRow inventoryRow = list[num]; ConfigEntryBase entry = inventoryRow.Entry; StringBuilder stringBuilder2 = stringBuilder.Append(Escape(inventoryRow.FileName)).Append('\t').Append(Escape(entry.Definition.Section)) .Append('\t') .Append(Escape(entry.Definition.Key)) .Append('\t') .Append(Escape(entry.SettingType?.FullName)) .Append('\t') .Append(Escape(Format(entry.DefaultValue))) .Append('\t') .Append(Escape(Format(entry.BoxedValue))) .Append('\t'); ConfigDescription description = entry.Description; stringBuilder2.Append(Escape((description != null) ? description.Description : null)).AppendLine(); } Directory.CreateDirectory(Path.GetDirectoryName(ReportPath)); File.WriteAllText(ReportPath, stringBuilder.ToString()); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Effective config inventory written to '{ReportPath}' ({list.Count} definitions)."); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("Failed writing effective config inventory: " + ex.Message)); } } } private static string Format(object value) { if (value == null) { return string.Empty; } if (!(value is IFormattable formattable)) { return value.ToString(); } return formattable.ToString(null, CultureInfo.InvariantCulture); } private static string Escape(string value) { return (value ?? string.Empty).Replace("\t", "\\t").Replace("\r", "\\r").Replace("\n", "\\n"); } } [Serializable] internal sealed class EmployeeStatisticsData { public int monstersKilled; public int stepsTaken; public int scrapValueDelivered; public int timesDied; public int bombsDefused; public float payloadDistancePushedMeters; public int surveyBeaconsPlaced; public int itemsIncinerated; public int whistleblowerDamageDealt; public int pestsTrapped; public int containmentWavesSurvived; public int drillsPlaced; public int breakersRestored; public float timeSpentOnCctvSeconds; public int devicesHacked; public int quotasCompleted; internal EmployeeStatisticsData Clone() { return new EmployeeStatisticsData { monstersKilled = monstersKilled, stepsTaken = stepsTaken, scrapValueDelivered = scrapValueDelivered, timesDied = timesDied, bombsDefused = bombsDefused, payloadDistancePushedMeters = payloadDistancePushedMeters, surveyBeaconsPlaced = surveyBeaconsPlaced, itemsIncinerated = itemsIncinerated, whistleblowerDamageDealt = whistleblowerDamageDealt, pestsTrapped = pestsTrapped, containmentWavesSurvived = containmentWavesSurvived, drillsPlaced = drillsPlaced, breakersRestored = breakersRestored, timeSpentOnCctvSeconds = timeSpentOnCctvSeconds, devicesHacked = devicesHacked, quotasCompleted = quotasCompleted }; } internal void Add(EmployeeStatisticsData other) { if (other != null) { monstersKilled = AddClamped(monstersKilled, other.monstersKilled); stepsTaken = AddClamped(stepsTaken, other.stepsTaken); scrapValueDelivered = AddClamped(scrapValueDelivered, other.scrapValueDelivered); timesDied = AddClamped(timesDied, other.timesDied); bombsDefused = AddClamped(bombsDefused, other.bombsDefused); payloadDistancePushedMeters = AddClamped(payloadDistancePushedMeters, other.payloadDistancePushedMeters); surveyBeaconsPlaced = AddClamped(surveyBeaconsPlaced, other.surveyBeaconsPlaced); itemsIncinerated = AddClamped(itemsIncinerated, other.itemsIncinerated); whistleblowerDamageDealt = AddClamped(whistleblowerDamageDealt, other.whistleblowerDamageDealt); pestsTrapped = AddClamped(pestsTrapped, other.pestsTrapped); containmentWavesSurvived = AddClamped(containmentWavesSurvived, other.containmentWavesSurvived); drillsPlaced = AddClamped(drillsPlaced, other.drillsPlaced); breakersRestored = AddClamped(breakersRestored, other.breakersRestored); timeSpentOnCctvSeconds = AddClamped(timeSpentOnCctvSeconds, other.timeSpentOnCctvSeconds); devicesHacked = AddClamped(devicesHacked, other.devicesHacked); quotasCompleted = AddClamped(quotasCompleted, other.quotasCompleted); } } private static int AddClamped(int left, int right) { long val = (long)Math.Max(0, left) + (long)Math.Max(0, right); return (int)Math.Min(2147483647L, val); } private static float AddClamped(float left, float right) { if (float.IsNaN(left) || float.IsInfinity(left)) { left = 0f; } if (float.IsNaN(right) || float.IsInfinity(right)) { right = 0f; } return Mathf.Clamp(Mathf.Max(0f, left) + Mathf.Max(0f, right), 0f, 1E+09f); } } internal static class EmployeeStatistics { internal readonly struct ReportNoteCandidate { internal readonly int Priority; internal readonly string Text; internal ReportNoteCandidate(int priority, string text) { Priority = priority; Text = text; } } private sealed class RoundState { internal readonly EmployeeStatisticsData Data = new EmployeeStatisticsData(); internal readonly Dictionary LastItemHolderByKey = new Dictionary(); internal readonly Dictionary LastEnemyHitByLocalPlayer = new Dictionary(); internal readonly HashSet KilledEnemies = new HashSet(); internal readonly HashSet UniqueEventKeys = new HashSet(StringComparer.Ordinal); internal Vector3 LastPlayerPosition; internal bool PlayerPositionValid; internal float StepDistance; internal object PayloadCart; internal Vector3 LastPayloadPosition; internal bool PayloadPositionValid; internal readonly CumulativeCountTracker PestCaptureCounts = new CumulativeCountTracker(); } private const string CompanyAssemblyName = "Y4NGZCompany"; private const string CctvAssemblyName = "LethalCCTV"; internal const float StepMeters = 0.76f; private const float MinimumTrackedMovement = 0.02f; private const float MaximumTrackedMovement = 8f; private static readonly string SaveDir = Path.Combine(Paths.ConfigPath, "Y4NGZEmployeeFile"); private static EmployeeStatisticsData _lifetime; private static EmployeeStatisticsData _lastRound; private static RoundState _round = new RoundState(); private static readonly RoundLatch _latch = new RoundLatch(); private static string _key; private static int _lastTimesFulfilledQuota = -1; private static bool _cctvReflectionResolved; private static PropertyInfo _cctvFocusedProperty; private static bool _payloadReflectionResolved; private static PropertyInfo _localPayloadCartProperty; private static PropertyInfo _payloadAttachedToLocalProperty; private static readonly string[] SpelledNumbers = new string[11] { "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten" }; internal static EmployeeStatisticsData CurrentSnapshot { get { EnsureLoaded(); EmployeeStatisticsData employeeStatisticsData = _lifetime?.Clone() ?? new EmployeeStatisticsData(); if (_latch.Active && !_latch.Finalized) { employeeStatisticsData.Add(_round.Data); } return employeeStatisticsData; } } internal static EmployeeStatisticsData LastRoundSnapshot => _lastRound?.Clone(); internal static void SwitchToCurrentSave() { if (!SaveKey.TryGetCurrent(out var key)) { _key = null; _lifetime = new EmployeeStatisticsData(); ResetRuntimeState(); } else if (_lifetime == null || !string.Equals(_key, key, StringComparison.OrdinalIgnoreCase)) { _key = key; _lifetime = Load(key); _lastRound = null; _round = new RoundState(); _latch.Abandon(); _lastTimesFulfilledQuota = CurrentQuotaCount(); ResetPositionTracking(); } } internal static void BeginRound() { SwitchToCurrentSave(); _round = new RoundState(); _latch.Begin(); _lastRound = null; _lastTimesFulfilledQuota = CurrentQuotaCount(); ResetPositionTracking(); } internal static void AbandonUnfinalizedRound() { if (!_latch.Finalized && _latch.Active) { _latch.Abandon(); _round = new RoundState(); ResetPositionTracking(); } } internal static void ResetCurrentSave() { if (!SaveKey.TryGetCurrentExistingOrSlot(out var key)) { _key = null; _lifetime = new EmployeeStatisticsData(); ResetRuntimeState(); } else { DeleteForKey(key); } } internal static bool DeleteForKey(string key) { bool result = false; try { string path = GetPath(key); if (File.Exists(path)) { File.Delete(path); result = true; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[EmployeeFile] Failed resetting statistics: " + ex.Message)); } } if (string.Equals(_key, key, StringComparison.OrdinalIgnoreCase)) { _key = null; _lifetime = new EmployeeStatisticsData(); } ResetRuntimeState(); return result; } internal static void RecordItemGrabbed(GrabbableObject item) { if (_latch.Active && !_latch.Finalized && !((Object)(object)item == (Object)null)) { PlayerControllerB playerHeldBy = item.playerHeldBy; if ((Object)(object)playerHeldBy != (Object)null) { _round.LastItemHolderByKey[NetworkKey((Component)(object)item)] = playerHeldBy.actualClientId; } } } internal static void RecordEnemyHit(EnemyAI enemy, PlayerControllerB playerWhoHit) { if (_latch.Active && !_latch.Finalized && !((Object)(object)enemy == (Object)null) && IsLocalPlayer(playerWhoHit)) { _round.LastEnemyHitByLocalPlayer[NetworkKey((Component)(object)enemy)] = Time.time; } } internal static void RecordEnemyKilled(EnemyAI enemy) { if (_latch.Active && !_latch.Finalized && !((Object)(object)enemy == (Object)null)) { ulong num = NetworkKey((Component)(object)enemy); if (_round.KilledEnemies.Add(num) && _round.LastEnemyHitByLocalPlayer.TryGetValue(num, out var value) && !(Time.time - value > Mathf.Max(1f, Plugin.ProgressionConfig.KillAttributionWindowSeconds.Value))) { _round.Data.monstersKilled = AddOne(_round.Data.monstersKilled); } } } internal static void RecordDeath() { AddRoundOrLifetime(delegate(EmployeeStatisticsData data) { data.timesDied = AddOne(data.timesDied); }); } internal static void RecordBombDefused(string eventId) { if (TryAddRoundKey("bomb." + (eventId ?? string.Empty))) { _round.Data.bombsDefused = AddOne(_round.Data.bombsDefused); } } internal static void RecordSurveyBeaconPlaced(string eventId) { if (TryAddRoundKey("survey." + (eventId ?? string.Empty))) { _round.Data.surveyBeaconsPlaced = AddOne(_round.Data.surveyBeaconsPlaced); } } internal static void RecordItemIncinerated(int playerId, ulong itemNetworkObjectId) { PlayerControllerB val = LocalPlayer(); if (!((Object)(object)val == (Object)null) && (int)val.playerClientId == playerId && TryAddRoundKey("incinerator.item." + itemNetworkObjectId)) { _round.Data.itemsIncinerated = AddOne(_round.Data.itemsIncinerated); } } internal static void RecordWhistleblowerDamage(EnemyAI enemy, PlayerControllerB playerWhoHit, int damage) { if (!((Object)(object)enemy == (Object)null) && damage > 0 && IsLocalPlayer(playerWhoHit) && _latch.Active && !_latch.Finalized) { _round.Data.whistleblowerDamageDealt = AddClamped(_round.Data.whistleblowerDamageDealt, damage); } } internal static void ObservePestsTrapped(string eventId, ulong creditedClientId, int capturedTotal) { if (_latch.Active && !_latch.Finalized) { int num = _round.PestCaptureCounts.Observe(capturedTotal); PlayerControllerB val = LocalPlayer(); if (num > 0 && !((Object)(object)val == (Object)null) && val.actualClientId == creditedClientId && TryAddRoundKey("pest.trapped." + (eventId ?? string.Empty))) { _round.Data.pestsTrapped = AddClamped(_round.Data.pestsTrapped, num); } } } internal static void RecordContainmentWaveSurvived(string eventId) { if (TryAddRoundKey("containment.wave." + (eventId ?? string.Empty))) { _round.Data.containmentWavesSurvived = AddOne(_round.Data.containmentWavesSurvived); } } internal static void RecordDrillPlaced(string eventId) { if (TryAddRoundKey("shadowraid.drill." + (eventId ?? string.Empty))) { _round.Data.drillsPlaced = AddOne(_round.Data.drillsPlaced); } } internal static void RecordBreakerRestored(int restoredCount, ulong actorClientId) { PlayerControllerB val = LocalPlayer(); if (!((Object)(object)val == (Object)null) && val.actualClientId == actorClientId && TryAddRoundKey("blackout.breaker.count." + Mathf.Max(1, restoredCount))) { _round.Data.breakersRestored = AddOne(_round.Data.breakersRestored); } } internal static void RecordSingleBreakerRestored(string eventId) { if (TryAddRoundKey("blackout.breaker.single." + (eventId ?? string.Empty))) { _round.Data.breakersRestored = AddOne(_round.Data.breakersRestored); } } internal static void RecordDeviceHacked(Object target) { RecordDeviceHacked((target != (Object)null) ? (((object)target).GetType().FullName + "." + target.GetInstanceID()) : ("unknown." + Time.frameCount)); } internal static void RecordDeviceHacked(string targetKey) { if (TryAddRoundKey("hack." + (targetKey ?? string.Empty))) { _round.Data.devicesHacked = AddOne(_round.Data.devicesHacked); } } internal static void UpdateRuntime(PlayerControllerB localPlayer, float deltaTime) { if (_lifetime == null) { SwitchToCurrentSave(); } UpdateQuotaCompletion(); if (_latch.Active && !_latch.Finalized && IsLocalPlayer(localPlayer)) { float num = Mathf.Clamp(deltaTime, 0f, 0.25f); UpdateSteps(localPlayer); if (IsCctvFocused()) { _round.Data.timeSpentOnCctvSeconds += num; } UpdatePayloadDistance(); } } internal static EmployeeStatisticsData FinalizeRound(int scrapCollected) { EnsureLoaded(); if (!_latch.TryBeginFinalize(out var recoveredMissedStart)) { return _lastRound?.Clone() ?? new EmployeeStatisticsData(); } if (recoveredMissedStart) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[EmployeeStatistics] FinalizeRound ran without a round start " + $"(sequence={_latch.Sequence}, scrapCollected={scrapCollected}). " + "Nothing was recorded this round — the RoundLifecycle.RoundStarted hook did not fire for this peer.")); } } _round.Data.scrapValueDelivered = ComputeLocalDeliveredScrapValue(); _lastRound = _round.Data.Clone(); if (_lifetime == null) { _lifetime = new EmployeeStatisticsData(); } _lifetime.Add(_lastRound); _latch.CompleteFinalize(); Save(); return _lastRound.Clone(); } internal static IReadOnlyList BuildReportNoteCandidates() { List list = new List(); EmployeeStatisticsData lastRound = _lastRound; if (lastRound == null) { return list; } if (lastRound.bombsDefused > 0) { list.Add(new ReportNoteCandidate(64, "* Defused " + FormatCount(lastRound.bombsDefused, "live bomb") + " during the operation.")); } if (lastRound.surveyBeaconsPlaced > 0) { list.Add(new ReportNoteCandidate(60, "* Planted " + FormatCount(lastRound.surveyBeaconsPlaced, "survey beacon") + " across the site.")); } if (lastRound.devicesHacked > 0) { list.Add(new ReportNoteCandidate(56, "* Hacked " + FormatCount(lastRound.devicesHacked, "secured device") + " during the operation.")); } if (lastRound.payloadDistancePushedMeters >= 5f) { list.Add(new ReportNoteCandidate(52, $"* Pushed the payload {lastRound.payloadDistancePushedMeters:0}m across the site.")); } if (lastRound.timeSpentOnCctvSeconds >= 20f) { list.Add(new ReportNoteCandidate(48, "* Monitored ship cameras for " + FormatDurationCompact(lastRound.timeSpentOnCctvSeconds) + ".")); } if (lastRound.quotasCompleted > 0) { list.Add(new ReportNoteCandidate(40, "* Closed out the profit quota during this operation.")); } return list; } private static string FormatCount(int count, string singularNoun) { int num = Mathf.Max(0, count); string text = ((num < SpelledNumbers.Length) ? SpelledNumbers[num] : num.ToString("N0")); if (num != 1) { return text + " " + singularNoun + "s"; } return text + " " + singularNoun; } private static string FormatDurationCompact(float seconds) { int num = Mathf.Max(0, Mathf.FloorToInt(seconds)); int num2 = num / 60; int num3 = num % 60; if (num2 <= 0) { return $"{num3}s"; } return $"{num2}m {num3}s"; } internal static string FormatDuration(float seconds) { int num = Mathf.Max(0, Mathf.FloorToInt(seconds)); int num2 = num / 3600; int num3 = num % 3600 / 60; int num4 = num % 60; if (num2 <= 0) { return $"{num3:00}:{num4:00}"; } return $"{num2}:{num3:00}:{num4:00}"; } private static void EnsureLoaded() { if (_lifetime == null) { SwitchToCurrentSave(); } } private static EmployeeStatisticsData Load(string key) { try { string path = GetPath(key); if (File.Exists(path)) { return JsonUtility.FromJson(File.ReadAllText(path)) ?? new EmployeeStatisticsData(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[EmployeeFile] Failed reading statistics: " + ex.Message)); } } return new EmployeeStatisticsData(); } private static void Save() { if (_lifetime == null || string.IsNullOrWhiteSpace(_key)) { return; } try { Directory.CreateDirectory(SaveDir); File.WriteAllText(GetPath(_key), JsonUtility.ToJson((object)_lifetime, true)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[EmployeeFile] Failed writing statistics: " + ex.Message)); } } } private static string GetPath(string key) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); char[] array = (key ?? "employee").ToCharArray(); for (int i = 0; i < array.Length; i++) { if (Array.IndexOf(invalidFileNameChars, array[i]) >= 0) { array[i] = '_'; } } return Path.Combine(SaveDir, new string(array) + ".json"); } private static void UpdateSteps(PlayerControllerB player) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !player.isPlayerControlled || player.isPlayerDead) { _round.PlayerPositionValid = false; return; } Vector3 position = ((Component)player).transform.position; if (!_round.PlayerPositionValid) { _round.LastPlayerPosition = position; _round.PlayerPositionValid = true; return; } float num = Vector3.Distance(_round.LastPlayerPosition, position); _round.LastPlayerPosition = position; if (!(num < 0.02f) && !(num > 8f)) { _round.StepDistance += num; _round.Data.stepsTaken = Mathf.Clamp(Mathf.FloorToInt(_round.StepDistance / 0.76f), 0, int.MaxValue); } } private static void UpdatePayloadDistance() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) object localPayloadCart = GetLocalPayloadCart(); Component val = (Component)((localPayloadCart is Component) ? localPayloadCart : null); if ((Object)(object)val == (Object)null || !IsPayloadAttachedToLocal(localPayloadCart)) { _round.PayloadCart = null; _round.PayloadPositionValid = false; return; } Vector3 position = val.transform.position; if (_round.PayloadCart != localPayloadCart || !_round.PayloadPositionValid) { _round.PayloadCart = localPayloadCart; _round.LastPayloadPosition = position; _round.PayloadPositionValid = true; return; } float num = Vector3.Distance(_round.LastPayloadPosition, position); _round.LastPayloadPosition = position; if (!(num < 0.005f) && !(num > 8f)) { _round.Data.payloadDistancePushedMeters = Mathf.Clamp(_round.Data.payloadDistancePushedMeters + num, 0f, 1E+09f); } } private static bool IsCctvFocused() { if (!_cctvReflectionResolved) { _cctvReflectionResolved = true; _cctvFocusedProperty = ResolveCompanyType("Y4NGZCompany.ShipSystems.Surveillance.MonitorFocus")?.GetProperty("IsFocused", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } try { bool flag = default(bool); int num; if (_cctvFocusedProperty != null) { object value = _cctvFocusedProperty.GetValue(null); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static object GetLocalPayloadCart() { ResolvePayloadReflection(); try { return _localPayloadCartProperty?.GetValue(null); } catch { return null; } } private static bool IsPayloadAttachedToLocal(object cart) { ResolvePayloadReflection(); try { bool flag = default(bool); int num; if (cart != null && _payloadAttachedToLocalProperty != null) { object value = _payloadAttachedToLocalProperty.GetValue(cart); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void ResolvePayloadReflection() { if (!_payloadReflectionResolved) { _payloadReflectionResolved = true; Type type = ResolveCompanyType("Y4NGZCompany.Contracts.Payload.PayloadCartController"); _localPayloadCartProperty = type?.GetProperty("LocalAttachedCart", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _payloadAttachedToLocalProperty = type?.GetProperty("IsAttachedToLocalPlayer", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } private static Type ResolveCompanyType(string fullName) { if (string.IsNullOrEmpty(fullName)) { return null; } return Type.GetType(fullName + ", Y4NGZCompany", throwOnError: false) ?? Type.GetType(fullName + ", LethalCCTV", throwOnError: false); } private static int ComputeLocalDeliveredScrapValue() { PlayerControllerB val = LocalPlayer(); if ((Object)(object)val == (Object)null) { return 0; } long num = 0L; HashSet hashSet = new HashSet(); GrabbableObject[] array = Object.FindObjectsOfType(); foreach (GrabbableObject val2 in array) { if (!((Object)(object)val2?.itemProperties == (Object)null) && val2.itemProperties.isScrap && (val2.isInShipRoom || val2.isInElevator)) { ulong num2 = NetworkKey((Component)(object)val2); if (hashSet.Add(num2) && _round.LastItemHolderByKey.TryGetValue(num2, out var value) && value == val.actualClientId) { num += Mathf.Max(0, val2.scrapValue); } } } return (int)Math.Min(2147483647L, num); } private static void UpdateQuotaCompletion() { int num = CurrentQuotaCount(); if (num < 0) { return; } if (_lastTimesFulfilledQuota < 0 || num < _lastTimesFulfilledQuota) { _lastTimesFulfilledQuota = num; } else { if (num == _lastTimesFulfilledQuota) { return; } int right = num - _lastTimesFulfilledQuota; _lastTimesFulfilledQuota = num; if (_latch.Active && !_latch.Finalized) { _round.Data.quotasCompleted = AddClamped(_round.Data.quotasCompleted, right); return; } if (_lifetime == null) { _lifetime = new EmployeeStatisticsData(); } _lifetime.quotasCompleted = AddClamped(_lifetime.quotasCompleted, right); Save(); } } private static int CurrentQuotaCount() { try { return ((Object)(object)TimeOfDay.Instance != (Object)null) ? Mathf.Max(0, TimeOfDay.Instance.timesFulfilledQuota) : (-1); } catch { return -1; } } private static bool TryAddRoundKey(string key) { if (_latch.Active && !_latch.Finalized) { return _round.UniqueEventKeys.Add(key ?? string.Empty); } return false; } private static void AddRoundOrLifetime(Action mutation) { if (mutation != null) { EnsureLoaded(); if (_latch.Active && !_latch.Finalized) { mutation(_round.Data); return; } mutation(_lifetime); Save(); } } private static PlayerControllerB LocalPlayer() { object obj = GameNetworkManager.Instance?.localPlayerController; if (obj == null) { StartOfRound instance = StartOfRound.Instance; if (instance == null) { return null; } obj = instance.localPlayerController; } return (PlayerControllerB)obj; } private static bool IsLocalPlayer(PlayerControllerB player) { PlayerControllerB val = LocalPlayer(); if ((Object)(object)player != (Object)null && (Object)(object)val != (Object)null) { return (Object)(object)player == (Object)(object)val; } return false; } private static ulong NetworkKey(Component component) { return NetworkObjectKey.For(component); } private static int AddOne(int value) { if (value < int.MaxValue) { return Mathf.Max(0, value) + 1; } return int.MaxValue; } private static int AddClamped(int left, int right) { return (int)Math.Min(2147483647L, (long)Mathf.Max(0, left) + (long)Mathf.Max(0, right)); } private static void ResetPositionTracking() { _round.PlayerPositionValid = false; _round.PayloadPositionValid = false; _round.PayloadCart = null; } private static void ResetRuntimeState() { _lastRound = null; _round = new RoundState(); _latch.Abandon(); _lastTimesFulfilledQuota = CurrentQuotaCount(); ResetPositionTracking(); } } public readonly struct ExternalTokenGrantRequest { public readonly int AmountPerPlayer; public readonly string Source; public readonly string MilestoneId; public readonly string ActionId; public ExternalTokenGrantRequest(int amountPerPlayer, string source, string milestoneId, string actionId) { AmountPerPlayer = amountPerPlayer; Source = source ?? string.Empty; MilestoneId = milestoneId ?? string.Empty; ActionId = actionId ?? string.Empty; } } public static class ExternalTokenGrantApi { public const int ProtocolVersion = 1; public static bool IsCompanyProviderRegistered => CompanyQuotaTokenIntegration.IsCompanyProviderRegistered; public static bool TryGrantConnectedPlayers(ExternalTokenGrantRequest request) { return CompanyQuotaTokenIntegration.TryGrantConnectedPlayers(request); } } public static class HeldItemStowApi { public const int ProtocolVersion = 1; public static bool BeginStow(PlayerControllerB player, string reason) { return HeldItemStowService.Begin(player, reason, 15f, disableItemActions: false, force: true).IsActive; } public static void EndStow(PlayerControllerB player, string reason) { HeldItemStowService.End(player, reason); } public static bool IsStowed(PlayerControllerB player) { return HeldItemStowService.IsStowed(player); } public static long BeginStowToken(PlayerControllerB player, string reason, float safetyTimeoutSeconds, bool disableItemActions, bool force) { return HeldItemStowService.Begin(player, reason, safetyTimeoutSeconds, disableItemActions, force).Token; } public static bool IsStowTokenLive(PlayerControllerB player, long token) { return HeldItemStowService.IsTokenLive(player, token); } public static void ReleaseStowToken(PlayerControllerB player, long token) { HeldItemStowService.Release(player, token); } } internal enum HostSaveScope { UseLocalSave, UseHostKey, Pending } internal static class HostSaveIdentity { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnRequestIdentityServerRpc; public static HandleNamedMessageDelegate <1>__OnIdentityClientRpc; public static Action <2>__Save; public static Action <3>__Save; public static Action <4>__Save; public static Action <5>__Reload; public static Action <6>__SwitchToCurrentSave; public static Action <7>__RaiseStoresRepointed; } private const string MSG_REQUEST_SERVER = "Y4NGZHostSave.RequestServerRpc"; private const string MSG_IDENTITY_CLIENT = "Y4NGZHostSave.IdentityClientRpc"; internal const string HostKeyPrefix = "HOST#"; private const float RequestRetrySeconds = 1.5f; private const float NoReplyGraceSeconds = 12f; private static bool handlersRegistered; private static NetworkManager registeredNetworkManager; private static string hostIdentity; private static string hostSaveKey; private static bool hostSpeaksProtocol; private static float nextRequestAt; private static float graceExpiresAt; private static bool fallbackLogged; private static bool resolving; private static bool mutatingStores; internal static string CurrentHostSaveKey => hostSaveKey; internal static HostSaveScope Resolve(out string key) { key = null; if (resolving || mutatingStores) { if (hostSaveKey == null) { return HostSaveScope.UseLocalSave; } key = hostSaveKey; return HostSaveScope.UseHostKey; } if (!IsJoinedRemoteClient()) { if (hostSaveKey != null || hostIdentity != null) { ClearIdentity("no longer joined to a remote host"); } return HostSaveScope.UseLocalSave; } if (hostSaveKey != null) { key = hostSaveKey; return HostSaveScope.UseHostKey; } if (graceExpiresAt <= 0f) { graceExpiresAt = Time.unscaledTime + 12f; } RequestIdentityIfDue(); if (!hostSpeaksProtocol && Time.unscaledTime >= graceExpiresAt) { if (!fallbackLogged) { fallbackLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[HostSaveIdentity] Host never sent a save identity; falling back to this client's own save scope (host is probably running an older build)."); } } return HostSaveScope.UseLocalSave; } return HostSaveScope.Pending; } internal static void RegisterNetworkHandlers() { //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || (handlersRegistered && registeredNetworkManager == singleton)) { return; } if (handlersRegistered) { UnregisterNetworkHandlers(); } try { if (singleton.IsServer) { object obj = <>O.<0>__OnRequestIdentityServerRpc; if (obj == null) { HandleNamedMessageDelegate val2 = OnRequestIdentityServerRpc; <>O.<0>__OnRequestIdentityServerRpc = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZHostSave.RequestServerRpc", (HandleNamedMessageDelegate)obj); } else { object obj2 = <>O.<1>__OnIdentityClientRpc; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnIdentityClientRpc; <>O.<1>__OnIdentityClientRpc = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZHostSave.IdentityClientRpc", (HandleNamedMessageDelegate)obj2); } handlersRegistered = true; registeredNetworkManager = singleton; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[HostSaveIdentity] network handlers registered."); } } catch (Exception arg) { handlersRegistered = false; registeredNetworkManager = null; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"[HostSaveIdentity] handler registration failed: {arg}"); } } } internal static void RequestIdentityFromHost() { nextRequestAt = 0f; RequestIdentityIfDue(); } internal static void Clear() { ClearIdentity("disconnected"); UnregisterNetworkHandlers(); } internal static void Tick() { Resolve(out var _); } private static bool IsJoinedRemoteClient() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsListening && singleton.IsClient) { return !singleton.IsServer; } return false; } private unsafe static void RequestIdentityIfDue() { //IL_0057: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime < nextRequestAt) { return; } nextRequestAt = Time.unscaledTime + 1.5f; NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val == null || singleton.IsServer || !singleton.IsConnectedClient) { return; } try { FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(1, (Allocator)2, -1); try { val.SendNamedMessage("Y4NGZHostSave.RequestServerRpc", 0uL, val2, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HostSaveIdentity] identity request failed: " + ex.Message)); } } } private unsafe static void OnRequestIdentityServerRpc(ulong senderId, FastBufferReader reader) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { string identity; string text = (TryGetLocalHostIdentity(out identity) ? identity : string.Empty); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(128, (Allocator)2, -1); try { FixedString64Bytes val2 = new FixedString64Bytes(text); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZHostSave.IdentityClientRpc", senderId, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[HostSaveIdentity] OnRequestIdentityServerRpc failed: {arg}"); } } } private unsafe static void OnIdentityClientRpc(ulong senderId, FastBufferReader reader) { //IL_0022: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderId != 0L) { return; } try { FixedString64Bytes val = default(FixedString64Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); hostSpeaksProtocol = true; string text = ((object)(*(FixedString64Bytes*)(&val))/*cast due to .constrained prefix*/).ToString()?.Trim(); if (string.IsNullOrEmpty(text)) { return; } if (!Guid.TryParseExact(text, "N", out var _)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HostSaveIdentity] Ignoring malformed host identity '" + text + "'.")); } } else { ApplyIdentity(text); } } catch (Exception arg) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"[HostSaveIdentity] OnIdentityClientRpc failed: {arg}"); } } } private static void ApplyIdentity(string identity) { if (string.Equals(hostIdentity, identity, StringComparison.OrdinalIgnoreCase)) { return; } mutatingStores = true; try { if (hostIdentity != null) { FlushLiveStores(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[HostSaveIdentity] joined-host identity changed " + hostIdentity + " -> " + identity + "; swapping store scope (previous host state retained on disk).")); } } hostIdentity = identity; hostSaveKey = "HOST#" + identity; fallbackLogged = false; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[HostSaveIdentity] joined-host identity=" + identity + ", store=" + hostSaveKey)); } RepointLiveStores(); } finally { mutatingStores = false; } } private static void ClearIdentity(string reason) { mutatingStores = true; try { if (hostIdentity != null) { FlushLiveStores(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[HostSaveIdentity] releasing joined-host scope " + hostSaveKey + " (" + reason + ").")); } } hostIdentity = null; hostSaveKey = null; hostSpeaksProtocol = false; nextRequestAt = 0f; graceExpiresAt = 0f; fallbackLogged = false; RepointLiveStores(); } finally { mutatingStores = false; } } private static void FlushLiveStores() { TryRun(ProgressionManager.Save, "progression flush"); TryRun(Y4NGZUpgradeManager.Save, "upgrade flush"); TryRun(PlayerLevelStore.Save, "player-level flush"); } private static void RepointLiveStores() { TryRun(delegate { ProgressionManager.SwitchToCurrentSave(); }, "progression re-point"); TryRun(delegate { Y4NGZUpgradeManager.SwitchToCurrentSave(); }, "upgrade re-point"); TryRun(PlayerLevelStore.Reload, "player-level re-point"); TryRun(EmployeeStatistics.SwitchToCurrentSave, "employee-file re-point"); TryRun(SaveIdentityApi.RaiseStoresRepointed, "cross-plugin store re-point"); } private static void TryRun(Action action, string label) { try { action(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HostSaveIdentity] " + label + " failed: " + ex.Message)); } } } private static bool TryGetLocalHostIdentity(out string identity) { identity = null; resolving = true; try { if (!SaveKey.TryGetCurrentOrSlot(out var key) || string.IsNullOrWhiteSpace(key)) { return false; } int num = key.LastIndexOf('#'); if (num <= 0 || num + 1 >= key.Length) { return false; } string text = key.Substring(num + 1); if (!Guid.TryParseExact(text, "N", out var _)) { return false; } identity = text; return true; } finally { resolving = false; } } private static void UnregisterNetworkHandlers() { if (!handlersRegistered) { return; } NetworkManager val = registeredNetworkManager ?? NetworkManager.Singleton; CustomMessagingManager val2 = ((val != null) ? val.CustomMessagingManager : null); if (val2 != null) { try { if (val.IsServer) { val2.UnregisterNamedMessageHandler("Y4NGZHostSave.RequestServerRpc"); } else { val2.UnregisterNamedMessageHandler("Y4NGZHostSave.IdentityClientRpc"); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HostSaveIdentity] handler unregister failed: " + ex.Message)); } } } handlersRegistered = false; registeredNetworkManager = null; } } [HarmonyPatch] internal static class HostSaveIdentityPatch { [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void AfterConnectClientToPlayerObject() { try { HostSaveIdentity.RegisterNetworkHandlers(); HostSaveIdentity.RequestIdentityFromHost(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[HostSaveIdentity] AfterConnectClientToPlayerObject: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void AfterResetShip() { try { HostSaveIdentity.RegisterNetworkHandlers(); HostSaveIdentity.RequestIdentityFromHost(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[HostSaveIdentity] AfterResetShip: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "Update")] [HarmonyPostfix] private static void AfterStartOfRoundUpdate() { HostSaveIdentity.Tick(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void AfterDisconnect() { try { HostSaveIdentity.Clear(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[HostSaveIdentity] AfterDisconnect: {arg}"); } } finally { SaveKey.ClearPendingIdentities(); } } } public static class KeybindReservationApi { public const int ProtocolVersion = 1; public static string[] GetReservedKeyNames() { return (string[])(Plugin.ReservedKeyNames ?? new string[0]).Clone(); } } internal static class LobbyTokenCommandNetwork { [HarmonyPatch(typeof(StartOfRound), "Awake")] private static class StartOfRoundAwakePatch { private static void Postfix() { EnsureRegistered(); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] private static class DisconnectPatch { private static void Prefix() { Shutdown(); } } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetTokensMessage; } private const string SetTokensMessage = "Y4NGZUpgrades.SetLobbyTokens.v1"; private static NetworkManager _registeredNetworkManager; internal unsafe static bool TrySetLobbyTokens(int amount, out int connectedEmployees, out string error) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) connectedEmployees = 0; if (amount < 0 || amount > 999999) { error = $"Amount must be from 0 to {999999}."; return false; } EnsureRegistered(); NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null) { error = "Lobby networking is not ready."; return false; } if (!singleton.IsServer) { error = "Only the host can set lobby Tokens."; return false; } if (!ProgressionApi.TrySetTokensForTesting(amount)) { error = "The host token balance could not be set for the current save."; return false; } try { FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref amount, default(ForPrimitives)); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { connectedEmployees++; if (connectedClientsId != singleton.LocalClientId) { val.SendNamedMessage("Y4NGZUpgrades.SetLobbyTokens.v1", connectedClientsId, val2, (NetworkDelivery)3); } } } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[SetTokens] Host set {connectedEmployees} connected employee balance(s) to {amount} Tokens."); } error = null; return true; } catch (Exception ex) { error = "Host Tokens were set, but the lobby broadcast failed: " + ex.Message; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[SetTokens] " + error)); } return false; } } private static void EnsureRegistered() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || (Object)(object)_registeredNetworkManager == (Object)(object)singleton) { return; } Shutdown(); try { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnSetTokensMessage; if (obj == null) { HandleNamedMessageDelegate val = OnSetTokensMessage; <>O.<0>__OnSetTokensMessage = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZUpgrades.SetLobbyTokens.v1", (HandleNamedMessageDelegate)obj); _registeredNetworkManager = singleton; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SetTokens] Network handler registration failed: " + ex.Message)); } } } private static void Shutdown() { NetworkManager registeredNetworkManager = _registeredNetworkManager; if (((registeredNetworkManager != null) ? registeredNetworkManager.CustomMessagingManager : null) != null) { try { _registeredNetworkManager.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZUpgrades.SetLobbyTokens.v1"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SetTokens] Network handler unregister failed: " + ex.Message)); } } } _registeredNetworkManager = null; } private static void OnSetTokensMessage(ulong senderClientId, FastBufferReader reader) { //IL_0018: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || senderClientId != 0L) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); if (num >= 0 && num <= 999999 && !ProgressionApi.TrySetTokensForTesting(num)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[SetTokens] Client could not set Tokens for the current save."); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[SetTokens] Malformed host message: " + ex.Message)); } } } } internal enum LobbyTokenCommandKind { NotCommand, Usage, InvalidAmount, Set } internal readonly struct LobbyTokenCommand { internal LobbyTokenCommandKind Kind { get; } internal int Amount { get; } internal LobbyTokenCommand(LobbyTokenCommandKind kind, int amount = 0) { Kind = kind; Amount = amount; } } internal static class LobbyTokenCommandParser { internal const int MaximumTokenBalance = 999999; internal static LobbyTokenCommand Parse(string input) { string text = (input ?? string.Empty).Trim(); if (text.Length == 0) { return new LobbyTokenCommand(LobbyTokenCommandKind.NotCommand); } string[] array = text.Split(new char[4] { ' ', '\t', '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0 || !string.Equals(array[0], "settokens", StringComparison.OrdinalIgnoreCase)) { return new LobbyTokenCommand(LobbyTokenCommandKind.NotCommand); } if (array.Length != 2) { return new LobbyTokenCommand(LobbyTokenCommandKind.Usage); } if (!int.TryParse(array[1], out var result) || result < 0 || result > 999999) { return new LobbyTokenCommand(LobbyTokenCommandKind.InvalidAmount); } return new LobbyTokenCommand(LobbyTokenCommandKind.Set, result); } } internal static class NetworkObjectKey { internal const ulong LocalInstanceKeyFlag = 9223372036854775808uL; internal static ulong For(Component component) { if ((Object)(object)component == (Object)null) { return 0uL; } try { NetworkBehaviour val = (NetworkBehaviour)(object)((component is NetworkBehaviour) ? component : null); if (val != null && (Object)(object)val.NetworkObject != (Object)null && val.NetworkObject.IsSpawned && val.NetworkObjectId != 0L) { return val.NetworkObjectId; } } catch { } return (ulong)(long.MinValue | (uint)((Object)component).GetInstanceID()); } internal static bool IsLocalInstanceKey(ulong key) { return (key & 0x8000000000000000uL) != 0; } } internal static class OptionalCctvBridge { private const string CctvApiTypeName = "Y4NGZCompany.Facility.Security.CctvSupportApi, LethalCCTV"; private const string MainframeTypeName = "Y4NGZCompany.Facility.Mainframe.MainframeSupport, LethalCCTV"; private const string CameraRegistryTypeName = "Y4NGZCompany.Facility.Security.CctvSecurityCameraRegistry, LethalCCTV"; private const string ObjectiveApiTypeName = "Y4NGZCompany.Contracts._Shared.MoonContractObjectiveMarkerApi, Y4NGZCompany"; private static Type CctvApi { get { if (!OptionalPluginCapabilities.LethalCctv) { return null; } return Type.GetType("Y4NGZCompany.Facility.Security.CctvSupportApi, LethalCCTV", throwOnError: false); } } private static Type MainframeType { get { if (!OptionalPluginCapabilities.LethalCctv) { return null; } return Type.GetType("Y4NGZCompany.Facility.Mainframe.MainframeSupport, LethalCCTV", throwOnError: false); } } internal static bool IsAlarmActive => ReadStaticBool(CctvApi, "IsAlarmActive"); internal static bool IsTimedSecurityAlarmActive => ReadStaticBool(CctvApi, "IsTimedSecurityAlarmActive"); internal static bool IsLockdownActive => ReadStaticBool(CctvApi, "IsLockdownActive"); internal static bool IsMainframeHacked => ReadStaticBool(CctvApi, "IsMainframeHacked"); internal static bool InstallDetectionTimeMultiplierProvider(Func provider) { Type cctvApi = CctvApi; if (cctvApi == null) { return false; } try { FieldInfo field = cctvApi.GetField("DetectionTimeMultiplierProvider", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType.IsInstanceOfType(provider)) { field.SetValue(null, provider); return true; } PropertyInfo property = cctvApi.GetProperty("DetectionTimeMultiplierProvider", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if ((object)property != null && property.CanWrite && property.PropertyType.IsInstanceOfType(provider)) { property.SetValue(null, provider); return true; } } catch { } return false; } internal static bool TryDisableCamera(int cameraId) { return InvokeStaticBool(CctvApi, "TryDisableCamera", new object[1] { cameraId }); } internal static bool IsCameraDisabled(int cameraId) { return InvokeStaticBool(CctvApi, "IsCameraDisabled", new object[1] { cameraId }); } internal static bool TrySetLockdown(bool begin) { return InvokeStaticBool(CctvApi, begin ? "TryBeginLockdown" : "TryEndLockdown", null); } internal static IReadOnlyList GetStashCodes() { return ReadIntList(ReadStaticMember(CctvApi, "MainframeControlStashCodes")); } internal static IReadOnlyList GetCameraIds() { return ReadIntList(InvokeStatic(CctvApi, "GetCameraIds", null)); } internal static string FormatStashCode(int code) { return (InvokeStatic(CctvApi, "FormatStashCode", new object[1] { code }) as string) ?? code.ToString("0000"); } internal static string GetCameraLabel(int cameraId) { return InvokeStatic(CctvApi, "GetCameraLabel", new object[1] { cameraId }) as string; } internal static bool IsSecurityAlarmActive() { if (!ReadInstanceBool(ReadStaticMember(MainframeType, "Active"), "IsSecurityAlarmActive")) { return IsTimedSecurityAlarmActive; } return true; } internal static void ApplyAlarmOperation(byte operation, byte silenceOperation) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) object obj = ReadStaticMember(MainframeType, "Active"); if (obj != null) { if (operation == silenceOperation) { InvokeInstance(obj, "SilenceSecurityAlarmServerRpc", new object[1] { (object)default(ServerRpcParams) }); } else { InvokeInstance(obj, "SetAlarmServerRpc", new object[2] { operation != 0, (object)default(ServerRpcParams) }); } } } internal static void CollectCameraTransforms(List output) { if (output == null || !OptionalPluginCapabilities.LethalCctv || !(ReadStaticMember(Type.GetType("Y4NGZCompany.Facility.Security.CctvSecurityCameraRegistry, LethalCCTV", throwOnError: false), "RegisteredCameras") is IEnumerable enumerable)) { return; } foreach (object item in enumerable) { object obj = ReadInstanceMember(item, "Transform"); Transform val = (Transform)((obj is Transform) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { output.Add(val); } } } internal static void CollectActiveObjectivePositions(List output) { //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_0068: Unknown result type (might be due to invalid IL or missing references) if (output == null || !OptionalPluginCapabilities.Contracted || !(InvokeStatic(Type.GetType("Y4NGZCompany.Contracts._Shared.MoonContractObjectiveMarkerApi, Y4NGZCompany", throwOnError: false), "GetActiveMarkers", null) is IEnumerable enumerable)) { return; } foreach (object item2 in enumerable) { if (item2 != null && !ReadInstanceBool(item2, "IsComplete") && ReadInstanceMember(item2, "Position") is Vector3 item) { output.Add(item); } } } private static IReadOnlyList ReadIntList(object value) { List list = new List(); if (!(value is IEnumerable enumerable)) { return list; } foreach (object item2 in enumerable) { if (item2 is int item) { list.Add(item); } } return list; } private static bool InvokeStaticBool(Type type, string name, object[] arguments) { object obj = InvokeStatic(type, name, arguments); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool ReadStaticBool(Type type, string name) { object obj = ReadStaticMember(type, name); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static bool ReadInstanceBool(object instance, string name) { object obj = ReadInstanceMember(instance, name); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } private static object InvokeStatic(Type type, string name, object[] arguments) { try { return type?.GetMethod(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(null, arguments); } catch { return null; } } private static object InvokeInstance(object instance, string name, object[] arguments) { if (instance == null) { return null; } try { return instance.GetType().GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(instance, arguments); } catch { return null; } } private static object ReadStaticMember(Type type, string name) { try { PropertyInfo propertyInfo = type?.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (propertyInfo != null) { return propertyInfo.GetValue(null); } return type?.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); } catch { return null; } } private static object ReadInstanceMember(object instance, string name) { if (instance == null) { return null; } try { Type type = instance.GetType(); PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null) { return property.GetValue(instance); } return type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance); } catch { return null; } } } internal static class OptionalPluginCapabilities { internal const string ContractedGuid = "com.y4ngz.company"; internal const string ShipSystemsGuid = "com.y4ngz.company.shipsystems"; internal const string LethalCctvGuid = "com.y4ngz.company.lethalcctv"; internal const string BetterArmoryGuid = "com.y4ngz.betterarmory"; internal const string BloodFxGuid = "com.y4ngz.bloodfx"; internal const string MoreCompanyGuid = "me.swipez.melonloader.morecompany"; internal const string TooManyEmotesGuid = "FlipMods.TooManyEmotes"; internal const string HotbarPlusGuid = "FlipMods.HotbarPlus"; internal const string CoronerGuid = "com.elitemastereric.coroner"; internal const string BetterExpGuid = "Swaggies.BetterEXP"; internal static bool Contracted => IsLoaded("com.y4ngz.company"); internal static bool ShipSystems => IsLoaded("com.y4ngz.company.shipsystems"); internal static bool LethalCctv => IsLoaded("com.y4ngz.company.lethalcctv"); internal static bool BetterArmory => IsLoaded("com.y4ngz.betterarmory"); internal static bool HotbarPlus => IsLoaded("FlipMods.HotbarPlus"); internal static bool NativeInventoryAvailable => !HotbarPlus; internal static bool Coroner => IsLoaded("com.elitemastereric.coroner"); internal static bool BetterExp => IsLoaded("Swaggies.BetterEXP"); internal static OptionalUpgradeProvider LoadedUpgradeProviders { get { OptionalUpgradeProvider optionalUpgradeProvider = OptionalUpgradeProvider.None; if (Contracted) { optionalUpgradeProvider |= OptionalUpgradeProvider.Contracted; } if (ShipSystems) { optionalUpgradeProvider |= OptionalUpgradeProvider.ShipSystems; } if (LethalCctv) { optionalUpgradeProvider |= OptionalUpgradeProvider.LethalCctv; } if (BetterArmory) { optionalUpgradeProvider |= OptionalUpgradeProvider.BetterArmory; } if (NativeInventoryAvailable) { optionalUpgradeProvider |= OptionalUpgradeProvider.NativeInventory; } return optionalUpgradeProvider; } } internal static bool HasAll(OptionalUpgradeProvider providers) { if (providers == OptionalUpgradeProvider.None) { return true; } if ((!providers.HasFlag(OptionalUpgradeProvider.Contracted) || Contracted) && (!providers.HasFlag(OptionalUpgradeProvider.ShipSystems) || ShipSystems) && (!providers.HasFlag(OptionalUpgradeProvider.LethalCctv) || LethalCctv) && (!providers.HasFlag(OptionalUpgradeProvider.BetterArmory) || BetterArmory)) { if (providers.HasFlag(OptionalUpgradeProvider.NativeInventory)) { return NativeInventoryAvailable; } return true; } return false; } internal static bool IsLoaded(string pluginGuid) { if (string.IsNullOrWhiteSpace(pluginGuid)) { return false; } try { return Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey(pluginGuid); } catch { return false; } } } internal sealed class PendingSaveIdentityStore { private readonly object _gate = new object(); private readonly Dictionary _identities = new Dictionary(StringComparer.OrdinalIgnoreCase); internal bool TryGet(string saveFileName, out string identity) { identity = null; if (!TryNormalize(saveFileName, out var normalized)) { return false; } lock (_gate) { return _identities.TryGetValue(normalized, out identity); } } internal bool TryGetOrCreate(string saveFileName, out string identity) { identity = null; if (!TryNormalize(saveFileName, out var normalized)) { return false; } lock (_gate) { if (_identities.TryGetValue(normalized, out identity)) { return true; } identity = Guid.NewGuid().ToString("N"); _identities[normalized] = identity; return true; } } internal void MarkPersisted(string saveFileName) { if (!TryNormalize(saveFileName, out var normalized)) { return; } lock (_gate) { _identities.Remove(normalized); } } internal void Clear() { lock (_gate) { _identities.Clear(); } } private static bool TryNormalize(string saveFileName, out string normalized) { normalized = saveFileName?.Trim(); if (!string.IsNullOrEmpty(normalized)) { return true; } normalized = null; return false; } } [BepInPlugin("com.y4ngz.upgrades", "Y4NGZUpgrades", "1.0.0")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class Plugin : BaseUnityPlugin { public const string Guid = "com.y4ngz.upgrades"; public const string Name = "Y4NGZUpgrades"; public const string Version = "1.0.0"; private static ConfigEntry _legacyShadowStepKeybind; private static ConfigEntry _legacyPingKeybind; private static ConfigEntry _legacyFieldTabletKeybind; private static ConfigEntry _legacyCommandNetKeybind; private static ConfigEntry _legacyWorklightBeaconKeybind; private static ConfigEntry _legacyDronePointerCommandKeybind; public static ConfigEntry TabletPullInMeters; public static ConfigEntry TabletPullUpMeters; public static ConfigEntry TabletRaisedPullInMeters; public static ConfigEntry WallMaxExtraPullMeters; public static ConfigEntry TabletScreenOffsetX; public static ConfigEntry TabletScreenOffsetY; public static ConfigEntry TabletScreenWidth; public static ConfigEntry TabletScreenHeight; public static ConfigEntry TabletScreenCalibration; public static ConfigEntry SlideRestoreStateMode; public static ConfigEntry SlidePostRestoreDiagnostics; public static ConfigEntry SlideRestoreCameraBaseline; public static ConfigEntry SlideRestoreCameraRotation; public static ConfigEntry SlideRestoreVisorPose; public static ConfigEntry RemoteSlideTerrainConformance; public static ConfigEntry RemoteMantleBodyGrabIk; public static ConfigEntry BurningStatusEnabled; public static ConfigEntry BurningFromFlamethrowerEnabled; public static ConfigEntry BurningDuration; public static ConfigEntry BurningDamagePerTick; public static ConfigEntry BurningTickInterval; public static ConfigEntry BurningLightIntensity; public static ConfigEntry BurningDebugLogging; public static ConfigEntry BurningRigEnabled; public static ConfigEntry BurningRigReferenceHeight; public static ConfigEntry BurningRigScaleMultiplier; public static ConfigEntry BurningRigAudioEnabled; public static ConfigEntry BurningMaxSimultaneousLights; private static bool _applicationQuitting; private static bool _shutdown; private static Harmony _harmony; internal static Plugin Instance { get; private set; } internal static ManualLogSource Log { get; private set; } internal static ProgressionSettings ProgressionConfig { get; private set; } internal static string[] ReservedKeyNames { get; private set; } = new string[0]; private void Awake() { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; _applicationQuitting = false; _shutdown = false; Application.quitting -= OnApplicationQuitting; Application.quitting += OnApplicationQuitting; Y4NGZConfigFiles.Initialize(((BaseUnityPlugin)this).Config, ((BaseUnityPlugin)this).Info.Metadata); ProgressionConfig = new ProgressionSettings(Y4NGZConfigFiles.Progression, Y4NGZConfigFiles.XpSources); Y4NGZPersistentRunner.Ensure(); MonoBehaviour val = Y4NGZPersistentRunner.Host; if ((Object)(object)val == (Object)null) { Log.LogError((object)"[Y4NGZUpgrades] Persistent session host could not be created; falling back to the BepInEx plugin host. Scene-lifetime services may stop if HideManagerGameObject is false."); val = (MonoBehaviour)(object)this; } BindCustomUpgradeConfig(); Y4NGZUpgrades.Interactive.Plugin.Initialize(((BaseUnityPlugin)this).Logger, val); Y4NGZUpgrades.Gui.Plugin.Initialize(Y4NGZConfigFiles.PlayerMenu, ((BaseUnityPlugin)this).Logger, val); MigrateLegacyKeybinds(); RefreshReservedKeyNames(); Y4NGZUpgradeCatalog.RegisterDefaults(); MovementPlayerAnimationRuntimeAssets.Prewarm(); ProgressionManager.Load(); Lucky8Manager.Initialize(Y4NGZConfigFiles.Lucky8); Y4NGZConfigFiles.CompleteMigration(); EffectiveConfigInventory.Write(Y4NGZConfigFiles.All); ProgressionXpBarUi.Initialize(val); Y4NGZUpgradeManager.Load(); SaveDataLifecycle.ReconcileOrphans(); RoundLifecycle.Install(); _harmony = new Harmony("com.y4ngz.upgrades"); _harmony.PatchAll(typeof(ProgressionPatches).Assembly); ExtraSlotManager.Initialize(); FieldOperationsTabletPatch.Initialize(); ChameleonCompanyPatch.Initialize(); ScavengerCompanyPatch.Initialize(); QuotaGuardCompanyPatch.Initialize(); Log.LogMessage((object)"Y4NGZUpgrades v1.0.0 loaded. Native progression enabled."); } private void OnDestroy() { if (!_applicationQuitting) { ManualLogSource log = Log; if (log != null) { log.LogWarning((object)"[Y4NGZUpgrades] The plugin host GameObject was destroyed mid-session (BepInEx [Chainloader] HideManagerGameObject is false). Harmony patches, keybinds and session services remain ACTIVE; cleanup is deferred until application quit."); } } else { Shutdown(); } } private static void OnApplicationQuitting() { _applicationQuitting = true; Shutdown(); } private static void Shutdown() { if (!_shutdown) { _shutdown = true; Application.quitting -= OnApplicationQuitting; RunShutdownStep("LUCKY-8", Lucky8Manager.Shutdown); RunShutdownStep("progression save", ProgressionManager.Save); RunShutdownStep("upgrade save", Y4NGZUpgradeManager.Save); RunShutdownStep("Field Operations tablet", FieldOperationsTabletPatch.Shutdown); RunShutdownStep("extra slots", ExtraSlotManager.Shutdown); RunShutdownStep("player menu", Y4NGZUpgrades.Gui.Plugin.Shutdown); RunShutdownStep("interactive systems", Y4NGZUpgrades.Interactive.Plugin.Shutdown); Harmony harmony = _harmony; _harmony = null; if (harmony != null) { RunShutdownStep("Harmony patches", (Action)harmony.UnpatchSelf); } } } private static void RunShutdownStep(string name, Action action) { try { action(); } catch (Exception arg) { ManualLogSource log = Log; if (log != null) { log.LogError((object)$"[Y4NGZUpgrades] Application-quit {name} teardown failed safely: {arg}"); } } } public static float GetTabletPullInMeters() { return ClampConfig(TabletPullInMeters, 0.1f, 0f, 0.25f); } public static float GetTabletPullUpMeters() { return ClampConfig(TabletPullUpMeters, 0.02f, 0f, 0.25f); } public static float GetTabletRaisedPullInMeters() { return ClampConfig(TabletRaisedPullInMeters, 0.05f, 0f, 0.25f); } public static float GetWallMaxExtraPullMeters() { return ClampConfig(WallMaxExtraPullMeters, 0.18f, 0f, 0.25f); } public static float GetTabletScreenOffsetX() { return ClampConfig(TabletScreenOffsetX, 0.01229f, -0.2f, 0.2f); } public static float GetTabletScreenOffsetY() { return ClampConfig(TabletScreenOffsetY, 0.108905f, -0.2f, 0.4f); } public static float GetTabletScreenWidth() { return ClampConfig(TabletScreenWidth, 0.21328f, 0.04f, 0.6f); } public static float GetTabletScreenHeight() { return ClampConfig(TabletScreenHeight, 0.14803f, 0.03f, 0.4f); } public static bool GetTabletScreenCalibration() { if (TabletScreenCalibration != null) { return TabletScreenCalibration.Value; } return false; } private void BindCustomUpgradeConfig() { _legacyShadowStepKeybind = BindUpgradeSetting("shadow_step", "Controls", "Activation Key", "g", "Key used to activate Shadow Step at level 3. Use a Unity Input System key name.", "Keybinds", "Shadow Step Key"); _legacyPingKeybind = BindUpgradeSetting("ping", "Controls", "Activation Key", "q", "Key used to place a Foreman Ping. This is separate from the vanilla scanner input.", "Keybinds", "Ping Key"); _legacyFieldTabletKeybind = BindUpgradeSetting("field_operations", "Controls", "Tablet Toggle Key", "y", "Key used to open or close the Field Operations tablet.", "Keybinds", "Field Tablet Key"); _legacyCommandNetKeybind = BindUpgradeSetting("command_net", "Controls", "Transmit Key", "j", "Hold this key to transmit over Command Net's built-in walkie channel.", "Keybinds", "Command Net Key"); Y4NGZConfigScope target = Y4NGZConfigFiles.Upgrade("worklight_beacon"); bool flag = Y4NGZConfigFiles.TargetAlreadyDefines(target, "Controls", "Throw Beacon Key"); _legacyWorklightBeaconKeybind = Y4NGZConfigFiles.BindMigrated(target, "Controls", "Throw Beacon Key", "v", "Key used to throw a Worklight Beacon.", new LegacyConfigKey("Keybinds", "Worklight Beacon Key")); if (!flag && string.Equals(_legacyWorklightBeaconKeybind.Value?.Trim(), "r", StringComparison.OrdinalIgnoreCase) && (!Y4NGZConfigFiles.TryGetLegacy("Keybinds", "SchemaVersion", out var value) || value < 2)) { _legacyWorklightBeaconKeybind.Value = "v"; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)"[Config] Updated the old Worklight Beacon default from R to V to avoid weapon reload."); } } _legacyDronePointerCommandKeybind = BindUpgradeSetting("courier_drone", "Controls", "Pointer Command", "MiddleButton", "Button used for Courier Drone pointer commands. Mouse values: MiddleButton, RightButton, ForwardButton, or BackButton; keyboard values use Unity Input System key names.", "Courier Drone", "DronePointerCommandKeybind"); Y4NGZConfigScope y4NGZConfigScope = Y4NGZConfigFiles.Upgrade("field_operations"); TabletPullInMeters = BindTabletSetting(y4NGZConfigScope, "Tablet Placement", "Pull Toward Camera", 0.1f, "Regular tablet pull toward the camera, in metres.", 0f, 0.25f, "TabletPullInMeters"); TabletPullUpMeters = BindTabletSetting(y4NGZConfigScope, "Tablet Placement", "Move Up", 0.02f, "Regular tablet upward camera-space offset, in metres.", 0f, 0.25f, "TabletPullUpMeters"); TabletRaisedPullInMeters = BindTabletSetting(y4NGZConfigScope, "Tablet Placement", "Raised Pull Toward Camera", 0.05f, "Raised tablet pull toward the camera, in metres.", 0f, 0.25f, "TabletRaisedPullInMeters"); WallMaxExtraPullMeters = BindTabletSetting(y4NGZConfigScope, "Tablet Placement", "Maximum Wall Avoidance Pull", 0.18f, "Maximum extra pull toward the camera when the tablet is near a wall, in metres.", 0f, 0.25f, "WallMaxExtraPullMeters"); TabletScreenOffsetX = BindTabletSetting(y4NGZConfigScope, "Screen Placement", "Horizontal Offset", 0.01229f, "Screen overlay centre offset along the tablet's local X axis, in metres.", -0.2f, 0.2f, "TabletScreenOffsetX"); TabletScreenOffsetY = BindTabletSetting(y4NGZConfigScope, "Screen Placement", "Vertical Offset", 0.108905f, "Screen overlay centre offset along the tablet's local Y axis, in metres.", -0.2f, 0.4f, "TabletScreenOffsetY"); TabletScreenWidth = BindTabletSetting(y4NGZConfigScope, "Screen Placement", "Width", 0.21328f, "Screen overlay width, in metres.", 0.04f, 0.6f, "TabletScreenWidth"); TabletScreenHeight = BindTabletSetting(y4NGZConfigScope, "Screen Placement", "Height", 0.14803f, "Screen overlay height, in metres.", 0.03f, 0.4f, "TabletScreenHeight"); TabletScreenCalibration = Y4NGZConfigFiles.BindMigrated(y4NGZConfigScope, "Screen Placement", "Show Calibration Pattern", false, "Show a temporary border, corner marks, crosshair, and live measurements for aligning the tablet screen.", new LegacyConfigKey("Field Operations Tablet", "TabletScreenCalibration")); SlideRestoreStateMode = BindUpgradeSetting("panic_slide", "Animation Restore", "State Mode", "fresh", "Vanilla Animator state restore mode after slide/mantle: fresh, crossfade, or replay. Fresh lets the restored controller enter from Entry using restored vanilla parameters.", "Panic Slide", "Slide Restore State Mode"); SlidePostRestoreDiagnostics = BindUpgradeSetting("panic_slide", "Animation Restore", "Post-Restore Diagnostics", defaultValue: true, "Log camera-container, gameplay-camera, and Animator layer state for the restore frame and next two frames.", "Panic Slide", "Slide Post-Restore Diagnostics"); SlideRestoreCameraBaseline = BindUpgradeSetting("panic_slide", "Animation Restore", "Camera Baseline", "begin", "Camera pose target after slide/mantle: begin restores clean pre-controller camera/container TRS with live cameraUp pitch; live keeps restore-entry pose as a diagnostic kill-switch.", "Panic Slide", "Slide Restore Camera Baseline"); SlideRestoreCameraRotation = BindUpgradeSetting("panic_slide", "Animation Restore", "Restore Camera Rotation", defaultValue: true, "Restore gameplay-camera and camera-container rotation using the selected camera baseline; begin keeps live cameraUp pitch with clean yaw and roll.", "Panic Slide", "Slide Restore Camera Rotation"); SlideRestoreVisorPose = BindUpgradeSetting("panic_slide", "Animation Restore", "Restore Visor Pose", defaultValue: true, "Preserve the local helmet visor pose and vanilla rotation-lerp state across slide/mantle Animator-controller restores.", "Panic Slide", "Slide Restore Visor Pose"); RemoteSlideTerrainConformance = BindUpgradeSetting("panic_slide", "Presentation", "Remote Slide Terrain Conformance", defaultValue: true, "Ground and slope-align the presentation-only body of remote players during panic slides.", "Panic Slide", "Remote Slide Terrain Conformance"); RemoteMantleBodyGrabIk = BindUpgradeSetting("panic_slide", "Presentation", "Remote Mantle Body Grab IK", defaultValue: true, "Plant remote mantle hands near the replicated ledge grip while preserving the authored arm bend.", "Panic Slide", "Remote Mantle Body Grab IK"); } private static ConfigEntry BindUpgradeSetting(string upgradeId, string section, string key, T defaultValue, string description, string legacySection, string legacyKey) { return Y4NGZConfigFiles.BindMigrated(Y4NGZConfigFiles.Upgrade(upgradeId), section, key, defaultValue, description, new LegacyConfigKey(legacySection, legacyKey)); } private static ConfigEntry BindTabletSetting(Y4NGZConfigScope config, string section, string key, float defaultValue, string description, float minimum, float maximum, string legacyKey) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown return Y4NGZConfigFiles.BindMigrated(config, section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange(minimum, maximum), Array.Empty()), new LegacyConfigKey("Field Operations Tablet", legacyKey)); } private static float ClampConfig(ConfigEntry entry, float fallback, float min, float max) { return Mathf.Clamp(entry?.Value ?? fallback, min, max); } private static Vector3 ParseVec(string s, Vector3 fallback) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(s)) { return fallback; } string[] array = s.Split(','); if (array.Length != 3) { return fallback; } CultureInfo invariantCulture = CultureInfo.InvariantCulture; if (float.TryParse(array[0].Trim(), NumberStyles.Float, invariantCulture, out var result) && float.TryParse(array[1].Trim(), NumberStyles.Float, invariantCulture, out var result2) && float.TryParse(array[2].Trim(), NumberStyles.Float, invariantCulture, out var result3)) { return new Vector3(result, result2, result3); } return fallback; } private static void MigrateLegacyKeybinds() { if (LegacyKeybindMigration.TryMigrate(Y4NGZUpgrades.Gui.Plugin.Keybinds, _legacyShadowStepKeybind, _legacyPingKeybind, _legacyFieldTabletKeybind, _legacyCommandNetKeybind, _legacyWorklightBeaconKeybind, _legacyDronePointerCommandKeybind)) { Y4NGZConfigFiles.RetireBindings((ConfigEntryBase)_legacyShadowStepKeybind, (ConfigEntryBase)_legacyPingKeybind, (ConfigEntryBase)_legacyFieldTabletKeybind, (ConfigEntryBase)_legacyCommandNetKeybind, (ConfigEntryBase)_legacyWorklightBeaconKeybind, (ConfigEntryBase)_legacyDronePointerCommandKeybind); } } private unsafe static void RefreshReservedKeyNames() { //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) HashSet hashSet = new HashSet(); IngameKeybinds keybinds = Y4NGZUpgrades.Gui.Plugin.Keybinds; if (keybinds != null) { foreach (InputAction gameplayReservationAction in keybinds.GameplayReservationActions) { ReserveActionKeys(hashSet, gameplayReservationAction); } } string[] array = new string[hashSet.Count]; int num = 0; foreach (Key item in hashSet) { array[num++] = ((object)(*(Key*)(&item))/*cast due to .constrained prefix*/).ToString(); } Array.Sort(array, (IComparer?)StringComparer.Ordinal); ReservedKeyNames = array; } private static void ReserveActionKeys(HashSet used, InputAction action) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (action == null) { return; } Enumerator enumerator = action.bindings.GetEnumerator(); try { while (enumerator.MoveNext()) { InputBinding current = enumerator.Current; Key? val = ParseKeyboardBindingPath(((InputBinding)(ref current)).effectivePath); if (val.HasValue) { used.Add(val.Value); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } private static Key? ParseKeyboardBindingPath(string path) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(path)) { return null; } if (!path.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { return null; } string text = path.Substring("/".Length).Trim(); if (text.Length == 1 && text[0] >= '1' && text[0] <= '9') { return (Key)(41 + (text[0] - 49)); } if (text == "0") { return (Key)50; } if (!Enum.TryParse(text, ignoreCase: true, out Key result)) { return null; } return result; } } public static class ProgressionApi { public static int RankXp => ProgressionManager.CurrentRankXp; public static int UpgradeCurrency => ProgressionManager.CurrentUpgradeCurrency; public static int Tokens => UpgradeCurrency; public static int Token => UpgradeCurrency; public static int Marks => UpgradeCurrency; public static int Bxp => UpgradeCurrency; public static int AvailableTokens => ProgressionManager.AvailableUpgradeCurrency; public static int RankIndex => RankCatalog.GetRankIndex(RankXp); public static string RankName => RankCatalog.GetRank(RankXp).Name; public static float RankProgress => RankCatalog.GetProgress(RankXp); public static void AwardContractXp(string key, string label, int amount, bool oncePerRound = true) { ProgressionManager.AddContractXp(key, label, amount, oncePerRound); } public static bool TrySpendUpgradeCurrency(int amount) { return ProgressionManager.TrySpendUpgradeCurrency(amount); } public static bool TryReserveTokenSpend(string transactionId, int amount) { return ProgressionManager.TryReserveTokenSpend(transactionId, amount); } public static bool CommitTokenSpend(string transactionId) { return ProgressionManager.CommitTokenSpend(transactionId); } public static bool CancelTokenSpend(string transactionId) { return ProgressionManager.CancelTokenSpend(transactionId); } internal static void AddUpgradeCurrency(int amount) { ProgressionManager.AddUpgradeCurrency(amount); } internal static void SetUpgradeCurrency(int amount) { ProgressionManager.SetUpgradeCurrency(amount); } internal static void AddTokens(int amount) { AddUpgradeCurrency(amount); } internal static void SetTokens(int amount) { SetUpgradeCurrency(amount); } internal static bool TrySetTokensForTesting(int amount) { return ProgressionManager.TrySetUpgradeCurrencyForTesting(amount); } internal static void AddToken(int amount) { AddUpgradeCurrency(amount); } internal static void SetToken(int amount) { SetUpgradeCurrency(amount); } internal static void AddMarks(int amount) { AddUpgradeCurrency(amount); } internal static void SetMarks(int amount) { SetUpgradeCurrency(amount); } internal static void AddBxp(int amount) { AddUpgradeCurrency(amount); } internal static void SetBxp(int amount) { SetUpgradeCurrency(amount); } public static RoundXpBreakdown GetLastRoundBreakdown() { return ProgressionManager.LastRoundBreakdown?.Clone(); } public static float GetScavengerAmmoMultiplier() { return ScavengerUpgrade.GetAmmoMultiplier(); } } public static class ProgressionEconomyMath { public static int ScaleRiskXp(int rawXp, float multiplier) { if (rawXp <= 0 || multiplier <= 0f) { return 0; } return Math.Max(0, (int)Math.Ceiling((double)rawXp * (double)multiplier)); } public static int ScaleContractXp(int rawContractXp, float multiplier) { return ScaleRiskXp(rawContractXp, multiplier); } public static int[] DistributeScaledXp(int[] rawAmounts, int scaledTotal) { if (rawAmounts == null || rawAmounts.Length == 0) { return Array.Empty(); } int[] array = new int[rawAmounts.Length]; if (scaledTotal <= 0) { return array; } long num = 0L; for (int i = 0; i < rawAmounts.Length; i++) { if (rawAmounts[i] > 0) { num += rawAmounts[i]; } } if (num <= 0) { return array; } long[] array2 = new long[rawAmounts.Length]; long num2 = 0L; for (int j = 0; j < rawAmounts.Length; j++) { if (rawAmounts[j] <= 0) { array2[j] = -1L; continue; } long num3 = (long)rawAmounts[j] * (long)scaledTotal; long num4 = num3 / num; array2[j] = num3 % num; array[j] = (int)((num4 > int.MaxValue) ? int.MaxValue : num4); num2 += array[j]; } for (long num5 = scaledTotal - num2; num5 > 0; num5--) { int num6 = -1; for (int k = 0; k < array2.Length; k++) { if (array2[k] >= 0 && (num6 < 0 || array2[k] > array2[num6])) { num6 = k; } } if (num6 < 0) { break; } array[num6]++; array2[num6] = -1L; } return array; } public static int ComputeRoundAwardedXp(int discoveryXp, int deliveryXp, int combatXp, int survivalXp, int rawContractXp, float contractMultiplier) { return ComputeRoundAwardedXp(discoveryXp, deliveryXp, combatXp, survivalXp, rawContractXp, 0, contractMultiplier); } public static int ComputeRoundAwardedXp(int discoveryXp, int deliveryXp, int combatXp, int survivalXp, int rawContractXp, int rawBodyRetrievalXp, float riskMultiplier) { return ComputeRoundAwardedXp(discoveryXp, deliveryXp, combatXp, survivalXp, 0, 0, rawContractXp, rawBodyRetrievalXp, riskMultiplier); } public static int ComputeRoundAwardedXp(int discoveryXp, int deliveryXp, int combatXp, int survivalXp, int mainframeHackXp, int clutchXp, int rawContractXp, int rawBodyRetrievalXp, float riskMultiplier) { long num = (long)Math.Max(0, discoveryXp) + (long)Math.Max(0, deliveryXp) + Math.Max(0, combatXp) + Math.Max(0, survivalXp) + Math.Max(0, mainframeHackXp) + Math.Max(0, clutchXp) + ScaleRiskXp(rawContractXp, riskMultiplier) + ScaleRiskXp(rawBodyRetrievalXp, riskMultiplier); if (num <= int.MaxValue) { return (int)num; } return int.MaxValue; } public static int GetRankWidth(int[] rankWidths, int rankIndex) { if (rankWidths == null || rankWidths.Length == 0) { return 0; } int num = rankIndex; if (num < 0) { num = 0; } if (num > rankWidths.Length - 1) { num = rankWidths.Length - 1; } return Math.Max(1, rankWidths[num]); } public static int GetRankIndex(int[] rankWidths, int xp) { if (rankWidths == null || rankWidths.Length == 0) { return 0; } int num = 0; for (int i = 0; i < rankWidths.Length; i++) { num += Math.Max(1, rankWidths[i]); if (xp < num) { return i; } } return rankWidths.Length; } public static int ComputeContractCompletionXp(int rankWidth, float widthFraction, float typeMultiplier) { if (rankWidth <= 0 || widthFraction <= 0f || typeMultiplier <= 0f) { return 0; } double num = Math.Round((double)rankWidth * (double)widthFraction * (double)typeMultiplier, MidpointRounding.AwayFromZero); if (num <= 0.0) { return 0; } if (!(num >= 2147483647.0)) { return (int)num; } return int.MaxValue; } public static int ComputeCappedRepeatXp(int creditsAlreadyPaid, int maxCredits, int xpPerCredit) { if (xpPerCredit <= 0 || maxCredits <= 0) { return 0; } if (Math.Max(0, creditsAlreadyPaid) < maxCredits) { return xpPerCredit; } return 0; } public static int ComputePayloadPilotXp(float seconds, float xpPerSecond, int cap) { if (seconds <= 0f || xpPerSecond <= 0f || cap <= 0) { return 0; } int val = (int)Math.Floor((double)seconds * (double)xpPerSecond); return Math.Min(Math.Max(0, cap), Math.Max(0, val)); } public static int GetTokenGrantForRankIndex(int rankIndex, int earnableRankCount, int ranks1To5, int ranks6To10, int ranks11To19, int ranks20To30) { if (rankIndex <= 0 || rankIndex > earnableRankCount) { return 0; } if (rankIndex <= 5) { return Math.Max(0, ranks1To5); } if (rankIndex <= 10) { return Math.Max(0, ranks6To10); } if (rankIndex <= 19) { return Math.Max(0, ranks11To19); } return Math.Max(0, ranks20To30); } public static int GetTokenGrantForRankRange(int firstRankIndex, int finalRankIndex, int earnableRankCount, int ranks1To5, int ranks6To10, int ranks11To19, int ranks20To30) { if (firstRankIndex > finalRankIndex) { return 0; } int num = Math.Max(1, firstRankIndex); int num2 = Math.Min(finalRankIndex, earnableRankCount); int num3 = 0; for (int i = num; i <= num2; i++) { num3 += GetTokenGrantForRankIndex(i, earnableRankCount, ranks1To5, ranks6To10, ranks11To19, ranks20To30); } return num3; } public static bool TryParsePositiveIntCsv(string value, int expectedCount, out int[] result) { result = null; if (string.IsNullOrWhiteSpace(value) || expectedCount < 0) { return false; } string[] array = value.Split(','); if (array.Length != expectedCount) { return false; } int[] array2 = new int[expectedCount]; for (int i = 0; i < array.Length; i++) { if (!int.TryParse(array[i].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out array2[i]) || array2[i] <= 0) { return false; } } result = array2; return true; } } internal static class ProgressionManager { private readonly struct TokenReservation { internal readonly string SaveKey; internal readonly int Amount; internal TokenReservation(string saveKey, int amount) { SaveKey = saveKey; Amount = amount; } } private sealed class DeliveredScrapReportGroup { internal readonly string Key; internal readonly string Name; internal int Count; internal int Value; internal DeliveredScrapReportGroup(string key, string name) { Key = key; Name = name; } } private sealed class ReportSourceAccumulator { internal readonly string Key; internal readonly ProgressionReportSourceKind Kind; internal readonly string Subject; internal readonly int Order; internal int Count; internal int Amount; internal ReportSourceAccumulator(string key, ProgressionReportSourceKind kind, string subject, int order) { Key = key; Kind = kind; Subject = subject; Order = order; } } private sealed class RoundTracker { internal float RoundStartTime; internal bool LocalPlayerDied; internal float LocalPlayerDeathTime; internal int ScrapPickupXp; internal int ScrapDeliveredXp; internal int MonsterKillXp; internal int SurvivalXp; internal int SurvivalMinutesForReport = 1; internal int MainframeHackXp; internal int ClutchXp; internal int ContractXp; internal int BodyRetrievalXp; internal string MoonRisk = "C"; internal float MoonMultiplier = 1f; internal const int UnpinnedRank = -1; internal int StartRankIndex = -1; internal readonly Dictionary FirstScrapDiscovererByKey = new Dictionary(); internal readonly DeliveryAttributionLedger Delivery = new DeliveryAttributionLedger(); internal readonly HashSet KilledEnemies = new HashSet(); internal readonly HashSet HackedMainframes = new HashSet(); internal readonly HashSet FacilityEntrants = new HashSet(); internal readonly Dictionary LastEnemyHitByLocalPlayer = new Dictionary(); internal readonly HashSet ContractXpKeys = new HashSet(); internal readonly Dictionary CappedContractCredits = new Dictionary(StringComparer.Ordinal); internal readonly List RetrievedBodyNames = new List(); internal int RetrievedBodyCount; private readonly List _reportSourceOrder = new List(); private readonly Dictionary _reportSources = new Dictionary(StringComparer.Ordinal); internal void AddReportSource(string key, ProgressionReportSourceKind kind, string subject, int count, int amount) { if (amount > 0 && !string.IsNullOrWhiteSpace(key)) { if (!_reportSources.TryGetValue(key, out var value)) { value = new ReportSourceAccumulator(key, kind, subject?.Trim() ?? string.Empty, _reportSourceOrder.Count); _reportSources.Add(key, value); _reportSourceOrder.Add(value); } value.Count = AddClamped(value.Count, count); value.Amount = AddClamped(value.Amount, amount); } } internal IReadOnlyList BuildReportSources() { ProgressionReportSource[] array = new ProgressionReportSource[_reportSourceOrder.Count]; for (int i = 0; i < _reportSourceOrder.Count; i++) { ReportSourceAccumulator reportSourceAccumulator = _reportSourceOrder[i]; array[i] = new ProgressionReportSource(reportSourceAccumulator.Key, reportSourceAccumulator.Kind, reportSourceAccumulator.Subject, reportSourceAccumulator.Count, reportSourceAccumulator.Amount, reportSourceAccumulator.Order); } return array; } } private static readonly Dictionary States = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly string SaveDir = Path.Combine(Application.persistentDataPath, "Y4NGZUpgrades"); private static readonly string SavePath = Path.Combine(SaveDir, "progression_save.txt"); private static ProgressionState _state = new ProgressionState(); private static string _currentSaveKey; private static RoundTracker _round = new RoundTracker(); private static readonly RoundLatch _latch = new RoundLatch(); private static readonly Dictionary TokenReservations = new Dictionary(StringComparer.Ordinal); private const int MaxCompletedTokenSpends = 256; private const string OverachieverRetroGrantIdPrefix = "overachiever_retro_tier"; private static bool _backfillingOverachiever; internal static RoundXpBreakdown LastRoundBreakdown { get; private set; } internal static IReadOnlyList LastRoundReportSources { get; private set; } = Array.Empty(); private static int LastRoundReportSequence { get; set; } internal static int CurrentRankXp => _state?.RankXp ?? 0; internal static int CurrentUpgradeCurrency => _state?.UpgradeCurrency ?? 0; internal static int AvailableUpgradeCurrency { get { SwitchToCurrentSave(); return Mathf.Max(0, CurrentUpgradeCurrency - ReservedCurrencyForCurrentSave()); } } internal static bool TrySpendUpgradeCurrency(int amount) { if (amount <= 0) { return true; } SwitchToCurrentSave(); if (_state == null || AvailableUpgradeCurrency < amount) { return false; } _state.UpgradeCurrency -= amount; Save(); return true; } internal static bool TryReserveTokenSpend(string transactionId, int amount) { transactionId = NormalizeTransactionId(transactionId); if (transactionId.Length == 0 || amount <= 0 || !SwitchToCurrentSave()) { return false; } if (_state.CompletedTokenSpendIds.Contains(transactionId)) { return true; } if (TokenReservations.TryGetValue(transactionId, out var value)) { if (string.Equals(value.SaveKey, _currentSaveKey, StringComparison.OrdinalIgnoreCase)) { return value.Amount == amount; } return false; } if (AvailableUpgradeCurrency < amount) { return false; } TokenReservations[transactionId] = new TokenReservation(_currentSaveKey, amount); return true; } internal static bool CommitTokenSpend(string transactionId) { transactionId = NormalizeTransactionId(transactionId); if (transactionId.Length == 0 || !SwitchToCurrentSave()) { return false; } if (_state.CompletedTokenSpendIds.Contains(transactionId)) { return true; } if (!TokenReservations.TryGetValue(transactionId, out var value) || !string.Equals(value.SaveKey, _currentSaveKey, StringComparison.OrdinalIgnoreCase) || _state.UpgradeCurrency < value.Amount) { return false; } _state.UpgradeCurrency -= value.Amount; TokenReservations.Remove(transactionId); _state.CompletedTokenSpendIds.Add(transactionId); TrimCompletedTokenSpends(_state.CompletedTokenSpendIds); Save(); return true; } internal static bool CancelTokenSpend(string transactionId) { transactionId = NormalizeTransactionId(transactionId); if (transactionId.Length > 0) { return TokenReservations.Remove(transactionId); } return false; } internal static void AddUpgradeCurrency(int amount) { if (amount != 0) { SwitchToCurrentSave(); if (_state == null) { _state = new ProgressionState(); } _state.UpgradeCurrency = Mathf.Max(0, _state.UpgradeCurrency + amount); Save(); } } internal static void SetUpgradeCurrency(int amount) { SwitchToCurrentSave(); if (_state == null) { _state = new ProgressionState(); } _state.UpgradeCurrency = Mathf.Max(ReservedCurrencyForCurrentSave(), amount); Save(); } internal static bool TrySetUpgradeCurrencyForTesting(int amount) { if (amount < 0 || !SwitchToCurrentSave()) { return false; } string[] array = (from pair in TokenReservations where string.Equals(pair.Value.SaveKey, _currentSaveKey, StringComparison.OrdinalIgnoreCase) select pair.Key).ToArray(); for (int num = 0; num < array.Length; num++) { TokenReservations.Remove(array[num]); } if (_state == null) { _state = new ProgressionState(); } _state.UpgradeCurrency = amount; Save(); return CurrentUpgradeCurrency == amount; } internal static bool TryApplyExternalTokenGrant(string actionId, int amount) { bool alreadyApplied; return TryApplyExternalTokenGrant(actionId, amount, out alreadyApplied); } internal static bool TryApplyExternalTokenGrant(string actionId, int amount, out bool alreadyApplied) { alreadyApplied = false; if (string.IsNullOrWhiteSpace(actionId) || amount <= 0) { return false; } if (!SwitchToCurrentSave()) { return false; } if (_state == null) { _state = new ProgressionState(); } actionId = actionId.Trim(); if (_state.ExternalTokenGrantIds.Contains(actionId)) { alreadyApplied = true; return true; } long val = (long)Mathf.Max(0, _state.UpgradeCurrency) + (long)amount; _state.UpgradeCurrency = (int)Math.Min(2147483647L, val); _state.ExternalTokenGrantIds.Add(actionId); Save(); return true; } internal static bool TryApplyLedgeredTokenGrant(string saveKey, string grantId, int amount) { if (string.IsNullOrWhiteSpace(saveKey) || string.IsNullOrWhiteSpace(grantId) || amount < 0) { return false; } grantId = grantId.Trim(); if (!string.IsNullOrWhiteSpace(_currentSaveKey) && string.Equals(saveKey, _currentSaveKey, StringComparison.OrdinalIgnoreCase) && _state != null) { if (!_state.ExternalTokenGrantIds.Add(grantId)) { return true; } _state.UpgradeCurrency = AddCurrencyClamped(_state.UpgradeCurrency, amount); Save(); return true; } if (!States.TryGetValue(saveKey, out var value) || value == null) { return false; } if (!value.ExternalTokenGrantIds.Add(grantId)) { return true; } value.UpgradeCurrency = AddCurrencyClamped(value.UpgradeCurrency, amount); WriteStatesToDisk(); return true; } internal static void ApplyOverachieverRankBonusBackfill() { if (_backfillingOverachiever || !IsEnabled()) { return; } _backfillingOverachiever = true; try { if (!SwitchToCurrentSave() || _state == null || string.IsNullOrWhiteSpace(_currentSaveKey)) { return; } int tier = OverachieverUpgrade.GetTier(); if (tier <= 0) { return; } int rankIndex = RankCatalog.GetRankIndex(_state.RankXp); bool flag = false; for (int i = 1; i <= tier; i++) { string item = "overachiever_retro_tier" + i; if (_state.ExternalTokenGrantIds.Add(item)) { int num = OverachieverUpgrade.GetBonusTokensForTier(i) - OverachieverUpgrade.GetBonusTokensForTier(i - 1); int num2 = Mathf.Max(0, rankIndex * Mathf.Max(0, num)); if (num2 > 0) { _state.UpgradeCurrency = AddCurrencyClamped(_state.UpgradeCurrency, num2); } flag = true; LogDebug($"Overachiever tier {i} retroactive grant +{num2} for {rankIndex} already-earned rank(s)."); } } if (flag) { Save(); } } finally { _backfillingOverachiever = false; } } private static int AddCurrencyClamped(int current, int amount) { long val = (long)Mathf.Max(0, current) + (long)Mathf.Max(0, amount); return (int)Math.Min(2147483647L, val); } internal static void Load() { States.Clear(); TokenReservations.Clear(); try { if (File.Exists(SavePath)) { string[] array = File.ReadAllLines(SavePath); foreach (string text in array) { if (string.IsNullOrWhiteSpace(text)) { continue; } string[] array2 = text.Split('|'); if (array2.Length < 3) { continue; } string text2 = array2[0].Trim(); if (!string.IsNullOrWhiteSpace(text2)) { int.TryParse(array2[1], out var result); int.TryParse(array2[2], out var result2); ProgressionState progressionState = new ProgressionState { RankXp = RankCatalog.ClampXp(result), UpgradeCurrency = Mathf.Max(0, result2) }; if (array2.Length >= 4) { progressionState.ExternalTokenGrantIds.UnionWith(DecodeExternalGrantIds(array2[3])); } if (array2.Length >= 5) { progressionState.CompletedTokenSpendIds.UnionWith(DecodeExternalGrantIds(array2[4])); } TrimCompletedTokenSpends(progressionState.CompletedTokenSpendIds); States[text2] = progressionState; } } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Progression] Failed reading progression save: " + ex.Message)); } } SwitchToCurrentSave(); } internal static void Save() { try { if (SwitchToCurrentSave(preserveExistingState: true)) { States[_currentSaveKey] = _state?.Clone() ?? new ProgressionState(); WriteStatesToDisk(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Progression] Failed writing progression save: " + ex.Message)); } } } internal static bool SwitchToCurrentSave(bool preserveExistingState = false) { if (!SaveKey.TryGetCurrent(out var key)) { if (preserveExistingState && !string.IsNullOrWhiteSpace(_currentSaveKey) && _state != null) { States[_currentSaveKey] = _state.Clone(); } _currentSaveKey = null; _state = new ProgressionState(); return false; } if (preserveExistingState && !string.IsNullOrWhiteSpace(_currentSaveKey) && _state != null) { States[_currentSaveKey] = _state.Clone(); } _currentSaveKey = key; if (!States.TryGetValue(_currentSaveKey, out _state) || _state == null) { _state = new ProgressionState(); States[_currentSaveKey] = _state; } SyncVanillaRank(); ProgressionRankSync.PublishLocalRank(); return true; } internal static void ResetCurrentSave() { if (!SaveKey.TryGetCurrentExistingOrSlot(out var key)) { _state = new ProgressionState(); _currentSaveKey = null; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Progression] Reset skipped; no active save file."); } } else { DeleteForKeys(new string[1] { key }); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Progression] Reset progression state for save '" + key + "'.")); } } } internal static IReadOnlyCollection GetKnownSaveKeys() { return (IReadOnlyCollection)(object)States.Keys.ToArray(); } internal static int DeleteForKeys(IEnumerable keys) { HashSet keySet = new HashSet((keys ?? Enumerable.Empty()).Where((string value) => !string.IsNullOrWhiteSpace(value)), StringComparer.OrdinalIgnoreCase); if (keySet.Count == 0) { return 0; } int num = 0; foreach (string item in keySet) { if (States.Remove(item)) { num++; } } string[] array = (from pair in TokenReservations where keySet.Contains(pair.Value.SaveKey) select pair.Key).ToArray(); foreach (string key in array) { TokenReservations.Remove(key); } if (!string.IsNullOrWhiteSpace(_currentSaveKey) && keySet.Contains(_currentSaveKey)) { _state = new ProgressionState(); _currentSaveKey = null; _round = new RoundTracker(); _latch.Abandon(); LastRoundBreakdown = null; ClearLastRoundReportLines(); } if (num > 0) { WriteStatesToDisk(); } return num; } internal static void BeginRound() { if (IsEnabled()) { bool flag = SwitchToCurrentSave(); _round = new RoundTracker { RoundStartTime = Time.time, MoonRisk = GetCurrentMoonRisk(), MoonMultiplier = GetMoonMultiplier(GetCurrentMoonRisk()), StartRankIndex = (flag ? RankCatalog.GetRankIndex(CurrentRankXp) : (-1)) }; _latch.Begin(); LastRoundBreakdown = null; ClearLastRoundReportLines(); SnapshotPreexistingShipScrap(); SnapshotPreexistingShipBodies(); LogDebug($"Round {_latch.Sequence} started. risk={_round.MoonRisk} multiplier={_round.MoonMultiplier:0.##} banked={_round.Delivery.PreexistingInsideCount}"); } } internal static void AbandonUnfinalizedRound(string reason) { if (!_latch.Finalized && _latch.Active) { LogDebug($"Round {_latch.Sequence} abandoned without finalizing ({reason})."); _latch.Abandon(); _round = new RoundTracker(); LastRoundBreakdown = null; ClearLastRoundReportLines(); } } private static void SnapshotPreexistingShipScrap() { _round.Delivery.Reset(); GrabbableObject[] array = Object.FindObjectsOfType(); foreach (GrabbableObject val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.itemProperties == (Object)null) && val.itemProperties.isScrap && !(val is RagdollGrabbableObject) && IsInsideShip(val)) { _round.Delivery.MarkPreexistingInside(GetNetworkKey((Component)(object)val)); } } } private static void SnapshotPreexistingShipBodies() { RagdollGrabbableObject[] array = Object.FindObjectsOfType(true); foreach (RagdollGrabbableObject val in array) { if (!((Object)(object)val == (Object)null) && IsAboard(val)) { _round.Delivery.MarkPreexistingInside(GetNetworkKey((Component)(object)val)); } } } private static bool IsAboard(RagdollGrabbableObject body) { if ((Object)(object)body != (Object)null) { if (!IsInsideShip((GrabbableObject)(object)body)) { if ((Object)(object)body.ragdoll != (Object)null) { return body.ragdoll.isInShip; } return false; } return true; } return false; } internal static bool IsInsideShip(GrabbableObject item) { if ((Object)(object)item != (Object)null) { if (!item.isInShipRoom) { return item.isInElevator; } return true; } return false; } internal static void RecordItemBoundaryCrossing(PlayerControllerB handler, GrabbableObject item, bool wasInside) { if (!IsEnabled() || !_latch.Active || (Object)(object)item == (Object)null) { return; } bool flag = IsInsideShip(item); if (flag != wasInside) { if (DeliveryAttributionLedger.SuppressOutwardTransition(flag, (Object)(object)handler != (Object)null, (Object)(object)handler != (Object)null && handler.isPlayerDead, (Object)(object)handler != (Object)null && (handler.isInHangarShipRoom || handler.isInElevator))) { LogDebug($"Ignoring outward transition of '{GetItemName(item)}': client {handler.actualClientId} " + "is " + (handler.isPlayerDead ? "dead" : "still inside the ship") + ", so the item did not leave with them."); } else { RecordBoundaryCrossingCore(((Object)(object)handler != (Object)null && (Object)(object)item.playerHeldBy == (Object)(object)handler) ? handler.actualClientId : ulong.MaxValue, item, flag); } } } internal static void RecordAttributedBoundaryCrossing(ulong handlerClientId, GrabbableObject item, bool wasInside) { if (IsEnabled() && _latch.Active && !((Object)(object)item == (Object)null)) { bool flag = IsInsideShip(item); if (flag != wasInside) { RecordBoundaryCrossingCore(handlerClientId, item, flag); } } } private static void RecordBoundaryCrossingCore(ulong handlerClientId, GrabbableObject item, bool nowInside) { ulong networkKey = GetNetworkKey((Component)(object)item); _round.Delivery.RecordBoundaryCrossing(networkKey, handlerClientId, nowInside); LogDebug("Boundary crossing '" + GetItemName(item) + "' " + (nowInside ? "into" : "out of") + " the ship by " + ((handlerClientId == ulong.MaxValue) ? "an unattributed carrier." : $"client {handlerClientId}.")); } internal static void MarkLocalPlayerDeath() { if (_latch.Active && !_round.LocalPlayerDied) { _round.LocalPlayerDied = true; _round.LocalPlayerDeathTime = Time.time; LogDebug($"Local survival ended after {Mathf.Max(0f, _round.LocalPlayerDeathTime - _round.RoundStartTime):0.0}s."); } } internal static void RecordFacilityEntry(int playerObjectIndex) { if (!_latch.Active || _latch.Finalized) { return; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array != null && playerObjectIndex >= 0 && playerObjectIndex < array.Length) { PlayerControllerB val = array[playerObjectIndex]; if ((Object)(object)val != (Object)null) { _round.FacilityEntrants.Add(val.actualClientId); } } } internal static void RecordMainframeHacked(Component target) { if (!IsEnabled() || !Plugin.ProgressionConfig.MainframeHackEnabled.Value || !_latch.Active || _latch.Finalized || (Object)(object)target == (Object)null) { return; } ulong networkKey = GetNetworkKey(target); if (_round.HackedMainframes.Add(networkKey)) { int num = Mathf.Max(0, Plugin.ProgressionConfig.MainframeHackXp.Value); if (num > 0) { _round.MainframeHackXp = AddClamped(_round.MainframeHackXp, num); _round.AddReportSource("mainframe.hacked", ProgressionReportSourceKind.MainframeHack, string.Empty, 1, num); LogDebug($"Mainframe hack key={networkKey} xp={num}."); } } } internal static void RecordScrapPickup(GrabbableObject item) { if (!IsEnabled() || !Plugin.ProgressionConfig.ScrapPickupEnabled.Value || !_latch.Active || (Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null || !item.itemProperties.isScrap) { return; } PlayerControllerB playerHeldBy = item.playerHeldBy; ulong networkKey = GetNetworkKey((Component)(object)item); if ((Object)(object)playerHeldBy == (Object)null || _round.FirstScrapDiscovererByKey.ContainsKey(networkKey)) { return; } _round.FirstScrapDiscovererByKey[networkKey] = playerHeldBy.actualClientId; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && playerHeldBy.actualClientId == val.actualClientId) { int num = Mathf.CeilToInt((float)Mathf.Max(0, item.scrapValue) * Plugin.ProgressionConfig.ScrapPickupXpPerValue.Value); if (num > 0) { _round.ScrapPickupXp += num; _round.AddReportSource("scrap.discovered." + NormalizeReportKeyPart(GetItemName(item)), ProgressionReportSourceKind.ScrapDiscovered, GetItemName(item), 1, num); LogDebug($"Scrap first pickup '{GetItemName(item)}' value={item.scrapValue} xp={num}."); } } } internal static void RecordEnemyHit(EnemyAI enemy, PlayerControllerB playerWhoHit) { if (IsEnabled() && Plugin.ProgressionConfig.MonsterKillEnabled.Value && _latch.Active && !((Object)(object)enemy == (Object)null) && !((Object)(object)playerWhoHit == (Object)null)) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)playerWhoHit != (Object)(object)val)) { _round.LastEnemyHitByLocalPlayer[GetNetworkKey((Component)(object)enemy)] = Time.time; } } } internal static void RecordEnemyKilled(EnemyAI enemy) { if (!IsEnabled() || !Plugin.ProgressionConfig.MonsterKillEnabled.Value || !_latch.Active || (Object)(object)enemy == (Object)null) { return; } ulong networkKey = GetNetworkKey((Component)(object)enemy); if (_round.KilledEnemies.Add(networkKey) && _round.LastEnemyHitByLocalPlayer.TryGetValue(networkKey, out var value) && !(Time.time - value > Mathf.Max(1f, Plugin.ProgressionConfig.KillAttributionWindowSeconds.Value))) { int enemyKillXp = GetEnemyKillXp(enemy); if (enemyKillXp > 0) { _round.MonsterKillXp += enemyKillXp; _round.AddReportSource("monster.killed." + NormalizeReportKeyPart(GetEnemyName(enemy)), ProgressionReportSourceKind.MonsterKill, GetEnemyName(enemy), 1, enemyKillXp); LogDebug($"Enemy kill '{GetEnemyName(enemy)}' xp={enemyKillXp}."); } } } internal static int GetContractCompletionXp(string contractType) { ProgressionSettings progressionConfig = Plugin.ProgressionConfig; if (progressionConfig == null || !progressionConfig.IsContractSourceEnabled("ContractCompleted")) { return 0; } return ProgressionEconomyMath.ComputeContractCompletionXp(RankCatalog.GetRankWidth(ResolveCompletionRankIndex()), progressionConfig.ContractCompletionRankWidthFraction.Value, progressionConfig.GetContractCompletedMultiplier(contractType)); } private static int ResolveCompletionRankIndex() { if (_round.StartRankIndex >= 0) { return _round.StartRankIndex; } bool num = SwitchToCurrentSave(); int rankIndex = RankCatalog.GetRankIndex(CurrentRankXp); if (num) { _round.StartRankIndex = rankIndex; LogDebug($"Completion rank pinned late at rank index {rankIndex} (round start had no resolvable save)."); } return rankIndex; } internal static bool AddContractXp(string key, string label, int amount, bool oncePerRound) { return AddContractXp(key, label, amount, oncePerRound, null); } internal static bool AddContractXp(string key, string label, int amount, bool oncePerRound, string eventKind) { if (IsEnabled()) { ProgressionSettings progressionConfig = Plugin.ProgressionConfig; if (progressionConfig != null && progressionConfig.IsContractSourceEnabled(eventKind) && _latch.Active && amount > 0) { string text = (string.IsNullOrWhiteSpace(key) ? label : key); if (oncePerRound && !_round.ContractXpKeys.Add(text)) { return false; } _round.ContractXp += amount; LogDebug($"Contract XP '{label ?? text}' +{amount}."); return true; } } return false; } internal static void AddCappedContractXp(string key, string label, int xpPerCredit, string capBucket, int maxPerRound) { AddCappedContractXp(key, label, xpPerCredit, capBucket, maxPerRound, null); } internal static void AddCappedContractXp(string key, string label, int xpPerCredit, string capBucket, int maxPerRound, string eventKind) { string text = (string.IsNullOrWhiteSpace(key) ? label : key); if (!string.IsNullOrWhiteSpace(text)) { string text2 = capBucket ?? string.Empty; _round.CappedContractCredits.TryGetValue(text2, out var value); int num = ProgressionEconomyMath.ComputeCappedRepeatXp(value, maxPerRound, xpPerCredit); if (num <= 0) { LogDebug($"Contract XP '{label ?? text}' declined: bucket '{text2}' at {value}/{maxPerRound}."); } else if (AddContractXp(text, label, num, oncePerRound: true, eventKind)) { _round.CappedContractCredits[text2] = value + 1; LogDebug($"Contract XP '{label ?? text}' is {value + 1}/{maxPerRound} in '{text2}'."); } } } internal static RoundXpBreakdown FinalizeRound(int scrapCollected) { if (LastRoundBreakdown != null && _latch.Finalized) { return LastRoundBreakdown; } if (!IsEnabled()) { LastRoundBreakdown = BuildEmptyBreakdown(); ClearLastRoundReportLines(); return LastRoundBreakdown; } SwitchToCurrentSave(); if (!_latch.TryBeginFinalize(out var recoveredMissedStart)) { return LastRoundBreakdown ?? BuildEmptyBreakdown(); } if (recoveredMissedStart) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Progression] FinalizeRound ran without a round start " + $"(sequence={_latch.Sequence}, moon={GetCurrentMoonRisk()}, scrapCollected={scrapCollected}, " + "host=" + (GameNetworkManager.Instance?.isHostingGame.ToString() ?? "?") + "). Every per-round recorder was inactive, so this payout is incomplete — the RoundLifecycle.RoundStarted hook did not fire for this peer.")); } _round.RoundStartTime = Time.time; _round.MoonRisk = GetCurrentMoonRisk(); _round.MoonMultiplier = GetMoonMultiplier(_round.MoonRisk); _round.StartRankIndex = RankCatalog.GetRankIndex(CurrentRankXp); } _round.ScrapDeliveredXp = ComputeLocalDeliveredScrapXp(); _round.BodyRetrievalXp = ComputeLocalBodyRetrievalXp(); _round.SurvivalXp = ComputeSurvivalXp(); _round.ClutchXp = ComputeClutchXp(); int num = RankCatalog.ClampXp(_state.RankXp); int rankIndex = RankCatalog.GetRankIndex(num); int num2 = SumPositive(_round.ScrapPickupXp, _round.ScrapDeliveredXp, _round.MonsterKillXp, _round.SurvivalXp, _round.MainframeHackXp, _round.ClutchXp, _round.ContractXp, _round.BodyRetrievalXp); int num3 = ProgressionEconomyMath.ScaleContractXp(_round.ContractXp, _round.MoonMultiplier); int num4 = ProgressionEconomyMath.ScaleRiskXp(_round.BodyRetrievalXp, _round.MoonMultiplier); int num5 = ProgressionEconomyMath.ComputeRoundAwardedXp(_round.ScrapPickupXp, _round.ScrapDeliveredXp, _round.MonsterKillXp, _round.SurvivalXp, _round.MainframeHackXp, _round.ClutchXp, _round.ContractXp, _round.BodyRetrievalXp, _round.MoonMultiplier); int num6 = RankCatalog.ClampXp(num + num5); int rankIndex2 = RankCatalog.GetRankIndex(num6); int num7 = Mathf.Max(0, rankIndex2 - rankIndex); int tokenGrantForRankRange = RankCatalog.GetTokenGrantForRankRange(rankIndex + 1, rankIndex2); tokenGrantForRankRange += num7 * OverachieverUpgrade.GetBonusTokensPerRank(); _state.RankXp = num6; _state.UpgradeCurrency = Mathf.Max(0, _state.UpgradeCurrency + tokenGrantForRankRange); LastRoundBreakdown = new RoundXpBreakdown { RoundSequence = _latch.Sequence, OldXp = num, NewXp = num6, ScrapPickupXp = _round.ScrapPickupXp, ScrapDeliveredXp = _round.ScrapDeliveredXp, MonsterKillXp = _round.MonsterKillXp, SurvivalXp = _round.SurvivalXp, MainframeHackXp = _round.MainframeHackXp, ClutchXp = _round.ClutchXp, ContractXp = _round.ContractXp, ContractXpAwarded = num3, BodyRetrievalXp = _round.BodyRetrievalXp, BodyRetrievalXpAwarded = num4, MoonMultiplier = _round.MoonMultiplier, MoonRisk = _round.MoonRisk, RawTotal = num2, AwardedTotal = num5, OldRankIndex = rankIndex, NewRankIndex = rankIndex2, RanksGained = num7, CurrencyGranted = tokenGrantForRankRange }; AddFinalizedReportSources(num4, num3); LastRoundReportSources = _round.BuildReportSources(); LastRoundReportSequence = LastRoundBreakdown.RoundSequence; _latch.CompleteFinalize(); Save(); SyncVanillaRank(); ProgressionRankSync.PublishLocalRank(); LogDebug($"Round {_latch.Sequence} finalized raw={num2} awarded={num5} old={num} new={num6} ranks={num7} currency={tokenGrantForRankRange}."); return LastRoundBreakdown; } internal static void SyncVanillaRank() { try { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null)) { HUDManager.Instance.SyncPlayerLevelServerRpc((int)val.playerClientId, RankCatalog.GetVanillaRankIndex(CurrentRankXp), true); } } catch (Exception ex) { LogDebug("Vanilla rank sync skipped: " + ex.Message); } } private static void ClearLastRoundReportLines() { LastRoundReportSources = Array.Empty(); LastRoundReportSequence = 0; } internal static bool TryGetLastRoundReportSources(out IReadOnlyList sources) { sources = Array.Empty(); RoundXpBreakdown lastRoundBreakdown = LastRoundBreakdown; if (lastRoundBreakdown == null || LastRoundReportSequence <= 0 || lastRoundBreakdown.RoundSequence != LastRoundReportSequence || LastRoundReportSources == null || LastRoundReportSources.Count == 0) { return false; } sources = LastRoundReportSources; return true; } internal static string BuildPerformanceReportLine() { RoundXpBreakdown lastRoundBreakdown = LastRoundBreakdown; if (lastRoundBreakdown == null) { return string.Empty; } return $"XP +{lastRoundBreakdown.AwardedTotal} FOUND +{lastRoundBreakdown.ScrapPickupXp} | SCRAP +{lastRoundBreakdown.ScrapDeliveredXp} | KILLS +{lastRoundBreakdown.MonsterKillXp} | SURV +{lastRoundBreakdown.SurvivalXp} | HACK +{lastRoundBreakdown.MainframeHackXp} | CLUTCH +{lastRoundBreakdown.ClutchXp} | BODIES +{lastRoundBreakdown.BodyRetrievalXpAwarded} ({lastRoundBreakdown.BodyRetrievalXp} x{lastRoundBreakdown.MoonMultiplier:0.##}) | CONTRACT +{lastRoundBreakdown.ContractXpAwarded} ({lastRoundBreakdown.ContractXp} x{lastRoundBreakdown.MoonMultiplier:0.##})"; } private static RoundXpBreakdown BuildEmptyBreakdown() { int num = _state?.RankXp ?? 0; int rankIndex = RankCatalog.GetRankIndex(num); return new RoundXpBreakdown { OldXp = num, NewXp = num, OldRankIndex = rankIndex, NewRankIndex = rankIndex, MoonRisk = GetCurrentMoonRisk(), MoonMultiplier = GetMoonMultiplier(GetCurrentMoonRisk()) }; } private static void AddFinalizedReportSources(int bodyAwarded, int contractAwarded) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; bool flag = (Object)(object)val != (Object)null && !val.isPlayerDead; if (_round.SurvivalXp > 0) { _round.AddReportSource("survival", ProgressionReportSourceKind.Survival, flag ? "extracted" : "timed", _round.SurvivalMinutesForReport, _round.SurvivalXp); } if (bodyAwarded > 0 && _round.RetrievedBodyCount > 0) { string subject = ((_round.RetrievedBodyCount == 1 && _round.RetrievedBodyNames.Count == 1) ? _round.RetrievedBodyNames[0] : string.Empty); _round.AddReportSource("body.retrieved", ProgressionReportSourceKind.BodyRetrieval, subject, _round.RetrievedBodyCount, bodyAwarded); } if (_round.ClutchXp > 0) { _round.AddReportSource("survival.clutch", ProgressionReportSourceKind.Clutch, string.Empty, 1, _round.ClutchXp); } if (contractAwarded > 0) { _round.AddReportSource("contract.objectives", ProgressionReportSourceKind.Contract, "Completed contract work", 1, contractAwarded); } } private static int ComputeSurvivalXp() { bool value = Plugin.ProgressionConfig.SurvivalTimeEnabled.Value; bool value2 = Plugin.ProgressionConfig.SurvivalExtractBonusEnabled.Value; if (!value && !value2) { return 0; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; int num = 0; if (value) { float num2 = (_round.LocalPlayerDied ? _round.LocalPlayerDeathTime : Time.time); float num3 = Mathf.Max(0f, num2 - _round.RoundStartTime); float num4 = Mathf.Max(1, Plugin.ProgressionConfig.SurvivalMaxMinutesPerRound.Value); float num5 = Mathf.Min(num3 / 60f, num4); _round.SurvivalMinutesForReport = Mathf.Max(1, Mathf.CeilToInt(num5)); num = Mathf.FloorToInt(num5 * (float)Mathf.Max(0, Plugin.ProgressionConfig.SurvivalXpPerMinute.Value)); } if (value2 && (Object)(object)val != (Object)null && !val.isPlayerDead) { _round.SurvivalMinutesForReport = Mathf.Max(1, _round.SurvivalMinutesForReport); num += Mathf.Max(0, Plugin.ProgressionConfig.SurvivalExtractBonus.Value); } return Mathf.Max(0, num); } private static int ComputeClutchXp() { if (!Plugin.ProgressionConfig.ClutchExtractEnabled.Value) { return 0; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return 0; } bool localEnteredFacility = _round.FacilityEntrants.Contains(val.actualClientId); bool localExtractedAlive = !val.isPlayerDead; int num = 0; int num2 = 0; foreach (ulong facilityEntrant in _round.FacilityEntrants) { if (facilityEntrant != val.actualClientId) { num++; PlayerControllerB val2 = FindPlayerByActualClientId(facilityEntrant); if ((Object)(object)val2 != (Object)null && val2.isPlayerDead) { num2++; } } } if (!ClutchXpPolicy.IsEligible(localEnteredFacility, localExtractedAlive, num, num2)) { return 0; } int num3 = Mathf.Max(0, Plugin.ProgressionConfig.ClutchExtractXp.Value); LogDebug($"Clutch extraction credited: entrants={num + 1} " + $"deadOthers={num2} xp={num3}."); return num3; } private static int ComputeLocalDeliveredScrapXp() { if (!Plugin.ProgressionConfig.ScrapDeliveredEnabled.Value) { return 0; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return 0; } int num = 0; HashSet hashSet = new HashSet(); List list = new List(); Dictionary dictionary = new Dictionary(StringComparer.Ordinal); GrabbableObject[] array = Object.FindObjectsOfType(); foreach (GrabbableObject val2 in array) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.itemProperties == (Object)null || !val2.itemProperties.isScrap || val2 is RagdollGrabbableObject || !IsInsideShip(val2)) { continue; } ulong networkKey = GetNetworkKey((Component)(object)val2); if (hashSet.Add(networkKey) && _round.Delivery.ShouldPayDelivery(networkKey, insideAtRoundEnd: true, val.actualClientId)) { int right = Mathf.Max(0, val2.scrapValue); num = AddClamped(num, right); string itemName = GetItemName(val2); string key = NormalizeReportKeyPart(itemName); if (!dictionary.TryGetValue(key, out var value)) { value = new DeliveredScrapReportGroup(key, itemName); dictionary.Add(key, value); list.Add(value); } value.Count = AddClamped(value.Count, 1); value.Value = AddClamped(value.Value, right); } } int num2 = Mathf.CeilToInt((float)num * Mathf.Max(0f, Plugin.ProgressionConfig.ScrapDeliveredXpPerValue.Value)); num2 = Mathf.Max(0, num2); if (num2 > 0 && list.Count > 0) { int[] array2 = new int[list.Count]; for (int j = 0; j < list.Count; j++) { array2[j] = list[j].Value; } int[] array3 = ProgressionEconomyMath.DistributeScaledXp(array2, num2); for (int k = 0; k < list.Count; k++) { if (array3[k] > 0) { _round.AddReportSource("scrap.delivered." + list[k].Key, ProgressionReportSourceKind.ScrapDelivered, list[k].Name, list[k].Count, array3[k]); } } } LogDebug($"Individual delivered scrap value={num} xp={num2}."); return num2; } private static int ComputeLocalBodyRetrievalXp() { if (!Plugin.ProgressionConfig.BodyRetrievalEnabled.Value) { return 0; } int num = Mathf.Max(0, Plugin.ProgressionConfig.BodyRetrievalXp.Value); if (num <= 0) { return 0; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return 0; } int num2 = 0; HashSet hashSet = new HashSet(); RagdollGrabbableObject[] array = Object.FindObjectsOfType(); foreach (RagdollGrabbableObject val2 in array) { if ((Object)(object)val2 == (Object)null || (Object)(object)val2.ragdoll == (Object)null) { continue; } ulong networkKey = GetNetworkKey((Component)(object)val2); ulong ownerClientId; bool flag = TryResolveBodyOwner(val2, out ownerClientId); if (DeliveryAttributionLedger.ShouldPayBodyRetrieval(_round.Delivery.ShouldPayDelivery(networkKey, insideAtRoundEnd: true, val.actualClientId), IsAboard(val2), val2.ragdoll.deactivated, flag, flag && ownerClientId == val.actualClientId) && hashSet.Add(networkKey)) { num2++; _round.RetrievedBodyCount++; string text = ResolveBodyOwnerName(val2, ownerClientId); if (!string.IsNullOrWhiteSpace(text)) { _round.RetrievedBodyNames.Add(text); } LogDebug($"Body retrieval credited for corpse key {networkKey} (body id {val2.bodyID})."); } } return num2 * num; } private static bool TryResolveBodyOwner(RagdollGrabbableObject body, out ulong ownerClientId) { ownerClientId = 0uL; if ((Object)(object)body == (Object)null) { return false; } PlayerControllerB val = (((Object)(object)body.ragdoll != (Object)null) ? body.ragdoll.playerScript : null); if ((Object)(object)val == (Object)null) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null || body.bodyID < 0 || body.bodyID >= array.Length) { return false; } val = array[body.bodyID]; } if ((Object)(object)val == (Object)null) { return false; } ownerClientId = val.actualClientId; return true; } private static string ResolveBodyOwnerName(RagdollGrabbableObject body, ulong ownerClientId) { PlayerControllerB val = (((Object)(object)body?.ragdoll != (Object)null) ? body.ragdoll.playerScript : null); if ((Object)(object)val == (Object)null) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array != null) { for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].actualClientId == ownerClientId) { val = array[i]; break; } } } } string text = (((Object)(object)val != (Object)null) ? val.playerUsername : null); if (!string.IsNullOrWhiteSpace(text)) { return text.Trim(); } return string.Empty; } private static int GetEnemyKillXp(EnemyAI enemy) { int num = 1; try { if ((Object)(object)enemy.enemyType != (Object)null) { num = Mathf.Max(1, Mathf.RoundToInt(enemy.enemyType.PowerLevel)); } } catch { num = 1; } return Mathf.Clamp(num * Mathf.Max(1, Plugin.ProgressionConfig.MonsterKillXpPerPower.Value), Mathf.Max(0, Plugin.ProgressionConfig.MonsterKillMinXp.Value), Mathf.Max(0, Plugin.ProgressionConfig.MonsterKillMaxXp.Value)); } private static string GetCurrentMoonRisk() { string text = StartOfRound.Instance?.currentLevel?.riskLevel; if (string.IsNullOrWhiteSpace(text)) { return "C"; } return text.Trim().ToUpperInvariant(); } private static float GetMoonMultiplier(string risk) { if (string.IsNullOrWhiteSpace(risk)) { return 1f; } risk = risk.Trim().ToUpperInvariant(); if (risk.StartsWith("S", StringComparison.Ordinal)) { return Mathf.Max(0f, Plugin.ProgressionConfig.RiskMultiplierS.Value); } if (risk.StartsWith("A", StringComparison.Ordinal)) { return Mathf.Max(0f, Plugin.ProgressionConfig.RiskMultiplierA.Value); } if (risk.StartsWith("B", StringComparison.Ordinal)) { return Mathf.Max(0f, Plugin.ProgressionConfig.RiskMultiplierB.Value); } if (risk.StartsWith("D", StringComparison.Ordinal)) { return Mathf.Max(0f, Plugin.ProgressionConfig.RiskMultiplierD.Value); } return Mathf.Max(0f, Plugin.ProgressionConfig.RiskMultiplierC.Value); } private static bool IsEnabled() { ProgressionSettings progressionConfig = Plugin.ProgressionConfig; if (progressionConfig == null) { return false; } return progressionConfig.Enabled?.Value == true; } private static void WriteStatesToDisk() { Directory.CreateDirectory(SaveDir); List list = new List(States.Count); foreach (KeyValuePair state in States) { if (!string.IsNullOrWhiteSpace(state.Key)) { ProgressionState progressionState = state.Value ?? new ProgressionState(); list.Add($"{state.Key}|{RankCatalog.ClampXp(progressionState.RankXp)}|{Mathf.Max(0, progressionState.UpgradeCurrency)}|{EncodeExternalGrantIds(progressionState.ExternalTokenGrantIds)}|{EncodeExternalGrantIds(progressionState.CompletedTokenSpendIds)}"); } } SaveDataFile.WriteAllLinesAtomic(SavePath, list); } private static string EncodeExternalGrantIds(IEnumerable actionIds) { if (actionIds == null) { return string.Empty; } return string.Join(",", from id in actionIds.Where((string id) => !string.IsNullOrWhiteSpace(id)).OrderBy((string id) => id, StringComparer.Ordinal) select Convert.ToBase64String(Encoding.UTF8.GetBytes(id))); } private static IEnumerable DecodeExternalGrantIds(string encoded) { if (string.IsNullOrWhiteSpace(encoded)) { yield break; } string[] values = encoded.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < values.Length; i++) { string text; try { text = Encoding.UTF8.GetString(Convert.FromBase64String(values[i])); } catch { continue; } if (!string.IsNullOrWhiteSpace(text)) { yield return text.Trim(); } } } private static int ReservedCurrencyForCurrentSave() { if (string.IsNullOrWhiteSpace(_currentSaveKey)) { return 0; } long num = 0L; foreach (TokenReservation value in TokenReservations.Values) { if (string.Equals(value.SaveKey, _currentSaveKey, StringComparison.OrdinalIgnoreCase)) { num += value.Amount; } } return (int)Math.Min(2147483647L, num); } private static string NormalizeTransactionId(string value) { value = (value ?? string.Empty).Trim(); if (value.Length > 128) { return value.Substring(0, 128); } return value; } private static void TrimCompletedTokenSpends(HashSet ids) { if (ids != null && ids.Count > 256) { string[] array = ids.OrderBy((string value) => value, StringComparer.Ordinal).Take(ids.Count - 256).ToArray(); foreach (string item in array) { ids.Remove(item); } } } private static PlayerControllerB FindPlayerByActualClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.actualClientId == clientId) { return val; } } return null; } private static int AddClamped(int left, int right) { long num = (long)Math.Max(0, left) + (long)Math.Max(0, right); if (num < int.MaxValue) { return (int)num; } return int.MaxValue; } private static int SumPositive(params int[] values) { long num = 0L; if (values != null) { for (int i = 0; i < values.Length; i++) { if (values[i] > 0) { num += values[i]; if (num >= int.MaxValue) { return int.MaxValue; } } } } return (int)num; } private static string NormalizeReportKeyPart(string value) { value = (string.IsNullOrWhiteSpace(value) ? "unknown" : value.Trim().ToLowerInvariant()); StringBuilder stringBuilder = new StringBuilder(value.Length); bool flag = false; foreach (char c in value) { if (char.IsLetterOrDigit(c)) { if (flag && stringBuilder.Length > 0) { stringBuilder.Append('-'); } stringBuilder.Append(c); flag = false; } else { flag = true; } } if (stringBuilder.Length != 0) { return stringBuilder.ToString(); } return "unknown"; } private static ulong GetNetworkKey(Component component) { return NetworkObjectKey.For(component); } private static string GetItemName(GrabbableObject item) { return item?.itemProperties?.itemName ?? ((item != null) ? ((Object)item).name : null) ?? "scrap"; } private static string GetEnemyName(EnemyAI enemy) { object obj = enemy?.enemyType?.enemyName; if (obj == null) { if (enemy == null) { obj = null; } else { GameObject gameObject = ((Component)enemy).gameObject; obj = ((gameObject != null) ? ((Object)gameObject).name : null); } if (obj == null) { obj = "enemy"; } } return (string)obj; } private static void LogDebug(string message) { ProgressionSettings progressionConfig = Plugin.ProgressionConfig; if (progressionConfig != null && progressionConfig.DebugLogging?.Value == true) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Progression] " + message)); } } } } [HarmonyPatch] internal static class ProgressionOrbitNameTags { private sealed class TagView { private const float PaddingX = 14f; private const float PaddingY = 8f; private readonly PlayerControllerB _player; private readonly GameObject _root; private readonly RectTransform _rect; private readonly RectTransform _backdropRect; private readonly TextMeshProUGUI _text; private string _lastUsername; private string _lastRank; internal bool IsAlive { get { if ((Object)(object)_root != (Object)null && (Object)(object)_text != (Object)null) { return (Object)(object)_player != (Object)null; } return false; } } private TagView(PlayerControllerB player, GameObject root, RectTransform rect, RectTransform backdropRect, TextMeshProUGUI text) { _player = player; _root = root; _rect = rect; _backdropRect = backdropRect; _text = text; } internal static TagView Create(PlayerControllerB player) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_004a: 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_0064: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_018e: 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) if ((Object)(object)player == (Object)null) { return null; } if (!TryResolveFont(out var font, out var material)) { return null; } GameObject val = new GameObject("Y4NGZ_OrbitNameTag"); val.transform.SetParent(((Component)player).transform, false); val.transform.localPosition = new Vector3(0f, 2.65f, 0f); val.transform.localScale = Vector3.one * 0.0105f; Canvas obj = val.AddComponent(); obj.renderMode = (RenderMode)2; obj.sortingOrder = 80; obj.additionalShaderChannels = (AdditionalCanvasShaderChannels)25; RectTransform component = val.GetComponent(); component.sizeDelta = new Vector2(260f, 62f); GameObject val2 = new GameObject("Background"); val2.transform.SetParent(val.transform, false); RectTransform val3 = val2.AddComponent(); val3.anchorMin = new Vector2(0.5f, 0.5f); val3.anchorMax = new Vector2(0.5f, 0.5f); val3.pivot = new Vector2(0.5f, 0.5f); val3.anchoredPosition = Vector2.zero; val3.sizeDelta = Vector2.zero; Image obj2 = val2.AddComponent(); obj2.sprite = null; ((Graphic)obj2).color = new Color(0.05f, 0.05f, 0.06f, 0.55f); ((Graphic)obj2).raycastTarget = false; GameObject val4 = new GameObject("Label"); val4.transform.SetParent(val.transform, false); RectTransform obj3 = val4.AddComponent(); obj3.anchorMin = Vector2.zero; obj3.anchorMax = Vector2.one; obj3.offsetMin = Vector2.zero; obj3.offsetMax = Vector2.zero; TextMeshProUGUI val5 = val4.AddComponent(); ((TMP_Text)val5).font = font; if ((Object)(object)material != (Object)null) { ((TMP_Text)val5).fontSharedMaterial = material; } ((TMP_Text)val5).alignment = (TextAlignmentOptions)514; ((TMP_Text)val5).enableWordWrapping = false; ((TMP_Text)val5).overflowMode = (TextOverflowModes)0; ((TMP_Text)val5).fontSize = 17f; ((TMP_Text)val5).richText = true; ((Graphic)val5).raycastTarget = false; ((TMP_Text)val5).characterSpacing = 0f; return new TagView(player, val, component, val3, val5); } internal void SetText(string username, string rank) { if (!((Object)(object)_text == (Object)null) && (!string.Equals(_lastUsername, username, StringComparison.Ordinal) || !string.Equals(_lastRank, rank, StringComparison.Ordinal))) { _lastUsername = username; _lastRank = rank; ((TMP_Text)_text).text = "" + EscapeRichText(username) + "\n" + EscapeRichText(rank) + ""; ResizeBackdrop(); } } private void ResizeBackdrop() { //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_0037: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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) if (!((Object)(object)_backdropRect == (Object)null) && !((Object)(object)_text == (Object)null)) { ((TMP_Text)_text).ForceMeshUpdate(false, false); Vector2 val = ((TMP_Text)_text).GetRenderedValues(false); if (val.x <= 0f || val.y <= 0f) { val = ((TMP_Text)_text).GetPreferredValues(); } _backdropRect.sizeDelta = new Vector2(val.x + 28f, val.y + 16f); } } internal void UpdateTransform(Camera camera) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_root == (Object)null) && !((Object)(object)_player == (Object)null) && !((Object)(object)camera == (Object)null)) { SuppressVanillaBillboard(); _root.transform.localPosition = new Vector3(0f, 2.65f, 0f); Vector3 val = _root.transform.position - ((Component)camera).transform.position; if (((Vector3)(ref val)).sqrMagnitude > 0.001f) { _root.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } if ((Object)(object)_rect != (Object)null) { float num = Mathf.Clamp(Vector3.Distance(((Component)camera).transform.position, _root.transform.position) / 16f, 0.75f, 1.25f); _root.transform.localScale = Vector3.one * (0.0105f * num); } } } private void SuppressVanillaBillboard() { if ((Object)(object)_player.usernameAlpha != (Object)null) { _player.usernameAlpha.alpha = 0f; } Canvas usernameCanvas = _player.usernameCanvas; if ((Object)(object)usernameCanvas != (Object)null && ((Component)usernameCanvas).gameObject.activeSelf) { ((Component)usernameCanvas).gameObject.SetActive(false); } } internal void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private static string EscapeRichText(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } return value.Replace("<", "<").Replace(">", ">"); } } private const float HeightAbovePlayer = 2.65f; private const float RefreshInterval = 0.25f; private static readonly Dictionary TagsByClientId = new Dictionary(); private static float _nextRefreshTime; private static TMP_FontAsset _fontCache; private static Material _fontMaterialCache; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)__instance == (Object)null || (Object)(object)val == (Object)null || (Object)(object)__instance != (Object)(object)val) { return; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || !IsInOrbit(instance)) { ClearAll(); return; } ProgressionRankSync.RegisterNetworkHandlers(); if (Time.unscaledTime >= _nextRefreshTime) { _nextRefreshTime = Time.unscaledTime + 0.25f; ProgressionRankSync.PublishLocalRank(); ProgressionRankSync.RequestAllRanksFromServer(); RefreshTagSet(instance, val); } UpdateTagTransforms(val); } private static bool IsInOrbit(StartOfRound round) { if (round.inShipPhase) { return !round.shipHasLanded; } return false; } internal static void OnRoundStarted() { ClearAll(); ProgressionRankSync.RegisterNetworkHandlers(); ProgressionRankSync.PublishLocalRank(); ProgressionRankSync.RequestAllRanksFromServer(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void OnEndOfGame() { ClearAll(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void OnDisconnect() { ClearAll(); ProgressionRankSync.Clear(); } private static void RefreshTagSet(StartOfRound round, PlayerControllerB local) { if (round?.allPlayerScripts == null) { return; } HashSet hashSet = new HashSet(); for (int i = 0; i < round.allPlayerScripts.Length; i++) { PlayerControllerB val = round.allPlayerScripts[i]; if (ShouldShowTagFor(val, local)) { ulong actualClientId = val.actualClientId; TagView orCreateTag = GetOrCreateTag(val); if (orCreateTag != null) { hashSet.Add(actualClientId); string name = RankCatalog.GetRank(ProgressionRankSync.GetRankXpForPlayer(val)).Name; string username = (string.IsNullOrWhiteSpace(val.playerUsername) ? "Employee" : val.playerUsername); orCreateTag.SetText(username, name); } } } List list = null; foreach (ulong key in TagsByClientId.Keys) { if (!hashSet.Contains(key)) { if (list == null) { list = new List(); } list.Add(key); } } if (list == null) { return; } for (int j = 0; j < list.Count; j++) { if (TagsByClientId.TryGetValue(list[j], out var value)) { value.Destroy(); } TagsByClientId.Remove(list[j]); } } private static void UpdateTagTransforms(PlayerControllerB local) { Camera val = local?.gameplayCamera; if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val == (Object)null) { return; } foreach (TagView value in TagsByClientId.Values) { value.UpdateTransform(val); } } private static bool ShouldShowTagFor(PlayerControllerB player, PlayerControllerB local) { if ((Object)(object)player == (Object)null || (Object)(object)local == (Object)null || (Object)(object)player == (Object)(object)local) { return false; } if (!player.isPlayerControlled || player.isPlayerDead) { return false; } if ((Object)(object)((Component)player).gameObject != (Object)null) { return ((Component)player).gameObject.activeInHierarchy; } return false; } private static TagView GetOrCreateTag(PlayerControllerB player) { ulong actualClientId = player.actualClientId; if (TagsByClientId.TryGetValue(actualClientId, out var value) && value != null && value.IsAlive) { return value; } TagView tagView = TagView.Create(player); if (tagView != null) { TagsByClientId[actualClientId] = tagView; } return tagView; } private static void ClearAll() { foreach (TagView value in TagsByClientId.Values) { value?.Destroy(); } TagsByClientId.Clear(); } private static bool TryResolveFont(out TMP_FontAsset font, out Material material) { if ((Object)(object)_fontCache != (Object)null) { font = _fontCache; material = _fontMaterialCache; return true; } font = null; material = null; HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null) { return false; } TMP_Text val = null; val = (TMP_Text)(((Object)(object)instance.playerLevelText != (Object)null && (Object)(object)((TMP_Text)instance.playerLevelText).font != (Object)null) ? instance.playerLevelText : ((!((Object)(object)instance.clockNumber != (Object)null) || !((Object)(object)((TMP_Text)instance.clockNumber).font != (Object)null)) ? ((object)((Component)instance).GetComponentInChildren(true)) : ((object)instance.clockNumber))); if ((Object)(object)val == (Object)null || (Object)(object)val.font == (Object)null) { return false; } _fontCache = val.font; _fontMaterialCache = val.fontSharedMaterial; font = _fontCache; material = _fontMaterialCache; return true; } } internal static class ProgressionPatches { [HarmonyPatch(typeof(StartOfRound), "Start")] internal static class StartOfRoundStartPatch { [HarmonyPostfix] private static void Postfix() { ProgressionManager.SwitchToCurrentSave(); EmployeeStatistics.SwitchToCurrentSave(); } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] internal static class PlayerRuntimeStatisticsPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)__instance == (Object)(object)val) { EmployeeStatistics.UpdateRuntime(__instance, Time.deltaTime); } } } [HarmonyPatch(typeof(EntranceTeleport), "TeleportPlayerClientRpc")] internal static class FacilityEntryPatch { [HarmonyPostfix] private static void Postfix(EntranceTeleport __instance, int playerObj) { if ((Object)(object)__instance != (Object)null && __instance.isEntranceToBuilding) { ProgressionManager.RecordFacilityEntry(playerObj); } } } [HarmonyPatch(typeof(GameNetworkManager), "ResetSavedGameValues")] internal static class ResetSavePatch { [HarmonyPrefix] private static void Prefix(GameNetworkManager __instance, out string __state) { __state = null; if ((Object)(object)__instance != (Object)null && __instance.isHostingGame) { SaveKey.TryGetCurrentExistingOrSlot(out __state); } } [HarmonyPostfix] private static void Postfix(string __state) { if (!string.IsNullOrWhiteSpace(__state)) { SaveDataLifecycle.DeleteSave(__state, "vanilla save-value reset"); } } } [HarmonyPatch(typeof(GrabbableObject), "GrabItem")] internal static class ScrapPickupPatch { [HarmonyPostfix] private static void Postfix(GrabbableObject __instance) { ProgressionManager.RecordScrapPickup(__instance); EmployeeStatistics.RecordItemGrabbed(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "SetItemInElevator")] internal static class ItemBoundaryCrossingPatch { [HarmonyPrefix] private static void Prefix(GrabbableObject gObject, out bool __state) { __state = ProgressionManager.IsInsideShip(gObject); } [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance, GrabbableObject gObject, bool __state) { ProgressionManager.RecordItemBoundaryCrossing(__instance, gObject, __state); } } [HarmonyPatch(typeof(PlayerControllerB), "SetHeldObjectInShip")] internal static class HeldObjectBoundaryCrossingPatch { [HarmonyPrefix] private static void Prefix(GrabbableObject gObject, out bool __state) { __state = ProgressionManager.IsInsideShip(gObject); } [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance, GrabbableObject gObject, bool __state) { ProgressionManager.RecordItemBoundaryCrossing(__instance, gObject, __state); } } [HarmonyPatch(typeof(EnemyAI), "SetItemInElevatorNonPlayer")] internal static class EnemyItemBoundaryCrossingPatch { [HarmonyPrefix] private static void Prefix(GrabbableObject gObject, out bool __state) { __state = ProgressionManager.IsInsideShip(gObject); } [HarmonyPostfix] private static void Postfix(GrabbableObject gObject, bool __state) { ProgressionManager.RecordItemBoundaryCrossing(null, gObject, __state); } } [HarmonyPatch(typeof(EnemyAI), "HitEnemy")] internal static class EnemyHitPatch { [HarmonyPostfix] private static void Postfix(EnemyAI __instance, PlayerControllerB playerWhoHit) { ProgressionManager.RecordEnemyHit(__instance, playerWhoHit); EmployeeStatistics.RecordEnemyHit(__instance, playerWhoHit); } } [HarmonyPatch(typeof(EnemyAI), "KillEnemy")] internal static class EnemyKillPatch { [HarmonyPrefix] private static void Prefix(EnemyAI __instance, out bool __state) { __state = (Object)(object)__instance != (Object)null && !__instance.isEnemyDead; } [HarmonyPostfix] private static void Postfix(EnemyAI __instance, bool __state) { if (__state) { ProgressionManager.RecordEnemyKilled(__instance); EmployeeStatistics.RecordEnemyKilled(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] internal static class PlayerDeathPatch { [HarmonyPrefix] private static void Prefix(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)__instance != (Object)null && (Object)(object)val != (Object)null && (Object)(object)__instance == (Object)(object)val && !__instance.isPlayerDead) { ProgressionManager.MarkLocalPlayerDeath(); EmployeeStatistics.RecordDeath(); } } } [HarmonyPatch(typeof(HUDManager), "FillEndGameStats")] internal static class FillEndGameStatsPatch { [HarmonyPrefix] private static void Prefix(int scrapCollected) { ProgressionManager.FinalizeRound(scrapCollected); EmployeeStatistics.FinalizeRound(scrapCollected); } [HarmonyFinalizer] [HarmonyPriority(0)] [HarmonyAfter(new string[] { "com.elitemastereric.coroner", "Swaggies.BetterEXP" })] private static Exception Finalizer(HUDManager __instance, Exception __exception) { if (__exception == null) { ProgressionPerformanceReportUi.Apply(__instance); } return __exception; } } [HarmonyPatch(typeof(HUDManager), "SetPlayerLevel")] internal static class SetPlayerLevelPatch { [HarmonyPrefix] private static bool Prefix(HUDManager __instance) { RoundXpBreakdown log = ProgressionManager.LastRoundBreakdown ?? ProgressionManager.FinalizeRound(((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.scrapCollectedLastRound : 0); ProgressionXpBarUi.PrimeStartingValues(__instance, log); ProgressionXpBarUi.ShowRoundXp(__instance, log); return false; } } [HarmonyPatch] internal static class ContractProgressionEventPatch { private static bool Prepare() { return AccessTools.Method(ContractType("ContractProgressionEvents"), "Publish", (Type[])null, (Type[])null) != null; } private static MethodBase TargetMethod() { return AccessTools.Method(ContractType("ContractProgressionEvents"), "Publish", (Type[])null, (Type[])null); } [HarmonyPostfix] private static void Postfix(object __0) { if (__0 == null || !TryGetProperty(__0, "SchemaVersion", out var value) || value != 1 || !TryGetProperty(__0, "PlayerClientId", out var value2) || !TryGetProperty(__0, "EventId", out var value3) || string.IsNullOrWhiteSpace(value3)) { return; } string text = GetPropertyValue(__0, "Kind")?.ToString(); if (text == "PestControlCompleted" || text == "PestControlCapture") { int value4; bool flag = TryGetProperty(__0, "Count", out value4); EmployeeStatistics.ObservePestsTrapped(value3, value2, flag ? value4 : 0); } if (!IsLocalPlayer(value2)) { return; } if (!TryGetProperty(__0, "ContractType", out var value5) || string.IsNullOrWhiteSpace(value5)) { TryGetProperty(__0, "ContractId", out value5); } if (!TryGetProperty(__0, "SourceLabel", out var value6)) { value6 = null; } ProgressionSettings progressionConfig = Plugin.ProgressionConfig; string text2 = null; int maxPerRound = 0; if (text == null) { return; } int num; string label; switch (text.Length) { default: return; case 17: switch (text[13]) { default: return; case 'W': if (!(text == "DefuseCorrectWire")) { return; } num = Plugin.ProgressionConfig.DefuseCorrectWireXp.Value; label = "Correct Defuse wire"; break; case 'C': if (!(text == "DefuseCorrectCode")) { return; } num = Plugin.ProgressionConfig.DefuseCorrectCodeXp.Value; label = "Correct Defuse code"; EmployeeStatistics.RecordBombDefused(value3); break; case 'a': if (!(text == "SurveyDronePlaced")) { return; } num = progressionConfig.SurveyDronePlacedXp.Value; label = (string.IsNullOrWhiteSpace(value6) ? "Survey drone planted" : ("Survey drone planted (" + value6 + ")")); if (ContractEventAttribution.IsIndividuallyAttributed(value3, value2)) { EmployeeStatistics.RecordSurveyBeaconPlaced(value3); } break; case 'e': if (!(text == "ContractCompleted")) { return; } num = ProgressionManager.GetContractCompletionXp(value5); label = (string.IsNullOrWhiteSpace(value5) ? "Contract completed" : (value5 + " contract completed")); break; } break; case 20: switch (text[0]) { default: return; case 'W': { if (!(text == "WhistleblowerSighted")) { return; } num = progressionConfig.WhistleblowerDiscoveryXp.Value; label = ((TryGetProperty(__0, "Count", out var value13) && value13 > 0) ? $"Whistleblower sighting {value13}" : "Whistleblower sighted"); break; } case 'P': { if (!(text == "PestControlCompleted")) { return; } num = progressionConfig.PestControlCompletedXp.Value; label = ((TryGetProperty(__0, "Count", out var value12) && value12 > 1) ? $"Specimens contained ({value12})" : "Specimen contained"); break; } } break; case 24: switch (text[0]) { default: return; case 'W': if (!(text == "WhistleblowerNeutralized")) { return; } num = progressionConfig.WhistleblowerKillXp.Value; label = "Whistleblower neutralized"; break; case 'S': if (!(text == "ShadowRaidDrillCompleted")) { return; } num = progressionConfig.ShadowRaidDrillCompletedXp.Value; label = "Breach container drilled"; break; } break; case 21: switch (text[0]) { default: return; case 'B': if (!(text == "BlackoutAuditRestored")) { return; } num = progressionConfig.BlackoutBreakerRestoredXp.Value; label = (string.IsNullOrWhiteSpace(value6) ? "Blackout power restored" : ("Blackout restored (" + value6 + ")")); if (string.Equals(value6, "single breaker box", StringComparison.OrdinalIgnoreCase)) { EmployeeStatistics.RecordSingleBreakerRestored(value3); } break; case 'W': { if (!(text == "WasteDisposalRepaired")) { return; } num = progressionConfig.WasteDisposalRepairedXp.Value; label = ((TryGetProperty(__0, "Count", out var value7) && value7 > 1) ? $"Incinerator repaired ({value7})" : "Incinerator repaired"); text2 = "wastedisposal.repair"; maxPerRound = progressionConfig.WasteDisposalRepairMaxPerRound.Value; break; } } break; case 19: { if (!(text == "PayloadPilotSeconds") || !TryGetProperty(__0, "ContractSucceeded", out var value9) || !value9 || !TryGetProperty(__0, "Seconds", out var value10) || value10 <= 0f) { return; } num = ProgressionEconomyMath.ComputePayloadPilotXp(value10, Plugin.ProgressionConfig.PayloadPilotXpPerSecond.Value, Plugin.ProgressionConfig.PayloadPilotMaxXp.Value); label = $"Payload piloting {value10:0.#}s"; break; } case 23: if (!(text == "ShadowRaidDrillAttached")) { return; } num = progressionConfig.BlacksiteDrillPlacedXp.Value; label = "Breach drill mounted"; EmployeeStatistics.RecordDrillPlaced(value3); break; case 22: { if (!(text == "WasteDisposalCompleted")) { return; } num = progressionConfig.WasteDisposalCompletedXp.Value; label = ((TryGetProperty(__0, "Count", out var value11) && value11 > 1) ? $"Waste incinerated ({value11})" : "Waste incinerated"); break; } case 29: if (!(text == "ContainmentBreachWaveSurvived")) { return; } num = progressionConfig.ContainmentWaveSurvivedXp.Value; label = (string.IsNullOrWhiteSpace(value6) ? "Breach wave survived" : ("Breach " + value6 + " survived")); EmployeeStatistics.RecordContainmentWaveSurvived(value3); break; case 28: if (!(text == "ShadowRaidHardDriveRecovered")) { return; } num = progressionConfig.ShadowRaidHardDriveXp.Value; label = "Hard drive recovered"; break; case 18: { if (!(text == "PestControlCapture")) { return; } num = progressionConfig.PestControlCaptureXp.Value; label = ((TryGetProperty(__0, "Count", out var value8) && value8 > 1) ? $"Specimen captured ({value8})" : "Specimen captured"); text2 = "pestcontrol.capture"; maxPerRound = progressionConfig.PestControlCaptureMaxPerRound.Value; break; } case 14: if (!(text == "ContractFailed")) { return; } num = progressionConfig.ContractFailedXp.Value; label = (string.IsNullOrWhiteSpace(value5) ? "Contract failed" : (value5 + " contract failed")); break; case 15: case 16: case 25: case 26: case 27: return; } if (text2 != null) { ProgressionManager.AddCappedContractXp(value3, label, num, text2, maxPerRound, text); } else { ProgressionManager.AddContractXp(value3, label, num, oncePerRound: true, text); } } private static bool IsLocalPlayer(ulong playerClientId) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { return val.actualClientId == playerClientId; } return false; } private static bool TryGetProperty(object source, string name, out T value) { if (GetPropertyValue(source, name) is T val) { value = val; return true; } value = default(T); return false; } private static object GetPropertyValue(object source, string name) { try { return source.GetType().GetProperty(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(source); } catch { return null; } } } [HarmonyPatch] internal static class BlackoutBreakerRestoredPatch { private static MethodBase TargetMethod() { return AccessTools.Method(ContractType("MoonContractRoundStats"), "RecordBlackoutBreakerRestored", new Type[2] { typeof(int), typeof(int) }, (Type[])null); } private static MethodInfo ActorResolver() { return AccessTools.Method(ContractType("BlackoutBreakerActorLatch"), "ResolveActorClientId", (Type[])null, (Type[])null); } private static bool Prepare() { if (TargetMethod() != null) { return ActorResolver() != null; } return false; } [HarmonyPostfix] private static void Postfix(int __0) { try { if (ActorResolver()?.Invoke(null, null) is ulong actorClientId) { EmployeeStatistics.RecordBreakerRestored(__0, actorClientId); } } catch { } } } [HarmonyPatch] internal static class WasteDisposalItemPlacementPatch { private static MethodBase TargetMethod() { return AccessTools.Method(ContractType("WasteDisposalIncineratorController"), "ConfirmPlaceHeldItemClientRpc", new Type[4] { typeof(int), typeof(ulong), typeof(Vector3), typeof(int) }, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } [HarmonyPostfix] private static void Postfix(int __0, ulong __1) { EmployeeStatistics.RecordItemIncinerated(__0, __1); } } [HarmonyPatch] internal static class WhistleblowerDamagePatch { private static MethodBase TargetMethod() { return AccessTools.Method(ContractType("WhistleblowerEnemyAI"), "HitEnemy", new Type[4] { typeof(int), typeof(PlayerControllerB), typeof(bool), typeof(int) }, (Type[])null); } private static bool Prepare() { return TargetMethod() != null; } [HarmonyPrefix] private static void Prefix(EnemyAI __instance, out int __state) { __state = (((Object)(object)__instance != (Object)null) ? Mathf.Max(0, __instance.enemyHP) : 0); } [HarmonyPostfix] private static void Postfix(EnemyAI __instance, PlayerControllerB __1, int __state) { int num = (((Object)(object)__instance != (Object)null) ? Mathf.Max(0, __instance.enemyHP) : __state); int damage = Mathf.Max(0, __state - num); EmployeeStatistics.RecordWhistleblowerDamage(__instance, __1, damage); } } [HarmonyPatch] internal static class LethalCctvMainframeHackPatch { private static Type _hackingOverlayType; private static FieldInfo _mainframeComponentField; private static MethodBase _successMethod; private static bool Prepare() { if (!OptionalPluginCapabilities.LethalCctv) { return false; } _hackingOverlayType = Type.GetType("Y4NGZCompany.ShipSystems.Surveillance.HackingOverlay, LethalCCTV", throwOnError: false); if (_hackingOverlayType == null) { return false; } _mainframeComponentField = _hackingOverlayType?.GetField("_mainframeComponent", BindingFlags.Instance | BindingFlags.NonPublic); _successMethod = _hackingOverlayType.GetMethod("TryMarkMainframeHacked", BindingFlags.Instance | BindingFlags.NonPublic); if (_mainframeComponentField != null) { return _successMethod != null; } return false; } private static MethodBase TargetMethod() { return _successMethod; } [HarmonyPostfix] private static void Postfix(object __instance) { try { object? obj = _mainframeComponentField?.GetValue(__instance); Object val = (Object)((obj is Object) ? obj : null); Component val2 = (Component)(object)((val is Component) ? val : null); if (val2 != null) { ProgressionManager.RecordMainframeHacked(val2); EmployeeStatistics.RecordDeviceHacked(val); } } catch { } } } private static readonly Dictionary ContractTypeCache = new Dictionary(StringComparer.Ordinal); private static Type ContractType(string typeName) { if (ContractTypeCache.TryGetValue(typeName, out var value)) { return value; } Type type = Type.GetType("Y4NGZCompany.Contracts._Shared." + typeName + ", Y4NGZCompany", throwOnError: false) ?? Type.GetType("Y4NGZCompany.Contracts.ShadowRaid." + typeName + ", Y4NGZCompany", throwOnError: false) ?? FindCompanyTypeByName(typeName); ContractTypeCache[typeName] = type; return type; } private static Type FindCompanyTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (!(assembly == null) && !(assembly.GetName().Name != "Y4NGZCompany")) { Type type = FindTypeByName(assembly, typeName); if (type != null) { return type; } } } return null; } private static Type FindTypeByName(Assembly assembly, string typeName) { try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type != null && string.Equals(type.Name, typeName, StringComparison.Ordinal)) { return type; } } } catch (ReflectionTypeLoadException ex) { Type[] types2 = ex.Types; foreach (Type type2 in types2) { if (type2 != null && string.Equals(type2.Name, typeName, StringComparison.Ordinal)) { return type2; } } } catch { } return null; } } internal static class ProgressionPerformanceReportUi { private static readonly string[] LegacyLineNames = new string[2] { "Y4NGZ_ProgressionPerformanceLine", "Y4NGZ_EmployeeStatisticsLine" }; private static int _lastLoggedRound; private static bool _betterExpSkipLogged; private static bool _companyStateLookupAttempted; private static FieldInfo _companyHasPendingField; private static FieldInfo _companyApplyCoroutineField; private const int CompanyWriterWaitFrames = 92; private const float ReportNotesMinimumFontSize = 12f; private const int ReportNotesTotalLineBudget = 4; private const int ReportNotesMinimumLineBudget = 2; private const float ReportNotesFitTolerance = 0.5f; private static readonly Dictionary _authoredFontSizes = new Dictionary(); private const string CompanyRoundEndStateTypeName = "Y4NGZCompany.Contracts._Shared.MoonContractRoundEndState, Y4NGZCompany"; private const string VanillaReportXpColorHex = "#FF521F"; internal static void Apply(HUDManager hud) { DestroyLegacyOverlayLines(); if ((Object)(object)hud == (Object)null) { return; } if (OptionalPluginCapabilities.BetterExp) { if (!_betterExpSkipLogged) { _betterExpSkipLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Progression] BetterEXP owns the performance-report XP surface; Y4NGZUpgrades Notes rendering is disabled for this session."); } } return; } RoundXpBreakdown lastRoundBreakdown = ProgressionManager.LastRoundBreakdown; if (lastRoundBreakdown == null || lastRoundBreakdown.RoundSequence <= 0 || !ProgressionManager.TryGetLastRoundReportSources(out var sources)) { return; } IReadOnlyList readOnlyList = ProgressionReportNotePlan.BuildXpNotes(sources, lastRoundBreakdown.RoundSequence, 3, ResolveXpNoteColorHex()); if (readOnlyList.Count == 0) { return; } ApplyNow(hud, lastRoundBreakdown.RoundSequence, readOnlyList); try { ((MonoBehaviour)hud).StartCoroutine(ApplyAfterDelayedWriters(hud, lastRoundBreakdown.RoundSequence, readOnlyList)); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Progression] Could not schedule the delayed report Notes pass: " + ex.Message)); } } } private static string ResolveXpNoteColorHex() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) try { if (UiTheme.CurrentPreset == HudColorPreset.Default) { return "#FF521F"; } return "#" + ColorUtility.ToHtmlStringRGB(UiTheme.Accent); } catch { return "#FF521F"; } } private static IEnumerator ApplyAfterDelayedWriters(HUDManager hud, int roundSequence, IReadOnlyList notes) { yield return (object)new WaitForEndOfFrame(); int framesRemaining = 92; while (framesRemaining-- > 0 && IsCompanyReportWriterPending()) { yield return null; } if (IsCompanyReportWriterPending()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Progression] Contracted's performance-report writer remained pending " + $"after {92} frames; composing with the current Notes text.")); } } ApplyNow(hud, roundSequence, notes); } private static bool IsCompanyReportWriterPending() { if (!OptionalPluginCapabilities.Contracted) { return false; } EnsureCompanyReportStateFields(); if (_companyHasPendingField == null && _companyApplyCoroutineField == null) { return false; } try { object obj = _companyHasPendingField?.GetValue(null); bool flag = default(bool); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } int num2 = num & (flag ? 1 : 0); bool flag2 = _companyApplyCoroutineField?.GetValue(null) != null; return (byte)((uint)num2 | (flag2 ? 1u : 0u)) != 0; } catch { return false; } } private static void EnsureCompanyReportStateFields() { if (!_companyStateLookupAttempted) { _companyStateLookupAttempted = true; Type? type = Type.GetType("Y4NGZCompany.Contracts._Shared.MoonContractRoundEndState, Y4NGZCompany", throwOnError: false); _companyHasPendingField = type?.GetField("_hasPending", BindingFlags.Static | BindingFlags.NonPublic); _companyApplyCoroutineField = type?.GetField("_performanceReportApplyCoroutine", BindingFlags.Static | BindingFlags.NonPublic); } } private static void ApplyNow(HUDManager hud, int roundSequence, IReadOnlyList notes) { RoundXpBreakdown lastRoundBreakdown = ProgressionManager.LastRoundBreakdown; if ((Object)(object)hud == (Object)null || lastRoundBreakdown == null || lastRoundBreakdown.RoundSequence != roundSequence || hud.statsUIElements?.playerNotesText == null) { return; } int localPlayerIndex = GetLocalPlayerIndex(); TextMeshProUGUI[] playerNotesText = hud.statsUIElements.playerNotesText; if (localPlayerIndex < 0 || localPlayerIndex >= playerNotesText.Length || (Object)(object)playerNotesText[localPlayerIndex] == (Object)null) { return; } TextMeshProUGUI val = playerNotesText[localPlayerIndex]; PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; bool preferLastForeign = OptionalPluginCapabilities.Coroner && (Object)(object)val2 != (Object)null && val2.isPlayerDead; string text = ((TMP_Text)val).text; ConfigureNoteSlot(val); int num = 4; while (true) { string text2 = ProgressionReportNotePlan.ComposeNotes(text, notes, num, preferLastForeign); text2 = text2.TrimEnd('\r', '\n'); if (!string.Equals(((TMP_Text)val).text, text2, StringComparison.Ordinal)) { ((TMP_Text)val).text = text2; } ((TMP_Text)val).ForceMeshUpdate(true, true); if (!OverflowsNoteSlot(val, num)) { break; } if (num <= 2) { ((TMP_Text)val).overflowMode = (TextOverflowModes)3; ((TMP_Text)val).ForceMeshUpdate(true, true); break; } num--; } if (_lastLoggedRound != roundSequence) { _lastLoggedRound = roundSequence; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)($"[Progression] Rendered {notes.Count} ranked XP note candidate(s) " + $"for local report slot {localPlayerIndex} (round {roundSequence}).")); } } } private static void ConfigureNoteSlot(TextMeshProUGUI slot) { if (!((Object)(object)slot == (Object)null)) { ((TMP_Text)slot).richText = true; ((TMP_Text)slot).enableWordWrapping = false; ((TMP_Text)slot).overflowMode = (TextOverflowModes)0; ((TMP_Text)slot).fontSizeMin = 12f; ((TMP_Text)slot).fontSizeMax = ResolveAuthoredFontSize(slot); ((TMP_Text)slot).enableAutoSizing = true; } } private static float ResolveAuthoredFontSize(TextMeshProUGUI slot) { int instanceID = ((Object)slot).GetInstanceID(); if (_authoredFontSizes.TryGetValue(instanceID, out var value)) { return value; } float num = Mathf.Max(12f, ((TMP_Text)slot).enableAutoSizing ? ((TMP_Text)slot).fontSizeMax : ((TMP_Text)slot).fontSize); _authoredFontSizes[instanceID] = num; return num; } private static bool OverflowsNoteSlot(TextMeshProUGUI slot, int budget) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) RectTransform rectTransform = ((TMP_Text)slot).rectTransform; if ((Object)(object)rectTransform == (Object)null) { return false; } Rect rect = rectTransform.rect; float height = ((Rect)(ref rect)).height; if (height <= 0f) { return false; } if (((TMP_Text)slot).textInfo != null && ((TMP_Text)slot).textInfo.lineCount > budget) { return true; } return ((TMP_Text)slot).preferredHeight > height + 0.5f; } internal static int GetLocalPlayerIndex() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { return -1; } ulong playerClientId = val.playerClientId; if (playerClientId <= int.MaxValue) { return (int)playerClientId; } return -1; } private static void DestroyLegacyOverlayLines() { RectTransform[] array = Resources.FindObjectsOfTypeAll(); foreach (RectTransform val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null) && Array.IndexOf(LegacyLineNames, ((Object)((Component)val).gameObject).name) >= 0) { string name = ((Object)((Component)val).gameObject).name; ((Component)val).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val).gameObject); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Progression] Removed legacy report overlay line '" + name + "'.")); } } } } } internal static class ProgressionRankSync { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetRankServerRpc; public static HandleNamedMessageDelegate <1>__OnRequestAllRanksServerRpc; public static HandleNamedMessageDelegate <2>__OnSetRankClientRpc; public static HandleNamedMessageDelegate <3>__OnSyncAllRanksClientRpc; } private const string MsgSetServer = "Y4NGZProgression.SetRankServerRpc"; private const string MsgSetClient = "Y4NGZProgression.SetRankClientRpc"; private const string MsgRequestAllServer = "Y4NGZProgression.RequestAllRanksServerRpc"; private const string MsgSyncAllClient = "Y4NGZProgression.SyncAllRanksClientRpc"; private static readonly Dictionary RankXpByClientId = new Dictionary(); private static bool _handlersRegistered; internal static void RegisterNetworkHandlers() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Expected O, but got Unknown //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: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown if (_handlersRegistered) { return; } NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null) { return; } try { if (singleton.IsServer) { object obj = <>O.<0>__OnSetRankServerRpc; if (obj == null) { HandleNamedMessageDelegate val2 = OnSetRankServerRpc; <>O.<0>__OnSetRankServerRpc = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZProgression.SetRankServerRpc", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequestAllRanksServerRpc; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnRequestAllRanksServerRpc; <>O.<1>__OnRequestAllRanksServerRpc = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZProgression.RequestAllRanksServerRpc", (HandleNamedMessageDelegate)obj2); } object obj3 = <>O.<2>__OnSetRankClientRpc; if (obj3 == null) { HandleNamedMessageDelegate val4 = OnSetRankClientRpc; <>O.<2>__OnSetRankClientRpc = val4; obj3 = (object)val4; } val.RegisterNamedMessageHandler("Y4NGZProgression.SetRankClientRpc", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnSyncAllRanksClientRpc; if (obj4 == null) { HandleNamedMessageDelegate val5 = OnSyncAllRanksClientRpc; <>O.<3>__OnSyncAllRanksClientRpc = val5; obj4 = (object)val5; } val.RegisterNamedMessageHandler("Y4NGZProgression.SyncAllRanksClientRpc", (HandleNamedMessageDelegate)obj4); _handlersRegistered = true; } catch (Exception ex) { _handlersRegistered = false; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ProgressionRankSync] handler registration failed: " + ex.Message)); } } } internal static void Clear() { RankXpByClientId.Clear(); UnregisterNetworkHandlers(); } internal static void PublishLocalRank() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { PublishRank(val.actualClientId, ProgressionManager.CurrentRankXp); } } internal unsafe static void RequestAllRanksFromServer() { //IL_0048: Unknown result type (might be due to invalid IL or missing references) RegisterNetworkHandlers(); NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsClient || singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(0, (Allocator)2, -1); try { val.SendNamedMessage("Y4NGZProgression.RequestAllRanksServerRpc", 0uL, val2, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } internal static int GetRankXpForPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)player == (Object)(object)val) { return ProgressionManager.CurrentRankXp; } if (!RankXpByClientId.TryGetValue(player.actualClientId, out var value)) { return 0; } return RankCatalog.ClampXp(value); } private unsafe static void PublishRank(ulong clientId, int rankXp) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) rankXp = RankCatalog.ClampXp(rankXp); RankXpByClientId[clientId] = rankXp; RegisterNetworkHandlers(); NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsClient) { return; } if (singleton.IsServer) { SendSetRankToAllClients(clientId, rankXp); return; } FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref clientId, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref rankXp, default(ForPrimitives)); val.SendNamedMessage("Y4NGZProgression.SetRankServerRpc", 0uL, val2, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void SendSetRankToAllClients(ulong clientId, int rankXp) { //IL_0030: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null) { return; } FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref clientId, default(ForPrimitives)); int num = RankCatalog.ClampXp(rankXp); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref num, default(ForPrimitives)); val.SendNamedMessageToAll("Y4NGZProgression.SetRankClientRpc", val2, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnSetRankServerRpc(ulong senderClientId, FastBufferReader reader) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int xp = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref xp, default(ForPrimitives)); xp = RankCatalog.ClampXp(xp); RankXpByClientId[num] = xp; SendSetRankToAllClients(num, xp); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[ProgressionRankSync] malformed rank set from {senderClientId}: {ex.Message}"); } } } private static void OnSetRankClientRpc(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) try { ulong key = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref key, default(ForPrimitives)); int xp = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref xp, default(ForPrimitives)); RankXpByClientId[key] = RankCatalog.ClampXp(xp); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[ProgressionRankSync] malformed rank sync from {senderClientId}: {ex.Message}"); } } } private unsafe static void OnRequestAllRanksServerRpc(ulong senderClientId, FastBufferReader reader) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a1: 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_00ce: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } try { int count = RankXpByClientId.Count; FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(2 + count * 12, (Allocator)2, -1); try { short num = (short)count; ((FastBufferWriter)(ref val2)).WriteValueSafe(ref num, default(ForPrimitives)); foreach (KeyValuePair item in RankXpByClientId) { ulong key = item.Key; ((FastBufferWriter)(ref val2)).WriteValueSafe(ref key, default(ForPrimitives)); int num2 = RankCatalog.ClampXp(item.Value); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref num2, default(ForPrimitives)); } val.SendNamedMessage("Y4NGZProgression.SyncAllRanksClientRpc", senderClientId, val2, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ProgressionRankSync] failed to send rank snapshot: " + ex.Message)); } } } private static void OnSyncAllRanksClientRpc(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) try { short num = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); ulong key = default(ulong); int xp = default(int); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref key, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref xp, default(ForPrimitives)); RankXpByClientId[key] = RankCatalog.ClampXp(xp); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[ProgressionRankSync] malformed rank snapshot from {senderClientId}: {ex.Message}"); } } } private static void UnregisterNetworkHandlers() { if (!_handlersRegistered) { return; } NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton != (Object)null && val != null) { try { if (singleton.IsServer) { val.UnregisterNamedMessageHandler("Y4NGZProgression.SetRankServerRpc"); val.UnregisterNamedMessageHandler("Y4NGZProgression.RequestAllRanksServerRpc"); } val.UnregisterNamedMessageHandler("Y4NGZProgression.SetRankClientRpc"); val.UnregisterNamedMessageHandler("Y4NGZProgression.SyncAllRanksClientRpc"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[ProgressionRankSync] handler unregister failed: " + ex.Message)); } } } _handlersRegistered = false; } } public static class ProgressionReportNotePlan { public const string XpColorHex = "#6FE7A8"; private const string XpTagOpen = " BuildXpNotes(IReadOnlyList sources, int roundSequence, int maxNotes = 3, string xpColorHex = null) { string text = ""; List list = new List(); if (sources == null || maxNotes <= 0) { return list; } List list2 = new List(); HashSet hashSet = new HashSet(StringComparer.Ordinal); for (int i = 0; i < sources.Count; i++) { ProgressionReportSource progressionReportSource = sources[i]; if (progressionReportSource != null && progressionReportSource.Amount > 0 && hashSet.Add(progressionReportSource.Key)) { list2.Add(progressionReportSource); } } list2.Sort(delegate(ProgressionReportSource left, ProgressionReportSource right) { int num2 = right.Amount.CompareTo(left.Amount); if (num2 != 0) { return num2; } int num3 = left.Order.CompareTo(right.Order); return (num3 == 0) ? string.Compare(left.Key, right.Key, StringComparison.Ordinal) : num3; }); for (int num = 0; num < list2.Count; num++) { if (list.Count >= maxNotes) { break; } ProgressionReportSource progressionReportSource2 = list2[num]; string text2 = BuildSentence(progressionReportSource2, UseAlternateWording(roundSequence, progressionReportSource2.Key)); if (!string.IsNullOrWhiteSpace(text2)) { list.Add("* " + text2 + " " + text + "(" + progressionReportSource2.Amount.ToString(CultureInfo.InvariantCulture) + "XP)"); } } return list; } public static string ComposeNotes(string existingText, IReadOnlyList xpNotes, int maxLines = 4, bool preferLastForeign = false) { if (xpNotes == null || xpNotes.Count == 0 || maxLines <= 0) { return existingText ?? string.Empty; } string[] array = (existingText ?? string.Empty).Replace("\r\n", "\n").Replace('\r', '\n').Split(new char[1] { '\n' }, StringSplitOptions.None); List list = new List(); List list2 = new List(); bool flag = false; for (int i = 0; i < array.Length; i++) { string text = array[i]?.TrimEnd() ?? string.Empty; string text2 = text.TrimStart(); if (text2.StartsWith("* ", StringComparison.Ordinal)) { flag = true; if (!IsXpNoteLine(text2)) { list2.Add(text2); } } else if (!flag && text.Length > 0 && (!IsNotesHeaderRow(text) || !HasNotesHeader(list))) { list.Add(text); } } if (list.Count == 0) { list.Add("Notes:"); } List list3 = new List(); for (int j = 0; j < xpNotes.Count; j++) { string text3 = xpNotes[j]?.Trim(); if (!string.IsNullOrEmpty(text3)) { list3.Add(text3); } } List list4 = new List(list3); int num = list.Count + list2.Count + list4.Count - maxLines; while (num > 0 && list4.Count > 1) { list4.RemoveAt(list4.Count - 1); num--; } while (num > 0 && TryDropLeadingHeading(list)) { num--; } while (num > 0 && list2.Count > 0) { list2.RemoveAt((!preferLastForeign) ? (list2.Count - 1) : 0); num--; } while (num > 0 && list4.Count > 0) { list4.RemoveAt(list4.Count - 1); num--; } while (list.Count > 0 && list2.Count == 0 && list4.Count == 0 && !IsNotesHeaderRow(list[list.Count - 1])) { list.RemoveAt(list.Count - 1); if (list3.Count > 0) { list4.Add(list3[0]); break; } } StringBuilder stringBuilder = new StringBuilder(); for (int k = 0; k < list.Count; k++) { stringBuilder.Append(list[k]).Append('\n'); } for (int l = 0; l < list2.Count; l++) { stringBuilder.Append(list2[l]).Append('\n'); } for (int m = 0; m < list4.Count; m++) { stringBuilder.Append(list4[m]).Append('\n'); } return stringBuilder.ToString(); } private static bool TryDropLeadingHeading(List header) { for (int i = 0; i < header.Count; i++) { if (!IsNotesHeaderRow(header[i])) { header.RemoveAt(i); return true; } } return false; } private static bool IsNotesHeaderRow(string row) { return (row ?? string.Empty).Trim().EndsWith("Notes:", StringComparison.OrdinalIgnoreCase); } private static bool IsXpNoteLine(string line) { int num = line.IndexOf("= 0) { return line.IndexOf("XP)", num, StringComparison.Ordinal) > num; } return false; } private static bool HasNotesHeader(List header) { for (int i = 0; i < header.Count; i++) { if (IsNotesHeaderRow(header[i])) { return true; } } return false; } private static string BuildSentence(ProgressionReportSource source, bool alternate) { switch (source.Kind) { case ProgressionReportSourceKind.ScrapDiscovered: return (alternate ? "Discovered " : "Found ") + FormatCountedSubject(source.Subject, source.Count) + "."; case ProgressionReportSourceKind.ScrapDelivered: return (alternate ? "Brought back " : "Delivered ") + FormatCountedSubject(source.Subject, source.Count) + "."; case ProgressionReportSourceKind.MonsterKill: return (alternate ? "Took down " : "Killed ") + FormatCountedSubject(source.Subject, source.Count) + "."; case ProgressionReportSourceKind.Survival: if (string.Equals(source.Subject, "extracted", StringComparison.OrdinalIgnoreCase)) { if (!alternate) { return "Survived the shift."; } return "Made it back alive."; } if (!alternate) { return "Stayed alive for " + FormatMinutes(source.Count) + "."; } return "Lasted " + FormatMinutes(source.Count) + "."; case ProgressionReportSourceKind.BodyRetrieval: if (source.Count == 1 && !string.IsNullOrWhiteSpace(source.Subject)) { string text = EscapeRichText(source.Subject); if (!alternate) { return "Recovered " + text + "'s body."; } return "Brought back " + text + "'s body."; } return (alternate ? "Brought back " : "Recovered ") + ((source.Count == 1) ? "a crew member's body." : (Math.Max(2, source.Count).ToString(CultureInfo.InvariantCulture) + " crew bodies.")); case ProgressionReportSourceKind.MainframeHack: if (source.Count > 1) { return (alternate ? "Breached " : "Hacked ") + source.Count.ToString(CultureInfo.InvariantCulture) + " mainframes."; } if (!alternate) { return "Hacked the mainframe."; } return "Breached the mainframe."; case ProgressionReportSourceKind.Clutch: if (!alternate) { return "Made the clutch escape."; } return "Came back as the last survivor."; case ProgressionReportSourceKind.Contract: return EnsureSentence(source.Subject, "Completed contract work."); default: return string.Empty; } } private static string FormatCountedSubject(string subject, int count) { int num = Math.Max(1, count); string value = EscapeRichText(string.IsNullOrWhiteSpace(subject) ? "scrap" : subject.Trim()); value = LowerFirst(value); if (num != 1) { value = Pluralize(value); } return num.ToString(CultureInfo.InvariantCulture) + " " + value; } private static string FormatMinutes(int minutes) { int num = Math.Max(1, minutes); return num.ToString(CultureInfo.InvariantCulture) + ((num == 1) ? " minute" : " minutes"); } private static string EnsureSentence(string value, string fallback) { string text = EscapeRichText(string.IsNullOrWhiteSpace(value) ? fallback : value.Trim()); char c = text[text.Length - 1]; if (c != '.' && c != '!' && c != '?') { return text + "."; } return text; } private static string EscapeRichText(string value) { return (value ?? string.Empty).Replace("&", "&").Replace("<", "<").Replace(">", ">"); } private static string LowerFirst(string value) { if (string.IsNullOrEmpty(value) || !char.IsUpper(value[0])) { return value; } if (value.Length == 1) { return char.ToLowerInvariant(value[0]).ToString(); } return char.ToLowerInvariant(value[0]) + value.Substring(1); } private static string Pluralize(string noun) { if (string.IsNullOrEmpty(noun)) { return noun; } if (string.Equals(noun, "teeth", StringComparison.OrdinalIgnoreCase) || string.Equals(noun, "scissors", StringComparison.OrdinalIgnoreCase) || string.Equals(noun, "dice", StringComparison.OrdinalIgnoreCase)) { return noun; } if (noun.EndsWith("ch", StringComparison.OrdinalIgnoreCase) || noun.EndsWith("sh", StringComparison.OrdinalIgnoreCase) || noun.EndsWith("s", StringComparison.OrdinalIgnoreCase) || noun.EndsWith("x", StringComparison.OrdinalIgnoreCase) || noun.EndsWith("z", StringComparison.OrdinalIgnoreCase)) { return noun + "es"; } if (noun.Length > 1 && noun.EndsWith("y", StringComparison.OrdinalIgnoreCase) && "aeiou".IndexOf(char.ToLowerInvariant(noun[noun.Length - 2])) < 0) { return noun.Substring(0, noun.Length - 1) + "ies"; } return noun + "s"; } private static bool UseAlternateWording(int roundSequence, string key) { uint num = 2166136261u; string text = roundSequence.ToString(CultureInfo.InvariantCulture) + ":" + (key ?? string.Empty); for (int i = 0; i < text.Length; i++) { num ^= text[i]; num *= 16777619; } return (num & 1) != 0; } } public enum ProgressionReportSourceKind { ScrapDiscovered, ScrapDelivered, MonsterKill, Survival, BodyRetrieval, MainframeHack, Clutch, Contract } public sealed class ProgressionReportSource { public string Key { get; } public ProgressionReportSourceKind Kind { get; } public string Subject { get; } public int Count { get; } public int Amount { get; } public int Order { get; } public ProgressionReportSource(string key, ProgressionReportSourceKind kind, string subject, int count, int amount, int order) { Key = (string.IsNullOrWhiteSpace(key) ? kind.ToString() : key.Trim()); Kind = kind; Subject = subject?.Trim() ?? string.Empty; Count = Math.Max(0, count); Amount = Math.Max(0, amount); Order = Math.Max(0, order); } } internal sealed class ProgressionState { internal int RankXp; internal int UpgradeCurrency; internal readonly HashSet ExternalTokenGrantIds = new HashSet(StringComparer.Ordinal); internal readonly HashSet CompletedTokenSpendIds = new HashSet(StringComparer.Ordinal); internal ProgressionState Clone() { ProgressionState progressionState = new ProgressionState(); progressionState.RankXp = RankXp; progressionState.UpgradeCurrency = UpgradeCurrency; progressionState.ExternalTokenGrantIds.UnionWith(ExternalTokenGrantIds); progressionState.CompletedTokenSpendIds.UnionWith(CompletedTokenSpendIds); return progressionState; } } [HarmonyPatch(typeof(Terminal), "ParsePlayerSentence")] internal static class ProgressionTokenTerminalPatch { [HarmonyPrefix] private static bool Prefix(Terminal __instance, ref TerminalNode __result) { LobbyTokenCommand lobbyTokenCommand = LobbyTokenCommandParser.Parse(GetInput(__instance)); if (lobbyTokenCommand.Kind == LobbyTokenCommandKind.NotCommand) { return true; } if (lobbyTokenCommand.Kind == LobbyTokenCommandKind.Usage) { __result = CreateNode("Usage: settokens \nExample: settokens 1000"); return false; } if (lobbyTokenCommand.Kind == LobbyTokenCommandKind.InvalidAmount) { __result = CreateNode($"Token amount must be a whole number from 0 to {999999}."); return false; } if (LobbyTokenCommandNetwork.TrySetLobbyTokens(lobbyTokenCommand.Amount, out var connectedEmployees, out var error)) { string arg = ((connectedEmployees == 1) ? "employee" : "employees"); __result = CreateNode($"Tokens set to {lobbyTokenCommand.Amount} for {connectedEmployees} connected {arg}."); } else { __result = CreateNode(error); } return false; } private static string GetInput(Terminal terminal) { object obj; if (terminal == null) { obj = null; } else { TMP_InputField screenText = terminal.screenText; obj = ((screenText != null) ? screenText.text : null); } if (obj == null) { obj = string.Empty; } string text = (string)obj; int num = text.LastIndexOf('\n'); if (num < 0) { return text.Trim(); } return text.Substring(num + 1).Trim(); } private static TerminalNode CreateNode(string text) { TerminalNode obj = ScriptableObject.CreateInstance(); obj.displayText = (text ?? string.Empty) + "\n\n"; obj.clearPreviousText = true; return obj; } } internal static class ProgressionXpBarUi { private enum RankChangeDirection { Up, None } private sealed class TokensGrantedLifetime : MonoBehaviour { internal RectTransform Reference; private float _hideAt = -1f; private void LateUpdate() { if ((Object)(object)Reference != (Object)null && !((Component)Reference).gameObject.activeInHierarchy) { ((Component)this).gameObject.SetActive(false); } else if (_hideAt > 0f && Time.realtimeSinceStartup >= _hideAt) { ((Component)this).gameObject.SetActive(false); } } internal void Extend(float seconds) { _hideAt = Time.realtimeSinceStartup + Mathf.Max(0.25f, seconds); } } private const string MarksCounterName = "Y4NGZ_TokensGrantedCounter"; private const string MarksStripName = "Y4NGZ_TokensGrantedExtension"; private const string LegacyMarksStripName = "Y4NGZ_MarksGrantedStrip"; private const string MarksSoundFileName = "juniorsoundays-ui-sound-67-527859.mp3"; private const float MarksStripHeight = 52f; private const float MarksStripVerticalGap = 10f; private const float PresentationVisibilityTimeoutSeconds = 2f; private const float CoordinatedPresentationReadyLifetimeSeconds = 1.5f; private const float DeferPresentationFailsafeSeconds = 45f; private const float RankUpBeatSeconds = 0.4f; private const string OwnedLevellingAudioName = "Y4NGZ_ProgressionLevellingAudio"; private const string OwnedUiAudioName = "Y4NGZ_ProgressionUiAudio"; private static AudioSource _ownedLevellingAudio; private static AudioSource _ownedUiAudio; private static readonly Vector3[] TokenStripWorldCorners = (Vector3[])(object)new Vector3[4]; private static MonoBehaviour _coroutineHost; private static AudioClip _marksGrantedClip; private static bool _marksGrantedClipLoadStarted; private static MonoBehaviour _animationHost; private static Coroutine _animationCoroutine; private static HUDManager _animationHud; private static RoundXpBreakdown _animationLog; private static RoundXpBreakdown _completedLog; private static int _animationGeneration; private static HUDManager _coordinatedPresentationHud; private static float _coordinatedPresentationReadyUntilRealtime; private static readonly Vector3[] PresentationWorldCorners = (Vector3[])(object)new Vector3[4]; internal static Func ShouldDeferPresentation; internal static bool IsPresentationActive => _animationCoroutine != null; internal static void Initialize(MonoBehaviour host) { _coroutineHost = host; EnsureMarksSoundLoading(); ShouldDeferPresentation = null; TryResolveCompanyReportHold(); } private static void TryResolveCompanyReportHold() { if (ShouldDeferPresentation != null) { return; } if (!OptionalPluginCapabilities.Contracted) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Progression] Contracted not present; XP/token gains use the standalone vanilla level-box presentation."); } return; } try { MethodInfo method = Type.GetType("Y4NGZCompany.Contracts._Shared.ContractPerformanceReportUi, Y4NGZCompany", throwOnError: false)?.GetMethod("ShouldHoldXpPresentation", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(HUDManager) }, null); if (method == null) { return; } ShouldDeferPresentation = delegate(HUDManager hud) { try { object obj2 = method.Invoke(null, new object[1] { hud }); bool flag = default(bool); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } }; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[Progression] XP/token presentation gated behind the Company performance report."); } } catch { } } private static bool IsSameRound(RoundXpBreakdown a, RoundXpBreakdown b) { if (a == null || b == null) { return false; } if (a == b) { return true; } if (a.RoundSequence > 0) { return a.RoundSequence == b.RoundSequence; } return false; } internal static void ResetForRound() { CancelActiveAnimation("round reset"); _completedLog = null; ClearCoordinatedPresentationReady(); } internal static void MarkPresentationWindowReady(HUDManager hud) { if (!((Object)(object)hud == (Object)null)) { _coordinatedPresentationHud = hud; _coordinatedPresentationReadyUntilRealtime = Time.realtimeSinceStartup + 1.5f; } } internal static void PrimeStartingValues(HUDManager hud, RoundXpBreakdown log) { if (!((Object)(object)hud == (Object)null) && _animationCoroutine == null && (log == null || !IsSameRound(log, _completedLog))) { int xp = ((log != null) ? Mathf.Max(0, log.OldXp) : ProgressionManager.CurrentRankXp); SetHudRankImmediate(hud, xp, RankChangeDirection.None); HideMarksCounter(hud); } } internal static void ShowRoundXp(HUDManager hud, RoundXpBreakdown log) { if ((Object)(object)hud == (Object)null) { return; } if (log == null) { CancelActiveAnimation("missing round breakdown"); HideMarksCounter(hud); SetHudRankImmediate(hud, ProgressionManager.CurrentRankXp, RankChangeDirection.None); return; } if (IsSameRound(log, _animationLog) && _animationCoroutine != null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[Progression] Coalesced duplicate in-flight XP/token presentation request."); } return; } if (IsSameRound(log, _completedLog)) { SetHudRankImmediate(hud, Mathf.Max(0, log.NewXp), (log.RanksGained <= 0) ? RankChangeDirection.None : RankChangeDirection.Up); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)"[Progression] Ignored duplicate completed XP/token presentation request."); } return; } CancelActiveAnimation("superseded presentation request"); MonoBehaviour val = (MonoBehaviour)(((Object)(object)_coroutineHost != (Object)null) ? _coroutineHost : (((Object)(object)Y4NGZPersistentRunner.Host != (Object)null) ? ((object)Y4NGZPersistentRunner.Host) : ((object)hud))); if (!((Object)(object)val == (Object)null)) { _animationHost = val; _animationHud = hud; _animationLog = log; int generation = ++_animationGeneration; bool flag = ConsumeCoordinatedPresentationReady(hud); _animationCoroutine = val.StartCoroutine(AnimateXp(hud, log, generation, flag)); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)($"[Progression] XP/token presentation started: old={log.OldXp}, new={log.NewXp}, " + $"awarded={log.AwardedTotal}, ranks={log.RanksGained}, tokens={log.CurrencyGranted}, " + $"coordinatedReady={flag}.")); } } } private static IEnumerator AnimateXp(HUDManager hud, RoundXpBreakdown log, int generation, bool presentationWindowReady) { int oldXp = Mathf.Max(0, log.OldXp); int newXp = Mathf.Max(0, log.NewXp); int gain = Mathf.Max(0, log.AwardedTotal); int changingRank = RankCatalog.GetRankIndex(oldXp); RankChangeDirection direction = ((log.RanksGained <= 0) ? RankChangeDirection.None : RankChangeDirection.Up); int totalMarksEarned = Mathf.Max(0, log.CurrencyGranted); int marksShown = 0; TextMeshProUGUI marksCounter = ((totalMarksEarned > 0) ? EnsureMarksCounter(hud) : FindMarksCounter(hud)); SetMarksCounter(marksCounter, 0, visible: false); if (!presentationWindowReady && ShouldDeferPresentation != null) { float deferStart = Time.realtimeSinceStartup; bool parked = false; while (Time.realtimeSinceStartup - deferStart < 45f) { bool flag; try { flag = ShouldDeferPresentation(hud); } catch { flag = false; } if (!flag) { break; } if (!parked) { parked = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[Progression] XP/token presentation parked behind the performance report."); } } if (!IsCurrentPresentation(hud, log, generation)) { yield break; } yield return null; } if (parked) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)("[Progression] XP/token presentation released after " + $"{Time.realtimeSinceStartup - deferStart:0.00}s behind the performance report.")); } } } if (!presentationWindowReady) { yield return WaitForPresentationVisible(hud, log, generation); if (!IsCurrentPresentation(hud, log, generation)) { yield break; } if (!IsPresentationVisible(hud)) { SetHudRankImmediate(hud, newXp, direction); HideMarksCounter(hud); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogWarning((object)("[Progression] XP/token presentation never became visible within " + $"{2f:0.0}s; applied final values without playing audio.")); } CompleteActiveAnimation(hud, log, generation); yield break; } } else { yield return null; if (!IsCurrentPresentation(hud, log, generation)) { yield break; } } PlayLevellingFillAudio(hud, gain); float start = Time.realtimeSinceStartup; float duration = Mathf.Clamp((float)gain / 120f, 1.1f, 2.5f); while (Time.realtimeSinceStartup - start < duration) { float t = Mathf.Clamp01((Time.realtimeSinceStartup - start) / duration); float num = Mathf.Lerp((float)oldXp, (float)newXp, Smooth(t)); int rankIndex = RankCatalog.GetRankIndex(Mathf.RoundToInt(num)); if (rankIndex > changingRank) { for (int i = changingRank + 1; i <= rankIndex; i++) { OnAnimatedRankUp(hud, log, i, totalMarksEarned, ref marksShown, marksCounter); } changingRank = rankIndex; } else if (rankIndex != changingRank) { changingRank = rankIndex; } SetHudRankValues(hud, Mathf.RoundToInt(num), changingRank, direction); yield return null; } int finalRank = RankCatalog.GetRankIndex(newXp); while (changingRank < finalRank) { changingRank++; OnAnimatedRankUp(hud, log, changingRank, totalMarksEarned, ref marksShown, marksCounter); SetHudRankValues(hud, newXp, changingRank, direction); float deferStart = Time.realtimeSinceStartup; while (Time.realtimeSinceStartup - deferStart < 0.4f) { if (!IsCurrentPresentation(hud, log, generation)) { yield break; } yield return null; } } StopLevellingAudio(hud); SetHudRankImmediate(hud, newXp, direction); if (totalMarksEarned > 0) { SetMarksCounter(marksCounter, totalMarksEarned, visible: true); } ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogInfo((object)($"[Progression] XP/token presentation settled: rank={changingRank}/{finalRank}, " + $"tokensEarned={totalMarksEarned}, tokensShown={marksShown}, " + $"counterPresent={(Object)(object)marksCounter != (Object)null}, " + $"stripActive={(Object)(object)marksCounter != (Object)null && (Object)(object)((TMP_Text)marksCounter).transform.parent != (Object)null && ((Component)((TMP_Text)marksCounter).transform.parent).gameObject.activeInHierarchy}.")); } CompleteActiveAnimation(hud, log, generation); } private static IEnumerator WaitForPresentationVisible(HUDManager hud, RoundXpBreakdown log, int generation) { float start = Time.realtimeSinceStartup; while (IsCurrentPresentation(hud, log, generation) && !IsPresentationVisible(hud) && Time.realtimeSinceStartup - start < 2f) { yield return null; } } private static bool ConsumeCoordinatedPresentationReady(HUDManager hud) { if ((Object)(object)_coordinatedPresentationHud == (Object)null || Time.realtimeSinceStartup > _coordinatedPresentationReadyUntilRealtime) { ClearCoordinatedPresentationReady(); return false; } if ((Object)(object)_coordinatedPresentationHud != (Object)(object)hud) { return false; } ClearCoordinatedPresentationReady(); return true; } private static void ClearCoordinatedPresentationReady() { _coordinatedPresentationHud = null; _coordinatedPresentationReadyUntilRealtime = 0f; } internal static bool IsPresentationVisible(HUDManager hud) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) RectTransform val = FindVanillaLevelUpBox(hud); if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null || !((Component)val).gameObject.activeInHierarchy) { return false; } Canvas componentInParent = ((Component)val).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null || !((Behaviour)componentInParent).isActiveAndEnabled) { return false; } if (!IsCanvasGroupPathVisible((Transform)(object)val)) { return false; } Graphic[] componentsInChildren = ((Component)val).GetComponentsInChildren(false); bool flag = false; foreach (Graphic val2 in componentsInChildren) { if ((Object)(object)val2 != (Object)null && ((Behaviour)val2).enabled && ((Component)val2).gameObject.activeInHierarchy && val2.color.a > 0.03f) { flag = true; break; } } if (!flag) { return false; } return IsRectOnScreen(val, componentInParent); } private static bool IsCanvasGroupPathVisible(Transform transform) { float num = 1f; Transform val = transform; while ((Object)(object)val != (Object)null) { CanvasGroup[] components = ((Component)val).GetComponents(); bool flag = false; foreach (CanvasGroup val2 in components) { if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled) { num *= val2.alpha; if (num <= 0.03f) { return false; } flag |= val2.ignoreParentGroups; } } if (flag) { break; } val = val.parent; } return true; } private static bool IsRectOnScreen(RectTransform rect, Canvas canvas) { //IL_0013: 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_0062: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (Screen.width <= 0 || Screen.height <= 0) { return true; } Camera val = (((int)canvas.renderMode == 0) ? null : canvas.worldCamera); rect.GetWorldCorners(PresentationWorldCorners); float num = float.PositiveInfinity; float num2 = float.PositiveInfinity; float num3 = float.NegativeInfinity; float num4 = float.NegativeInfinity; for (int i = 0; i < PresentationWorldCorners.Length; i++) { Vector2 val2 = RectTransformUtility.WorldToScreenPoint(val, PresentationWorldCorners[i]); num = Mathf.Min(num, val2.x); num2 = Mathf.Min(num2, val2.y); num3 = Mathf.Max(num3, val2.x); num4 = Mathf.Max(num4, val2.y); } Rect pixelRect = canvas.pixelRect; if (((Rect)(ref pixelRect)).width <= 0f || ((Rect)(ref pixelRect)).height <= 0f) { ((Rect)(ref pixelRect))..ctor(0f, 0f, (float)Screen.width, (float)Screen.height); } if (num3 >= ((Rect)(ref pixelRect)).xMin && num <= ((Rect)(ref pixelRect)).xMax && num4 >= ((Rect)(ref pixelRect)).yMin) { return num2 <= ((Rect)(ref pixelRect)).yMax; } return false; } private static bool IsCurrentPresentation(HUDManager hud, RoundXpBreakdown log, int generation) { if (generation == _animationGeneration && (Object)(object)_animationHud == (Object)(object)hud) { return _animationLog == log; } return false; } private static void CompleteActiveAnimation(HUDManager hud, RoundXpBreakdown log, int generation) { if (IsCurrentPresentation(hud, log, generation)) { StopLevellingAudio(hud); _completedLog = log; _animationCoroutine = null; _animationHost = null; _animationHud = null; _animationLog = null; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"[Progression] XP/token presentation value animation completed."); } } } private static void CancelActiveAnimation(string reason) { if (_animationCoroutine != null) { Coroutine animationCoroutine = _animationCoroutine; MonoBehaviour animationHost = _animationHost; HUDManager animationHud = _animationHud; _animationGeneration++; _animationCoroutine = null; _animationHost = null; _animationHud = null; _animationLog = null; if ((Object)(object)animationHost != (Object)null && animationCoroutine != null) { animationHost.StopCoroutine(animationCoroutine); } StopLevellingAudio(animationHud); if ((Object)(object)animationHud != (Object)null) { HideMarksCounter(animationHud); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Progression] Cancelled XP/token presentation (" + (reason ?? "unspecified") + ").")); } } } private static void StopLevellingAudio(HUDManager hud) { if ((Object)(object)hud != (Object)null && (Object)(object)hud.LevellingAudio != (Object)null && hud.LevellingAudio.isPlaying) { hud.LevellingAudio.Stop(); } if ((Object)(object)_ownedLevellingAudio != (Object)null && _ownedLevellingAudio.isPlaying) { _ownedLevellingAudio.Stop(); } } private static void PlayLevellingFillAudio(HUDManager hud, int gain) { if ((Object)(object)hud == (Object)null || gain <= 0 || (Object)(object)hud.increaseXPSFX == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Progression] XP fill audio skipped: " + $"hud={(Object)(object)hud != (Object)null}, gain={gain}, clip={(Object)(object)hud != (Object)null && (Object)(object)hud.increaseXPSFX != (Object)null}.")); } return; } if (IsUsableAudioSource(hud.LevellingAudio)) { hud.LevellingAudio.clip = hud.increaseXPSFX; hud.LevellingAudio.Play(); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)($"[Progression] XP fill audio playing on vanilla LevellingAudio (isPlaying={hud.LevellingAudio.isPlaying}, " + $"volume={hud.LevellingAudio.volume:0.00}, mute={hud.LevellingAudio.mute}).")); } return; } AudioSource val = EnsureOwnedAudioSource(ref _ownedLevellingAudio, "Y4NGZ_ProgressionLevellingAudio", hud.LevellingAudio ?? hud.UIAudio); if (!((Object)(object)val == (Object)null)) { val.loop = true; val.clip = hud.increaseXPSFX; val.Play(); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)"[Progression] Vanilla LevellingAudio unusable; played the XP fill through the Y4NGZ source."); } } } private static void PlayLevelUpOneShot(HUDManager hud) { if ((Object)(object)hud == (Object)null || (Object)(object)hud.levelIncreaseSFX == (Object)null) { return; } if (IsUsableAudioSource(hud.UIAudio)) { hud.UIAudio.PlayOneShot(hud.levelIncreaseSFX); return; } AudioSource obj = EnsureOwnedAudioSource(ref _ownedUiAudio, "Y4NGZ_ProgressionUiAudio", hud.UIAudio ?? hud.LevellingAudio); if (obj != null) { obj.PlayOneShot(hud.levelIncreaseSFX); } } private static bool IsUsableAudioSource(AudioSource source) { if ((Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null && ((Component)source).gameObject.activeInHierarchy) { return ((Behaviour)source).isActiveAndEnabled; } return false; } private static AudioSource EnsureOwnedAudioSource(ref AudioSource cached, string objectName, AudioSource template) { //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_0028: Expected O, but got Unknown if ((Object)(object)cached != (Object)null && (Object)(object)((Component)cached).gameObject != (Object)null) { return cached; } GameObject val = new GameObject(objectName); Object.DontDestroyOnLoad((Object)val); AudioSource val2 = val.AddComponent(); val2.playOnAwake = false; val2.loop = false; val2.spatialBlend = 0f; val2.volume = (((Object)(object)template != (Object)null) ? template.volume : 1f); if ((Object)(object)template != (Object)null) { val2.outputAudioMixerGroup = template.outputAudioMixerGroup; } cached = val2; return val2; } private static float Smooth(float t) { return t * t * (3f - 2f * t); } private static void SetHudRankImmediate(HUDManager hud, int xp, RankChangeDirection direction) { SetHudRankValues(hud, xp, RankCatalog.GetRankIndex(xp), direction); } private static void SetHudRankValues(HUDManager hud, int xp, int rankIndex, RankChangeDirection direction) { RankDefinition rankByIndex = RankCatalog.GetRankByIndex(rankIndex); float fillAmount = ((rankIndex >= RankCatalog.Count - 1) ? 1f : Mathf.Clamp01((float)(xp - rankByIndex.StartXp) / (float)Mathf.Max(1, rankByIndex.EndXp - rankByIndex.StartXp))); Image playerLevelMeter = hud.playerLevelMeter; if ((Object)(object)playerLevelMeter != (Object)null) { playerLevelMeter.fillAmount = fillAmount; } TextMeshProUGUI playerLevelText = hud.playerLevelText; if ((Object)(object)playerLevelText != (Object)null) { string text = ((direction == RankChangeDirection.Up) ? "#ffff00" : "#6969ff"); ((TMP_Text)playerLevelText).text = "" + rankByIndex.Name + ""; } TextMeshProUGUI playerLevelXPCounter = hud.playerLevelXPCounter; if ((Object)(object)playerLevelXPCounter != (Object)null) { ((TMP_Text)playerLevelXPCounter).text = $"{xp} XP"; } } private static void OnAnimatedRankUp(HUDManager hud, RoundXpBreakdown log, int rank, int totalMarksEarned, ref int marksShown, TextMeshProUGUI marksCounter) { int num = Mathf.Clamp(rank - log.OldRankIndex, 1, Mathf.Max(1, log.RanksGained)); if (totalMarksEarned > 0 && log.RanksGained > 0) { int num2 = Mathf.Clamp(Mathf.CeilToInt((float)totalMarksEarned * ((float)num / (float)log.RanksGained)), 0, totalMarksEarned); if (num2 > marksShown) { marksShown = num2; SetMarksCounter(marksCounter, marksShown, visible: true); PlayMarksGrantedSound(hud, num); } } PlayLevelUpOneShot(hud); if ((Object)(object)hud.playerLevelBoxAnimator != (Object)null && ((Behaviour)hud.playerLevelBoxAnimator).isActiveAndEnabled) { hud.playerLevelBoxAnimator.SetTrigger("Shake"); } } private static TextMeshProUGUI EnsureMarksCounter(HUDManager hud) { //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_006c: 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_0088: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_01a0: Unknown result type (might be due to invalid IL or missing references) RectTransform val = FindVanillaLevelUpBox(hud); if ((Object)(object)val == (Object)null) { return null; } RemoveMisplacedTokenStrips((Transform)(object)val); TextMeshProUGUI val2 = FindMarksCounter(val); if ((Object)(object)val2 != (Object)null) { UpdateMarksStripLayout(((TMP_Text)val2).transform.parent, val); return val2; } GameObject val3 = EnsureMarksStrip(val); TextMeshProUGUI val4 = FindEmployeeRankTitleText(FindTextSearchRoot(hud, val), hud); GameObject val5 = new GameObject("Y4NGZ_TokensGrantedCounter"); val5.transform.SetParent(val3.transform, false); val5.transform.SetAsLastSibling(); RectTransform obj = val5.AddComponent(); obj.anchorMin = new Vector2(0.03f, 0f); obj.anchorMax = new Vector2(0.97f, 1f); obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; TextMeshProUGUI val6 = val5.AddComponent(); if ((Object)(object)val4 != (Object)null) { ((TMP_Text)val6).font = ((TMP_Text)val4).font; ((TMP_Text)val6).fontSharedMaterial = ((TMP_Text)val4).fontSharedMaterial; float num = (((Object)(object)hud.playerLevelXPCounter != (Object)null) ? (((TMP_Text)hud.playerLevelXPCounter).fontSize * 0.58f) : 0f); ((TMP_Text)val6).fontSize = Mathf.Clamp(Mathf.Max(((TMP_Text)val4).fontSize * 0.58f, num), 16f, 34f); } else { ((TMP_Text)val6).fontSize = 24f; } ((TMP_Text)val6).fontStyle = (FontStyles)(((Object)(object)val4 != (Object)null) ? ((int)((TMP_Text)val4).fontStyle) : 0); ((TMP_Text)val6).alignment = (TextAlignmentOptions)514; ((TMP_Text)val6).enableWordWrapping = false; ((TMP_Text)val6).overflowMode = (TextOverflowModes)1; ((Graphic)val6).raycastTarget = false; ((TMP_Text)val6).richText = true; ((Graphic)val6).color = new Color(1f, 0.86f, 0.24f, 1f); ((TMP_Text)val6).characterSpacing = 0f; val3.SetActive(false); return val6; } private static GameObject EnsureMarksStrip(RectTransform levelUpBox) { //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_003a: 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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: 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_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Expected O, but got Unknown Transform val = ((Transform)levelUpBox).Find("Y4NGZ_TokensGrantedExtension"); if ((Object)(object)val != (Object)null) { UpdateMarksStripLayout(val, levelUpBox); return ((Component)val).gameObject; } GameObject val2 = new GameObject("Y4NGZ_TokensGrantedExtension"); val2.transform.SetParent((Transform)(object)levelUpBox, false); val2.transform.SetAsLastSibling(); ApplyTokenStripLayout(val2.AddComponent(), levelUpBox); val2.AddComponent().Reference = levelUpBox; Image obj = val2.AddComponent(); ((Graphic)obj).color = new Color(0.18f, 0f, 0f, 0.72f); ((Graphic)obj).raycastTarget = false; Color color = default(Color); ((Color)(ref color))..ctor(1f, 0f, 0f, 0.92f); AddHorizontalFrameLine(val2.transform, "Top", 1f, -0.7f, color); AddHorizontalFrameLine(val2.transform, "Bottom", 0f, 0.7f, color); AddVerticalFrameLine(val2.transform, "Left", 0f, 0.7f, color); AddVerticalFrameLine(val2.transform, "Right", 1f, -0.7f, color); val2.SetActive(false); return val2; } private static void UpdateMarksStripLayout(Transform strip, RectTransform levelUpBox) { if (!((Object)(object)strip == (Object)null)) { RectTransform val = (RectTransform)(object)((strip is RectTransform) ? strip : null); if (val != null) { ApplyTokenStripLayout(val, levelUpBox); } TokensGrantedLifetime tokensGrantedLifetime = ((Component)strip).GetComponent(); if ((Object)(object)tokensGrantedLifetime == (Object)null) { tokensGrantedLifetime = ((Component)strip).gameObject.AddComponent(); } tokensGrantedLifetime.Reference = levelUpBox; } } private static void ApplyTokenStripLayout(RectTransform rect, RectTransform levelUpBox) { //IL_0088: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: 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_0032: 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_005c: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { if (HasCanvasRoomBelow(levelUpBox)) { rect.anchorMin = new Vector2(0.035f, 0f); rect.anchorMax = new Vector2(0.965f, 0f); rect.pivot = new Vector2(0.5f, 1f); rect.offsetMin = new Vector2(0f, -62f); rect.offsetMax = new Vector2(0f, -10f); } else { rect.anchorMin = new Vector2(0.035f, 1f); rect.anchorMax = new Vector2(0.965f, 1f); rect.pivot = new Vector2(0.5f, 0f); rect.offsetMin = new Vector2(0f, 10f); rect.offsetMax = new Vector2(0f, 62f); } ((Transform)rect).localScale = Vector3.one; ((Transform)rect).localRotation = Quaternion.identity; } } private static bool HasCanvasRoomBelow(RectTransform levelUpBox) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_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) if ((Object)(object)levelUpBox == (Object)null) { return true; } Canvas componentInParent = ((Component)levelUpBox).GetComponentInParent(); RectTransform val = (RectTransform)(((Object)(object)componentInParent != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null); if ((Object)(object)val == (Object)null) { return true; } levelUpBox.GetWorldCorners(TokenStripWorldCorners); float y = ((Transform)val).InverseTransformPoint(TokenStripWorldCorners[0]).y; float num = 66f; float num2 = y - num; Rect rect = val.rect; return num2 >= ((Rect)(ref rect)).yMin; } private static void AddHorizontalFrameLine(Transform parent, string name, float yAnchor, float yOffset, Color color) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0061: 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_0085: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Frame" + name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(0f, yAnchor); obj.anchorMax = new Vector2(1f, yAnchor); obj.pivot = new Vector2(0.5f, 0.5f); obj.anchoredPosition = new Vector2(0f, yOffset); obj.sizeDelta = new Vector2(0f, 1.4f); Image obj2 = val.AddComponent(); ((Graphic)obj2).color = color; ((Graphic)obj2).raycastTarget = false; } private static void AddVerticalFrameLine(Transform parent, string name, float xAnchor, float xOffset, Color color) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0061: 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_0085: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Frame" + name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(xAnchor, 0f); obj.anchorMax = new Vector2(xAnchor, 1f); obj.pivot = new Vector2(0.5f, 0.5f); obj.anchoredPosition = new Vector2(xOffset, 0f); obj.sizeDelta = new Vector2(1.4f, 0f); Image obj2 = val.AddComponent(); ((Graphic)obj2).color = color; ((Graphic)obj2).raycastTarget = false; } private static RectTransform FindVanillaLevelUpBox(HUDManager hud) { GameObject val = GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpBox"); RectTransform result = default(RectTransform); if ((Object)(object)val != (Object)null && val.TryGetComponent(ref result)) { return result; } RectTransform val2 = FindCommonRankPanelRoot(hud); if ((Object)(object)val2 != (Object)null) { return val2; } GameObject[] array = Resources.FindObjectsOfTypeAll(); RectTransform result2 = default(RectTransform); foreach (GameObject val3 in array) { if (!((Object)(object)val3 == (Object)null) && !(((Object)val3).name != "LevelUpBox") && val3.TryGetComponent(ref result2)) { return result2; } } return null; } private static RectTransform FindCommonRankPanelRoot(HUDManager hud) { if ((Object)(object)hud == (Object)null || (Object)(object)hud.playerLevelMeter == (Object)null) { return null; } if ((Object)(object)hud.playerLevelMeter != (Object)null) { Transform val = (Transform)(object)((Graphic)hud.playerLevelMeter).rectTransform; while ((Object)(object)val != (Object)null) { RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); if (val2 != null && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelMeter) && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelText) && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelXPCounter)) { return val2; } val = val.parent; } } return null; } private static RectTransform FindTextSearchRoot(HUDManager hud, RectTransform fallback) { if ((Object)(object)hud != (Object)null && (Object)(object)hud.playerLevelText != (Object)null) { Transform val = ((TMP_Text)hud.playerLevelText).transform; while ((Object)(object)val != (Object)null) { RectTransform val2 = (RectTransform)(object)((val is RectTransform) ? val : null); if (val2 != null && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelMeter) && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelText) && ContainsTransform((Transform)(object)val2, (Component)(object)hud.playerLevelXPCounter)) { return val2; } val = val.parent; } } if ((Object)(object)hud != (Object)null) { Transform transform = ((Component)hud).transform; RectTransform val3 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if (val3 != null) { return val3; } } return fallback; } private static bool ContainsTransform(Transform root, Component child) { if ((Object)(object)child == (Object)null || (Object)(object)root == (Object)null) { return true; } Transform transform = child.transform; if (!((Object)(object)transform == (Object)(object)root)) { return transform.IsChildOf(root); } return true; } private static TextMeshProUGUI FindMarksCounter(HUDManager hud) { RectTransform val = FindVanillaLevelUpBox(hud); if (!((Object)(object)val != (Object)null)) { return null; } return FindMarksCounter(val); } private static TextMeshProUGUI FindMarksCounter(RectTransform root) { TextMeshProUGUI[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (TextMeshProUGUI val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)((Component)val).gameObject).name == "Y4NGZ_TokensGrantedCounter") { return val; } } return null; } private static TextMeshProUGUI FindEmployeeRankTitleText(RectTransform root, HUDManager hud) { TextMeshProUGUI[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (TextMeshProUGUI val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !(((Object)((Component)val).gameObject).name == "Y4NGZ_TokensGrantedCounter")) { string text = (((TMP_Text)val).text ?? string.Empty).ToUpperInvariant(); if (text.Contains("EMPLOYEE") && text.Contains("RANK")) { return val; } } } foreach (TextMeshProUGUI val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2 == (Object)(object)hud.playerLevelText) && !((Object)(object)val2 == (Object)(object)hud.playerLevelXPCounter) && !(((Object)((Component)val2).gameObject).name == "Y4NGZ_TokensGrantedCounter") && ((Object)((Component)val2).gameObject).name.IndexOf("rank", StringComparison.OrdinalIgnoreCase) >= 0) { return val2; } } if (!((Object)(object)hud.playerLevelText != (Object)null)) { return hud.playerLevelXPCounter; } return hud.playerLevelText; } private static void HideMarksCounter(HUDManager hud) { SetMarksCounter(FindMarksCounter(hud), 0, visible: false); SetAllTokenStripsActive(hud, active: false); } private static void SetMarksCounter(TextMeshProUGUI counter, int marks, bool visible) { if (!((Object)(object)counter == (Object)null)) { bool flag = visible && marks > 0; GameObject obj = (((Object)(object)((TMP_Text)counter).transform.parent != (Object)null && ((Object)((Component)((TMP_Text)counter).transform.parent).gameObject).name == "Y4NGZ_TokensGrantedExtension") ? ((Component)((TMP_Text)counter).transform.parent).gameObject : ((Component)counter).gameObject); obj.SetActive(flag); TokensGrantedLifetime component = obj.GetComponent(); if ((Object)(object)component != (Object)null && flag) { component.Extend(9f); } if (marks > 0) { ((TMP_Text)counter).text = ((marks == 1) ? "1 TOKEN GRANTED" : $"{marks} TOKENS GRANTED"); } } } private static void RemoveMisplacedTokenStrips(Transform expectedParent) { if ((Object)(object)expectedParent == (Object)null) { return; } RectTransform[] array = Resources.FindObjectsOfTypeAll(); for (int i = 0; i < array.Length; i++) { Transform val = (Transform)(object)array[i]; if (IsTokenStripName(((Object)val).name) && !((Object)(object)val.parent == (Object)(object)expectedParent)) { ((Component)val).gameObject.SetActive(false); Object.Destroy((Object)(object)((Component)val).gameObject); } } } private static void SetAllTokenStripsActive(HUDManager hud, bool active) { RectTransform[] array = Resources.FindObjectsOfTypeAll(); for (int i = 0; i < array.Length; i++) { Transform val = (Transform)(object)array[i]; if (IsTokenStripName(((Object)val).name)) { ((Component)val).gameObject.SetActive(active); } } } private static bool IsTokenStripName(string name) { if (!string.Equals(name, "Y4NGZ_TokensGrantedExtension", StringComparison.Ordinal) && !string.Equals(name, "Y4NGZ_MarksGrantedStrip", StringComparison.Ordinal)) { return string.Equals(name, "Y4NGZ_MarksGrantedExtension", StringComparison.Ordinal); } return true; } private static void EnsureMarksSoundLoading() { if (!((Object)(object)_marksGrantedClip != (Object)null) && !_marksGrantedClipLoadStarted) { MonoBehaviour val = (((Object)(object)_coroutineHost != (Object)null) ? _coroutineHost : Y4NGZPersistentRunner.Host); if (!((Object)(object)val == (Object)null)) { _marksGrantedClipLoadStarted = true; val.StartCoroutine(LoadMarksSoundClip()); } } } private static IEnumerator LoadMarksSoundClip() { string path = FindMarksSoundPath(); if (string.IsNullOrWhiteSpace(path)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Progression] Tokens granted sound not found under Assets/UI."); } yield break; } UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)13); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Progression] Failed to load tokens granted sound '" + path + "': " + request.error)); } yield break; } _marksGrantedClip = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)_marksGrantedClip != (Object)null) { ((Object)_marksGrantedClip).name = "Y4NGZ_TokensGranted"; } } finally { ((IDisposable)request)?.Dispose(); } } private static string FindMarksSoundPath() { string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, "Assets", "UI", "juniorsoundays-ui-sound-67-527859.mp3"); if (File.Exists(text)) { return text; } } string text2 = Path.Combine(Paths.PluginPath, "Y4NGZUpgrades", "Assets", "UI", "juniorsoundays-ui-sound-67-527859.mp3"); if (!File.Exists(text2)) { return null; } return text2; } private static void PlayMarksGrantedSound(HUDManager hud, int rankUpNumber) { //IL_0018: 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_0023: Expected O, but got Unknown //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown EnsureMarksSoundLoading(); if (!((Object)(object)_marksGrantedClip == (Object)null)) { GameObject val = new GameObject("Y4NGZ_TokensGrantedSfx"); Object.DontDestroyOnLoad((Object)val); AudioSource val2 = val.AddComponent(); val2.playOnAwake = false; val2.loop = false; val2.spatialBlend = 0f; val2.volume = 0.85f; val2.pitch = Mathf.Clamp(1f + (float)(Mathf.Max(1, rankUpNumber) - 1) * 0.075f, 1f, 1.55f); val2.clip = _marksGrantedClip; if ((Object)(object)hud != (Object)null && (Object)(object)hud.UIAudio != (Object)null) { val2.outputAudioMixerGroup = hud.UIAudio.outputAudioMixerGroup; } val2.Play(); float num = Mathf.Max(0.1f, _marksGrantedClip.length / Mathf.Max(0.1f, val2.pitch)) + 0.25f; Object.Destroy((Object)val, num); } } } public readonly struct RankDefinition { public readonly string Name; public readonly int StartXp; public readonly int EndXp; public RankDefinition(string name, int startXp, int endXp) { Name = name; StartXp = startXp; EndXp = endXp; } } public static class RankCatalog { public const string DefaultXpRequiredPerLevel = "150,150,150,150,150,180,200,230,260,290,330,370,420,470,540,600,680,770,870,980,1110,1250,1410,1590,1800,2000,2000,2000,2000,2000"; private static readonly string[] DefaultRankNames; private static int[] _curve; private static string[] _rankNames; private static RankDefinition[] Ranks; private static int _tokensRanks1To5; private static int _tokensRanks6To10; private static int _tokensRanks11To19; private static int _tokensRanks20To30; public static int MaxRankXp { get; private set; } internal static int DefaultRankCount => DefaultRankNames.Length; public static int Count => Ranks.Length; public static int EarnableRankCount => Ranks.Length - 1; static RankCatalog() { MaxRankXp = 25100; DefaultRankNames = new string[31] { "Applicant", "Probationary Intern", "Dock Intern", "Scrap Trainee", "Field Trainee", "Junior Runner", "Scrap Runner", "Route Runner", "Quota Runner", "Salvage Hand", "Certified Hand", "Facility Scout", "Hazard Scout", "Quota Scout", "Recovery Tech", "Senior Recovery Tech", "Ship Operator", "Route Operator", "Field Operator", "Quota Operator", "Crew Lead", "Salvage Lead", "Hazard Lead", "Route Supervisor", "Quota Supervisor", "Site Manager", "Operations Manager", "Sector Manager", "Regional Asset", "Executive Asset", "Company Asset" }; _tokensRanks1To5 = 5; _tokensRanks6To10 = 8; _tokensRanks11To19 = 12; _tokensRanks20To30 = 15; ProgressionEconomyMath.TryParsePositiveIntCsv("150,150,150,150,150,180,200,230,260,290,330,370,420,470,540,600,680,770,870,980,1110,1250,1410,1590,1800,2000,2000,2000,2000,2000", DefaultRankNames.Length - 1, out var result); _rankNames = (string[])DefaultRankNames.Clone(); ApplyCurve(result); } internal static void Configure(ProgressionSettings config) { string[] array = config?.GetRankNames(); int[] result = config?.GetRankWidths(); if (array == null || array.Length != DefaultRankNames.Length) { array = (string[])DefaultRankNames.Clone(); } if (result == null || result.Length != DefaultRankNames.Length - 1) { ProgressionEconomyMath.TryParsePositiveIntCsv("150,150,150,150,150,180,200,230,260,290,330,370,420,470,540,600,680,770,870,980,1110,1250,1410,1590,1800,2000,2000,2000,2000,2000", DefaultRankNames.Length - 1, out result); } _rankNames = array; ApplyCurve(result); _tokensRanks1To5 = Mathf.Max(0, config?.TokensRanks1To5?.Value ?? 5); _tokensRanks6To10 = Mathf.Max(0, config?.TokensRanks6To10?.Value ?? 8); _tokensRanks11To19 = Mathf.Max(0, config?.TokensRanks11To19?.Value ?? 12); _tokensRanks20To30 = Mathf.Max(0, config?.TokensRanks20To30?.Value ?? 15); } internal static string GetDefaultRankName(int index) { return DefaultRankNames[Mathf.Clamp(index, 0, DefaultRankNames.Length - 1)]; } internal static int GetDefaultRankWidth(int index) { ProgressionEconomyMath.TryParsePositiveIntCsv("150,150,150,150,150,180,200,230,260,290,330,370,420,470,540,600,680,770,870,980,1110,1250,1410,1590,1800,2000,2000,2000,2000,2000", DefaultRankNames.Length - 1, out var result); return result[Mathf.Clamp(index, 0, result.Length - 1)]; } public static int ClampXp(int xp) { return Mathf.Clamp(xp, 0, MaxRankXp); } public static RankDefinition GetRank(int xp) { return Ranks[GetRankIndex(xp)]; } public static RankDefinition GetRankByIndex(int index) { return Ranks[Mathf.Clamp(index, 0, Ranks.Length - 1)]; } public static int GetRankIndex(int xp) { return ProgressionEconomyMath.GetRankIndex(_curve, ClampXp(xp)); } public static float GetProgress(int xp) { xp = ClampXp(xp); int rankIndex = GetRankIndex(xp); if (rankIndex >= Ranks.Length - 1) { return 1f; } RankDefinition rankDefinition = Ranks[rankIndex]; return Mathf.Clamp01((float)(xp - rankDefinition.StartXp) / (float)Mathf.Max(1, rankDefinition.EndXp - rankDefinition.StartXp)); } public static int GetRankWidth(int rankIndex) { return ProgressionEconomyMath.GetRankWidth(_curve, rankIndex); } public static int GetTokenGrantForRankIndex(int rankIndex) { if (rankIndex <= 0) { return 0; } if (rankIndex <= 5) { return _tokensRanks1To5; } return ProgressionEconomyMath.GetTokenGrantForRankIndex(rankIndex, EarnableRankCount, _tokensRanks1To5, _tokensRanks6To10, _tokensRanks11To19, _tokensRanks20To30); } public static int GetTokenGrantForRankRange(int firstRankIndex, int finalRankIndex) { return ProgressionEconomyMath.GetTokenGrantForRankRange(firstRankIndex, finalRankIndex, EarnableRankCount, _tokensRanks1To5, _tokensRanks6To10, _tokensRanks11To19, _tokensRanks20To30); } public static int GetVanillaRankIndex(int xp) { xp = ClampXp(xp); if (xp >= GetRankByIndex(25).StartXp) { return 4; } if (xp >= GetRankByIndex(19).StartXp) { return 3; } if (xp >= GetRankByIndex(10).StartXp) { return 2; } if (xp >= GetRankByIndex(5).StartXp) { return 1; } return 0; } private static void ApplyCurve(int[] widths) { _curve = widths; Ranks = BuildRanks(widths); MaxRankXp = Ranks[Ranks.Length - 1].StartXp; } private static RankDefinition[] BuildRanks(int[] widths) { RankDefinition[] array = new RankDefinition[_rankNames.Length]; int num = 0; for (int i = 0; i < widths.Length; i++) { int num2 = num + Mathf.Max(1, widths[i]); array[i] = new RankDefinition(_rankNames[i], num, num2); num = num2; } array[^1] = new RankDefinition(_rankNames[_rankNames.Length - 1], num, num + 1); return array; } } internal sealed class RoundLatch { internal int Sequence { get; private set; } internal bool Active { get; private set; } internal bool Finalized { get; private set; } internal bool FinalizedWithoutStart { get; private set; } internal void Begin() { Sequence++; Active = true; Finalized = false; FinalizedWithoutStart = false; } internal bool TryBeginFinalize(out bool recoveredMissedStart) { recoveredMissedStart = false; if (Finalized) { return false; } if (!Active) { recoveredMissedStart = true; FinalizedWithoutStart = true; if (Sequence <= 0) { Sequence = 1; } Active = true; } return true; } internal void CompleteFinalize() { Finalized = true; Active = false; } internal void Abandon() { Active = false; Finalized = false; FinalizedWithoutStart = false; } } [HarmonyPatch] internal static class RoundLifecycle { private static bool _startedThisRound; private static bool _endedThisRound; private static bool _installed; internal static event Action RoundStarted; internal static event Action RoundEnded; internal static void Install() { if (!_installed) { _installed = true; RoundStarted += ProgressionManager.BeginRound; RoundStarted += EmployeeStatistics.BeginRound; RoundStarted += ProgressionXpBarUi.ResetForRound; RoundStarted += ProgressionOrbitNameTags.OnRoundStarted; RoundStarted += CombatFeedbackPatch.OnRoundStarted; RoundStarted += WorldFeedbackPatch.OnRoundStarted; RoundStarted += AdrenalineRushPatch.OnRoundStarted; RoundStarted += CommandNetPatch.OnRoundStarted; RoundStarted += CourierDronePatch.OnRoundStarted; RoundStarted += EscapeArtistDoubleJumpPatch.OnRoundStarted; RoundStarted += EscapeReflexPatch.OnRoundStarted; RoundStarted += FieldMechanicCompanyPatch.OnRoundStarted; RoundStarted += ForemanPingPatch.OnRoundStarted; RoundStarted += ForemanSupportPatch.OnRoundStarted; RoundStarted += GlowInTheDarkPatch.OnRoundStarted; RoundStarted += LedgeMantlePatch.OnRoundStarted; RoundStarted += NativeFistsPatch.OnRoundStarted; RoundStarted += PanicSlidePatch.OnRoundStarted; RoundStarted += ShadowStepPatch.OnRoundStarted; RoundStarted += ShoulderCheckPatch.OnRoundStarted; RoundStarted += SixthSensePatch.OnRoundStarted; RoundStarted += SquadSightPatch.OnRoundStarted; RoundStarted += TurretHackerPatch.OnRoundStarted; RoundStarted += WorklightBeaconPatch.OnRoundStarted; RoundEnded += FinalizeProgression; } } private static void FinalizeProgression() { int scrapCollected = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.scrapCollectedLastRound : 0); ProgressionManager.FinalizeRound(scrapCollected); EmployeeStatistics.FinalizeRound(scrapCollected); } private static void RaiseRoundStarted() { if (!_startedThisRound) { _startedThisRound = true; _endedThisRound = false; Dispatch(RoundLifecycle.RoundStarted, "RoundStarted"); } } private static void RaiseRoundEnded() { if (!_endedThisRound) { _endedThisRound = true; _startedThisRound = false; Dispatch(RoundLifecycle.RoundEnded, "RoundEnded"); } } private static void ForceRoundOver(string reason) { _startedThisRound = false; _endedThisRound = true; ProgressionManager.AbandonUnfinalizedRound(reason); EmployeeStatistics.AbandonUnfinalizedRound(); } private static void Dispatch(Action handlers, string label) { if (handlers == null) { return; } Delegate[] invocationList = handlers.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { try { ((Action)invocationList[i])(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[RoundLifecycle] {label} subscriber {invocationList[i].Method?.DeclaringType?.Name}.{invocationList[i].Method?.Name} threw: {ex}"); } } } } [HarmonyPatch(typeof(StartOfRound), "openingDoorsSequence")] [HarmonyPostfix] private static void PostOpeningDoorsSequence() { RaiseRoundStarted(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { RaiseRoundEnded(); } [HarmonyPatch(typeof(StartOfRound), "SetShipReadyToLand")] [HarmonyPostfix] private static void PostSetShipReadyToLand() { ForceRoundOver("ship ready to land"); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { ForceRoundOver("disconnect"); } } public sealed class RoundXpBreakdown { public int RoundSequence; public int OldXp; public int NewXp; public int ScrapPickupXp; public int ScrapDeliveredXp; public int MonsterKillXp; public int SurvivalXp; public int MainframeHackXp; public int ClutchXp; public int ContractXp; public int ContractXpAwarded; public int BodyRetrievalXp; public int BodyRetrievalXpAwarded; public float MoonMultiplier = 1f; public string MoonRisk = "C"; public int RawTotal; public int AwardedTotal; public int OldRankIndex; public int NewRankIndex; public int RanksGained; public int CurrencyGranted; public int PositiveRawTotal => Mathf.Max(0, ScrapPickupXp) + Mathf.Max(0, ScrapDeliveredXp) + Mathf.Max(0, MonsterKillXp) + Mathf.Max(0, SurvivalXp) + Mathf.Max(0, MainframeHackXp) + Mathf.Max(0, ClutchXp) + Mathf.Max(0, ContractXp) + Mathf.Max(0, BodyRetrievalXp); public int PositiveAwardedTotal => Mathf.Max(0, ScrapPickupXp) + Mathf.Max(0, ScrapDeliveredXp) + Mathf.Max(0, MonsterKillXp) + Mathf.Max(0, SurvivalXp) + Mathf.Max(0, MainframeHackXp) + Mathf.Max(0, ClutchXp) + Mathf.Max(0, ContractXpAwarded) + Mathf.Max(0, BodyRetrievalXpAwarded); public RoundXpBreakdown Clone() { return (RoundXpBreakdown)MemberwiseClone(); } } internal static class SaveDataFile { internal static void WriteAllLinesAtomic(string path, IEnumerable lines) { string directoryName = Path.GetDirectoryName(path); if (!string.IsNullOrWhiteSpace(directoryName)) { Directory.CreateDirectory(directoryName); } string text = path + ".tmp." + Guid.NewGuid().ToString("N"); string text2 = path + ".bak"; try { File.WriteAllLines(text, lines); if (File.Exists(path)) { TryDelete(text2); try { File.Replace(text, path, text2, ignoreMetadataErrors: true); } catch (PlatformNotSupportedException) { File.Copy(text, path, overwrite: true); TryDelete(text); } TryDelete(text2); } else { File.Move(text, path); } } finally { TryDelete(text); } } private static void TryDelete(string path) { try { if (File.Exists(path)) { File.Delete(path); } } catch { } } } internal static class SaveDataLifecycle { private static readonly string[] SidecarDirectoryNames = new string[3] { "Y4NGZAmmoReserve", "Y4NGZPlayerLevel", "Y4NGZEmployeeFile" }; internal static void DeleteSave(string key, string reason) { DeleteSaves(new string[1] { key }, reason); } internal static void ReconcileOrphans() { try { HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); hashSet.UnionWith(ProgressionManager.GetKnownSaveKeys()); hashSet.UnionWith(Y4NGZUpgradeManager.GetKnownSaveKeys()); CollectSidecarKeys(hashSet); SaveSlotSnapshot[] snapshots = SaveKey.ReadManagedSlotSnapshots(); IReadOnlyList readOnlyList = SaveIdentityCleanupPolicy.FindOrphans(hashSet, snapshots); if (readOnlyList.Count != 0) { DeleteSaves(readOnlyList, "startup orphan reconciliation"); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Save-data orphan reconciliation skipped safely: " + ex.Message)); } } } private static void DeleteSaves(IEnumerable keys, string reason) { string saveFileName2; string[] array = (keys ?? Enumerable.Empty()).Where((string key2) => SaveIdentityCleanupPolicy.TryGetManagedSlotName(key2, out saveFileName2)).Distinct(StringComparer.OrdinalIgnoreCase).ToArray(); if (array.Length == 0) { return; } int num = 0; foreach (string key in array) { SaveIdentityApi.RaiseSaveKeyDeleted(key); if (PlayerLevelStore.DeleteForKey(key)) { num++; } if (EmployeeStatistics.DeleteForKey(key)) { num++; } if (!SaveIdentityCleanupPolicy.IsLegacyBareSlotKey(key) && SaveIdentityCleanupPolicy.TryGetManagedSlotName(key, out var saveFileName)) { SaveIdentityApi.RaiseSaveKeyDeleted(saveFileName); if (PlayerLevelStore.DeleteForKey(saveFileName)) { num++; } if (EmployeeStatistics.DeleteForKey(saveFileName)) { num++; } } } int num3 = 0; int num4 = 0; try { num3 = ProgressionManager.DeleteForKeys(array); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Failed pruning progression rows: " + ex.Message)); } } try { num4 = Y4NGZUpgradeManager.DeleteForKeys(array); } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Y4NGZUpgrades] Failed pruning upgrade rows: " + ex2.Message)); } } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)($"[Y4NGZUpgrades] Cleaned {array.Length} save identity(s) after {reason}; " + $"removed {num} sidecar file(s), " + $"{num3} progression row(s), and " + $"{num4} upgrade row(s).")); } } private static void CollectSidecarKeys(ISet candidates) { for (int i = 0; i < SidecarDirectoryNames.Length; i++) { string path = Path.Combine(Paths.ConfigPath, SidecarDirectoryNames[i]); if (!Directory.Exists(path)) { continue; } string[] files = Directory.GetFiles(path, "*.json", SearchOption.TopDirectoryOnly); for (int j = 0; j < files.Length; j++) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(files[j]); if (!string.IsNullOrWhiteSpace(fileNameWithoutExtension)) { candidates.Add(fileNameWithoutExtension); } } } } } [HarmonyPatch(typeof(DeleteFileButton), "DeleteFile")] internal static class SaveDeletionPatches { private sealed class DeleteState { internal string SaveFileName { get; } internal string SaveKey { get; } internal DeleteState(string saveFileName, string saveKey) { SaveFileName = saveFileName; SaveKey = saveKey; } } [HarmonyPrefix] private static void Prefix(DeleteFileButton __instance, out DeleteState __state) { __state = null; string saveFileName = GetSaveFileName(__instance?.fileToDelete ?? (-1)); if (saveFileName != null && SaveKey.TryGetExistingForSaveFile(saveFileName, out var key)) { __state = new DeleteState(saveFileName, key); } } [HarmonyPostfix] private static void Postfix(DeleteState __state) { string text = __state?.SaveFileName; string text2 = __state?.SaveKey; bool exists = default(bool); if (!(string.IsNullOrWhiteSpace(text) || string.IsNullOrWhiteSpace(text2) || !SaveKey.TrySaveFileExists(text, out exists) || exists)) { SaveDataLifecycle.DeleteSave(text2, "manual vanilla save deletion"); } } private static string GetSaveFileName(int fileNumber) { return fileNumber switch { 0 => "LCSaveFile1", 1 => "LCSaveFile2", 2 => "LCSaveFile3", _ => null, }; } } public static class SaveIdentityApi { public const int ProtocolVersion = 1; public static event Action StoresRepointed; public static event Action SaveKeyDeleted; public static string GetCurrentSaveKey() { if (!SaveKey.TryGetCurrent(out var key)) { return null; } return key; } public static string GetCurrentExistingOrSlotSaveKey() { if (!SaveKey.TryGetCurrentExistingOrSlot(out var key)) { return null; } return key; } internal static void RaiseStoresRepointed() { Raise(SaveIdentityApi.StoresRepointed); } internal static void RaiseSaveKeyDeleted(string key) { if (string.IsNullOrWhiteSpace(key)) { return; } Action saveKeyDeleted = SaveIdentityApi.SaveKeyDeleted; if (saveKeyDeleted == null) { return; } Delegate[] invocationList = saveKeyDeleted.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { try { ((Action)invocationList[i])(key); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SaveIdentityApi] SaveKeyDeleted subscriber threw: " + ex.Message)); } } } } private static void Raise(Action handlers) { if (handlers == null) { return; } Delegate[] invocationList = handlers.GetInvocationList(); for (int i = 0; i < invocationList.Length; i++) { try { ((Action)invocationList[i])(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[SaveIdentityApi] StoresRepointed subscriber threw: " + ex.Message)); } } } } } internal readonly struct SaveSlotSnapshot { internal readonly string SaveFileName; internal readonly bool StatusKnown; internal readonly bool FileExists; internal readonly string LiveKey; internal SaveSlotSnapshot(string saveFileName, bool statusKnown, bool fileExists, string liveKey) { SaveFileName = saveFileName; StatusKnown = statusKnown; FileExists = fileExists; LiveKey = liveKey; } } internal static class SaveIdentityCleanupPolicy { internal static readonly string[] ManagedSlotNames = new string[3] { "LCSaveFile1", "LCSaveFile2", "LCSaveFile3" }; internal static IReadOnlyList FindOrphans(IEnumerable candidateKeys, IEnumerable snapshots) { Dictionary dictionary = (snapshots ?? Enumerable.Empty()).Where((SaveSlotSnapshot snapshot) => !string.IsNullOrWhiteSpace(snapshot.SaveFileName)).GroupBy((SaveSlotSnapshot snapshot) => snapshot.SaveFileName, StringComparer.OrdinalIgnoreCase).ToDictionary, string, SaveSlotSnapshot>((IGrouping group) => group.Key, (IGrouping group) => group.Last(), StringComparer.OrdinalIgnoreCase); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string item in candidateKeys ?? Enumerable.Empty()) { if (TryGetManagedSlotName(item, out var saveFileName) && dictionary.TryGetValue(saveFileName, out var value) && value.StatusKnown) { if (!value.FileExists) { hashSet.Add(item); } else if (!IsLegacyBareSlotKey(item) && !string.IsNullOrWhiteSpace(value.LiveKey) && !string.Equals(item, value.LiveKey, StringComparison.OrdinalIgnoreCase)) { hashSet.Add(item); } } } return hashSet.OrderBy((string key) => key, StringComparer.OrdinalIgnoreCase).ToArray(); } internal static bool IsLegacyBareSlotKey(string key) { if (!string.IsNullOrWhiteSpace(key) && key.IndexOf('#') < 0) { return IsManagedSlotName(key.Trim()); } return false; } private static bool IsManagedSlotName(string slot) { for (int i = 0; i < ManagedSlotNames.Length; i++) { if (string.Equals(slot, ManagedSlotNames[i], StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } internal static bool TryGetManagedSlotName(string key, out string saveFileName) { saveFileName = null; if (string.IsNullOrWhiteSpace(key)) { return false; } int num = key.IndexOf('#'); if (num < 0) { string text = key.Trim(); if (!IsManagedSlotName(text)) { return false; } saveFileName = text; return true; } if (num == 0 || num != key.LastIndexOf('#')) { return false; } string text2 = key.Substring(0, num); if (!IsManagedSlotName(text2)) { return false; } string text3 = key.Substring(num + 1); if (text3.Length != 32) { return false; } foreach (char c in text3) { if ((c < '0' || c > '9') && (c < 'a' || c > 'f') && (c < 'A' || c > 'F')) { return false; } } saveFileName = text2; return true; } } internal static class SaveKey { private enum IdentityReadStatus { Unknown, MissingFile, PresentWithoutIdentity, PresentWithIdentity } private const string SaveIdentityKey = "Y4NGZUpgrades_SaveIdentity"; private static readonly string[] ManagedSaveFiles = new string[3] { "LCSaveFile1", "LCSaveFile2", "LCSaveFile3" }; private static readonly PendingSaveIdentityStore PendingIdentities = new PendingSaveIdentityStore(); private static Type _es3Type; private static MethodInfo _es3FileExists; private static MethodInfo _es3KeyExists; private static MethodInfo _es3LoadWithDefault; private static MethodInfo _es3SaveObject; internal static bool TryGetCurrent(out string key) { return TryGetCurrentInternal(out key, allowSlotFallback: false, createIdentity: true); } internal static bool TryGetCurrentOrSlot(out string key) { return TryGetCurrentInternal(out key, allowSlotFallback: true, createIdentity: true); } internal static bool TryGetCurrentExistingOrSlot(out string key) { return TryGetCurrentInternal(out key, allowSlotFallback: true, createIdentity: false); } internal static void ClearPendingIdentities() { PendingIdentities.Clear(); } internal static bool TryGetExistingForSaveFile(string saveFileName, out string key) { key = null; if (ReadSaveIdentity(saveFileName, out var identity) != IdentityReadStatus.PresentWithIdentity) { return false; } key = BuildKey(saveFileName, identity); return true; } internal static bool TrySaveFileExists(string saveFileName, out bool exists) { exists = false; if (string.IsNullOrWhiteSpace(saveFileName) || !ResolveEs3()) { return false; } try { exists = (bool)_es3FileExists.Invoke(null, new object[1] { saveFileName.Trim() }); return true; } catch (Exception exception) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Could not test save file '" + saveFileName + "': " + UnwrapMessage(exception))); } return false; } } internal static SaveSlotSnapshot[] ReadManagedSlotSnapshots() { SaveSlotSnapshot[] array = new SaveSlotSnapshot[ManagedSaveFiles.Length]; for (int i = 0; i < ManagedSaveFiles.Length; i++) { string saveFileName = ManagedSaveFiles[i]; string identity; switch (ReadSaveIdentity(saveFileName, out identity)) { case IdentityReadStatus.MissingFile: array[i] = new SaveSlotSnapshot(saveFileName, statusKnown: true, fileExists: false, null); break; case IdentityReadStatus.PresentWithoutIdentity: array[i] = new SaveSlotSnapshot(saveFileName, statusKnown: true, fileExists: true, null); break; case IdentityReadStatus.PresentWithIdentity: array[i] = new SaveSlotSnapshot(saveFileName, statusKnown: true, fileExists: true, BuildKey(saveFileName, identity)); break; default: array[i] = new SaveSlotSnapshot(saveFileName, statusKnown: false, fileExists: false, null); break; } } return array; } private static bool TryGetCurrentInternal(out string key, bool allowSlotFallback, bool createIdentity) { key = null; string key2; switch (HostSaveIdentity.Resolve(out key2)) { case HostSaveScope.UseHostKey: key = key2; return true; case HostSaveScope.Pending: return false; default: { if (!TryGetBaseSaveFileName(out var saveName, allowSlotFallback)) { return false; } string identity; IdentityReadStatus identityReadStatus = ReadSaveIdentity(saveName, out identity); if (identityReadStatus == IdentityReadStatus.PresentWithIdentity) { PendingIdentities.MarkPersisted(saveName); key = BuildKey(saveName, identity); return true; } if (!createIdentity) { return false; } if (identityReadStatus == IdentityReadStatus.MissingFile && IsActiveAuthoritativeSession()) { if (!PendingIdentities.TryGet(saveName, out identity)) { if (!PendingIdentities.TryGetOrCreate(saveName, out identity)) { return false; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Y4NGZUpgrades] Reserved pending save identity for active fresh save '" + saveName + "': " + identity)); } } key = BuildKey(saveName, identity); return true; } if (identityReadStatus != IdentityReadStatus.PresentWithoutIdentity) { return false; } if (PendingIdentities.TryGet(saveName, out var identity2)) { if (!TryPersistSaveIdentity(saveName, identity2, out identity)) { return false; } PendingIdentities.MarkPersisted(saveName); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Y4NGZUpgrades] Persisted pending save identity for '" + saveName + "': " + identity)); } } else if (!TryCreateSaveIdentity(saveName, out identity)) { return false; } key = BuildKey(saveName, identity); return true; } } } private static bool TryGetBaseSaveFileName(out string saveName, bool allowSlotFallback) { saveName = GameNetworkManager.Instance?.currentSaveFileName; if (!string.IsNullOrWhiteSpace(saveName)) { saveName = saveName.Trim(); return saveName.Length > 0; } if (!allowSlotFallback) { saveName = null; return false; } GameNetworkManager instance = GameNetworkManager.Instance; if ((Object)(object)instance == (Object)null || instance.saveFileNum < 0 || instance.saveFileNum >= ManagedSaveFiles.Length) { saveName = null; return false; } saveName = ManagedSaveFiles[instance.saveFileNum]; return true; } private static bool IsActiveAuthoritativeSession() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsListening) { return singleton.IsServer; } return false; } private static IdentityReadStatus ReadSaveIdentity(string saveFileName, out string identity) { identity = null; if (string.IsNullOrWhiteSpace(saveFileName) || !ResolveEs3()) { return IdentityReadStatus.Unknown; } saveFileName = saveFileName.Trim(); try { if (!(bool)_es3FileExists.Invoke(null, new object[1] { saveFileName })) { return IdentityReadStatus.MissingFile; } if (!(bool)_es3KeyExists.Invoke(null, new object[2] { "Y4NGZUpgrades_SaveIdentity", saveFileName })) { return IdentityReadStatus.PresentWithoutIdentity; } object obj = _es3LoadWithDefault.Invoke(null, new object[3] { "Y4NGZUpgrades_SaveIdentity", saveFileName, "" }); identity = (obj as string) ?? obj?.ToString(); if (string.IsNullOrWhiteSpace(identity)) { identity = null; return IdentityReadStatus.PresentWithoutIdentity; } identity = identity.Trim(); if (!Guid.TryParseExact(identity, "N", out var _)) { identity = null; return IdentityReadStatus.PresentWithoutIdentity; } return IdentityReadStatus.PresentWithIdentity; } catch (Exception exception) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Save identity unavailable for '" + saveFileName + "': " + UnwrapMessage(exception))); } identity = null; return IdentityReadStatus.Unknown; } } private static bool TryCreateSaveIdentity(string saveFileName, out string identity) { string requestedIdentity = Guid.NewGuid().ToString("N"); if (!TryPersistSaveIdentity(saveFileName, requestedIdentity, out identity)) { return false; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Y4NGZUpgrades] Created save identity for '" + saveFileName + "': " + identity)); } return true; } private static bool TryPersistSaveIdentity(string saveFileName, string requestedIdentity, out string identity) { identity = requestedIdentity?.Trim(); if (string.IsNullOrWhiteSpace(saveFileName) || !Guid.TryParseExact(identity, "N", out var _)) { identity = null; return false; } try { if (!ResolveEs3()) { identity = null; return false; } if (!(bool)_es3FileExists.Invoke(null, new object[1] { saveFileName })) { identity = null; return false; } _es3SaveObject.Invoke(null, new object[3] { "Y4NGZUpgrades_SaveIdentity", identity, saveFileName }); return true; } catch (Exception exception) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Could not persist save identity for '" + saveFileName + "': " + UnwrapMessage(exception))); } identity = null; return false; } } private static string BuildKey(string saveFileName, string identity) { return saveFileName.Trim() + "#" + identity.Trim(); } private static bool ResolveEs3() { if (_es3Type != null) { if (_es3FileExists != null && _es3KeyExists != null && _es3LoadWithDefault != null) { return _es3SaveObject != null; } return false; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { try { _es3Type = assembly.GetType("ES3"); if (_es3Type != null) { break; } } catch { } } if (_es3Type == null) { return false; } _es3FileExists = _es3Type.GetMethod("FileExists", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null); _es3KeyExists = _es3Type.GetMethod("KeyExists", BindingFlags.Static | BindingFlags.Public, null, new Type[2] { typeof(string), typeof(string) }, null); _es3LoadWithDefault = _es3Type.GetMethod("Load", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(string), typeof(string), typeof(object) }, null); _es3SaveObject = _es3Type.GetMethod("Save", BindingFlags.Static | BindingFlags.Public, null, new Type[3] { typeof(string), typeof(object), typeof(string) }, null); if (_es3FileExists != null && _es3KeyExists != null && _es3LoadWithDefault != null) { return _es3SaveObject != null; } return false; } private static string UnwrapMessage(Exception exception) { if (!(exception is TargetInvocationException { InnerException: not null } ex)) { return exception.Message; } return ex.InnerException.Message; } } [Flags] internal enum OptionalUpgradeProvider { None = 0, Contracted = 1, LethalCctv = 2, BetterArmory = 4, NativeInventory = 8, ShipSystems = 0x10 } internal static class UpgradeCatalogTable { internal sealed class Entry { internal string Id { get; } internal string DisplayName { get; } internal Y4NGZSkillTreeClass TreeClass { get; } internal int Tier { get; } internal int Column { get; } internal int Row { get; } internal int SubTierCount { get; } internal string IconKey { get; } internal string Description { get; } internal string[] PrerequisiteUpgradeIds { get; } internal string[] ConnectionUpgradeIds { get; } internal OptionalUpgradeProvider RequiredProviders { get; } internal OptionalUpgradeProvider AnyProviders { get; } internal bool HasOptionalProviderRequirement { get { if (RequiredProviders == OptionalUpgradeProvider.None) { return AnyProviders != OptionalUpgradeProvider.None; } return true; } } internal int UnlockPrice => Tier; internal int[] TierPrices { get; } internal int MaxTier => UpgradePriceMath.GetMaxTier(TierPrices); internal int GateRequirement => GateForTier(TreeClass, Tier); internal int TotalPrice { get { int num = UnlockPrice; for (int i = 0; i < TierPrices.Length; i++) { num += TierPrices[i]; } return num; } } internal Entry(string id, string displayName, Y4NGZSkillTreeClass treeClass, int tier, int column, int row, int subTierCount, string iconKey, string description, string[] prerequisiteUpgradeIds = null, string[] connectionUpgradeIds = null, OptionalUpgradeProvider requiredProviders = OptionalUpgradeProvider.None, OptionalUpgradeProvider anyProviders = OptionalUpgradeProvider.None) { if (subTierCount < 1) { throw new ArgumentOutOfRangeException("subTierCount", "Upgrade '" + id + "' needs at least one sub-tier."); } if (tier < 1) { throw new ArgumentOutOfRangeException("tier", "Upgrade '" + id + "' needs a tree tier of 1 or more."); } Id = id; DisplayName = displayName; TreeClass = treeClass; Tier = tier; Column = column; Row = row; SubTierCount = subTierCount; IconKey = iconKey; Description = description ?? string.Empty; PrerequisiteUpgradeIds = prerequisiteUpgradeIds ?? Array.Empty(); ConnectionUpgradeIds = connectionUpgradeIds ?? Array.Empty(); RequiredProviders = requiredProviders; AnyProviders = anyProviders; int[] array = new int[subTierCount - 1]; for (int i = 0; i < array.Length; i++) { array[i] = tier + 1 + i; } TierPrices = array; } internal bool IsAvailable(OptionalUpgradeProvider installedProviders) { bool num = (RequiredProviders & installedProviders) == RequiredProviders; bool flag = AnyProviders == OptionalUpgradeProvider.None || (AnyProviders & installedProviders) != 0; return num && flag; } } internal static readonly int[] DefaultTierGates = new int[4] { 0, 3, 7, 11 }; private static readonly Entry[] Ordered = new Entry[27] { new Entry("back_muscles", "Transporter", Y4NGZSkillTreeClass.Enforcer, 1, 0, 0, 3, "transporter", "Description: Cuts the movement and stamina penalty of the scrap you are carrying. It does not change what the scrap is worth.\nLevel 1: Carried weight counts for 20% less.\nLevel 2: Carried weight counts for 40% less.\nLevel 3: Carried weight counts for 60% less."), new Entry("protein_powder", "Pumping Iron", Y4NGZSkillTreeClass.Enforcer, 2, 1, 0, 2, "pumping_iron", "Description: Adds force to melee weapon hits. Fists are governed by Lethal Hands instead, and Better Armory weapons are excluded.\nLevel 1: Melee hits gain +1 force. A vanilla shovel hits for 1, so this doubles it.\nLevel 2: Melee hits also have a 25% chance to stun the struck enemy for 1 second.", null, new string[1] { "back_muscles" }), new Entry("thick_skin", "Resilience", Y4NGZSkillTreeClass.Enforcer, 2, 1, 1, 4, "resilience", "Description: Raises the health cap and regenerates 1 HP per second while injured, up to a cap. Rank 4 adds a countershock against enemy melee.\nLevel 1: Max health 120. Regenerates up to 20 HP.\nLevel 2: Max health 140. Regeneration cap rises to 30 HP.\nLevel 3: Max health 160. Regeneration cap stays 30 HP.\nLevel 4: Max health 180. Enemy melee hits have a 50% chance to reflect one shovel hit of damage and stun the attacker for 1 second.", null, new string[1] { "back_muscles" }), new Entry("lethal_hands_training", "Lethal Hands", Y4NGZSkillTreeClass.Enforcer, 3, 2, 0, 3, "lethal_hands", "Description: Unlocks empty-handed punching. One punch lands every 0.75 seconds; a vanilla shovel hit is 1 damage for scale.\nLevel 1: Punches deal 0.5 shovel hits of damage.\nLevel 2: Punches deal 1.0 shovel hit of damage.\nLevel 3: Punches deal 1.5 shovel hits of damage and stun the target for 1 second.", new string[1] { "protein_powder" }, new string[1] { "protein_powder" }), new Entry("extra_inventory_slot", "Deeper Pockets", Y4NGZSkillTreeClass.Enforcer, 3, 2, 1, 3, "deeper_pockets", "Description: Adds hotbar slots to the standard four.\nLevel 1: Five hotbar slots.\nLevel 2: Six hotbar slots.\nLevel 3: Seven hotbar slots, and you can carry two two-handed items at once.", null, new string[1] { "thick_skin" }, OptionalUpgradeProvider.NativeInventory), new Entry("adrenaline_rush", "Adrenaline Rush", Y4NGZSkillTreeClass.Enforcer, 4, 3, 0, 2, "adrenaline_rush", "Description: A speed surge at low health, and one death save per round at the second level.\nLevel 1: At 20 HP or lower, movement speed rises 30% until you heal back above 20.\nLevel 2: Once per round, a lethal hit leaves you at 1 HP, critically injured, with 2 seconds of invincibility. Falls, drowning and abandonment are not covered.", null, new string[2] { "lethal_hands_training", "extra_inventory_slot" }), new Entry("light_feet", "Light Feet", Y4NGZSkillTreeClass.Ghost, 1, 0, 0, 3, "light_feet", "Description: Automated hazards stop reacting to you.\nLevel 1: Footsteps no longer trigger landmines.\nLevel 2: Turrets hold fire for up to 2.5 extra seconds after spotting you.\nLevel 3: Lightning strikes no longer damage or kill you."), new Entry("sixth_sense", "Sixth Sense", Y4NGZSkillTreeClass.Ghost, 1, 0, 1, 3, "sixth_sense", "Description: Outlines what you cannot see. Anything in direct line of sight is skipped; only occluded targets are drawn.\nLevel 1: Main entrance, fire exits, mainframes, stashes and objectives outline within 15m. Turrets and landmines only within 5m.\nLevel 2: Also outlines grabbable scrap and items within 10m.\nLevel 3: Also outlines living enemies within 15m."), new Entry("chameleon", "Chameleon", Y4NGZSkillTreeClass.Ghost, 1, 0, 2, 3, "chameleon", "Description: Camouflage plating that only fools Company security cameras. It does nothing to enemies.\nLevel 1: Cameras take 15% longer to detect you.\nLevel 2: Cameras take 30% longer to detect you.\nLevel 3: Cameras take 50% longer to detect you.", null, new string[1] { "panic_slide" }, OptionalUpgradeProvider.LethalCctv), new Entry("physical_conditioning", "Sprinter", Y4NGZSkillTreeClass.Ghost, 2, 1, 0, 5, "sprinter", "Description: Athletics training: speed, stamina, climbing, terrain, quiet movement, and landings.\nLevel 1: Movement speed +1.4, sinking slowdown -20%, ladder speed +20%.\nLevel 2: Sprint time +6 seconds, stamina regen +5%, traction +25%, ladder speed +40%.\nLevel 3: Jump force +3, uphill slowdown -25%, ladder speed +60%.\nLevel 4: Jump force +0.75 more, footstep noise range -10m, crouch slowdown -10%.\nLevel 5: Fall damage -25%.", null, new string[1] { "light_feet" }), new Entry("panic_slide", "Escape Artist", Y4NGZSkillTreeClass.Ghost, 2, 1, 1, 3, "panic_slide", "Description: A chained movement kit. A heavy load weakens the slide.\nLevel 1: Sprint-crouch to power slide. Costs 14% stamina, 2.25 second cooldown.\nLevel 2: Mantle ledges from 0.95m to 3m high. Costs 8% stamina.\nLevel 3: One extra jump while airborne for 8% stamina, restored when you land.", null, new string[1] { "sixth_sense" }), new Entry("lone_wolf", "Lone Wolf", Y4NGZSkillTreeClass.Ghost, 3, 2, 0, 3, "lone_wolf", "Description: Active only while you are the sole living employee outside the ship room.\nLevel 1: Movement speed +30% while active.\nLevel 2: Stamina also refills 1.5% of the bar per second while active.\nLevel 3: Enemies within 30m glow red for 5 seconds, repeating every 20 seconds while active.", null, new string[2] { "physical_conditioning", "panic_slide" }), new Entry("shadow_step", "Shadow Step", Y4NGZSkillTreeClass.Ghost, 4, 3, 0, 3, "shadow_step", "Description: Shrinks the range at which enemies notice you, then unlocks a cloak.\nLevel 1: Enemy detection range -25% while crouching.\nLevel 2: Walking gets the same -25%; sprinting stays fully detectable.\nLevel 3: The Shadow Step key cloaks you for 6 seconds. The 120 second cooldown starts when the cloak ends, so 126 seconds between uses.", null, new string[1] { "lone_wolf" }), new Entry("better_scanner", "Field Optics", Y4NGZSkillTreeClass.Technician, 1, 0, 0, 3, "better_scanner", "Description: Upgrades issued optics - scanner glass and lamp alike - so you spot scrap sooner and light more of the room.\nLevel 1: Increases scanner node detection range by 15%, flashlight brightness by 10%, and flashlight cone width by 10%.\nLevel 2: Increases scanner node detection range by 30%, flashlight brightness by 15%, and flashlight cone width by 20%.\nLevel 3: Increases scanner node detection range by 45%, flashlight brightness by 40%, and flashlight cone width by 30%."), new Entry("quick_hands", "Quick Hands", Y4NGZSkillTreeClass.Technician, 1, 0, 1, 3, "quick_hands", "Description: Faster hold interactions and longer reach when grabbing.\nLevel 1: Hold interactions 10% faster, grab reach +1m.\nLevel 2: Hold interactions 20% faster, grab reach +2m.\nLevel 3: Hold interactions 30% faster, grab reach +3m."), new Entry("turret_hacker", "Field Mechanic", Y4NGZSkillTreeClass.Technician, 2, 1, 0, 3, "field_mechanic", "Description: On-site sabotage of facility hardware. Every hold interaction takes 1.2 seconds.\nLevel 1: Fuel pumps are half as likely to stall, and Company CCTV cameras can be disabled for the rest of the round.\nLevel 2: Standard locked doors can be hacked open, no key required.\nLevel 3: Turrets can be disabled for 90 seconds from the Field Operations tablet or a nearby hold, with a 20 second cooldown.", null, new string[1] { "better_scanner" }), new Entry("scavenger", "Scavenger", Y4NGZSkillTreeClass.Technician, 2, 1, 1, 3, "scavenger", "Description: Squeezes extra value out of everything scavenged in the field.\nLevel 1: Ammo pickups grant 10% more rounds and fuel chute deposits are worth 10% more.\nLevel 2: Ammo pickups grant 20% more rounds and fuel deposits are worth 20% more.\nLevel 3: Ammo pickups grant 30% more rounds and fuel deposits are worth 30% more.", null, new string[1] { "quick_hands" }, OptionalUpgradeProvider.None, OptionalUpgradeProvider.BetterArmory | OptionalUpgradeProvider.ShipSystems), new Entry("field_operations", "Field Operations", Y4NGZSkillTreeClass.Technician, 3, 2, 0, 1, "field_operations", "Description: Grants the Field Operations tablet.\nLevel 1: Unlocks the tablet: scan, interior map, drone link, and a mainframe uplink that takes 10 seconds to establish and then offers a scrap sweep and a trap shutdown. With LethalCCTV it also carries stash codes, camera view and disable, alarm control and lockdown.", new string[1] { "turret_hacker" }, new string[1] { "turret_hacker" }), new Entry("deathbound", "Deathbound", Y4NGZSkillTreeClass.Technician, 3, 2, 1, 1, "deathbound", "Description: Binds the far-left hotbar slot through death.\nLevel 1: The item in the far-left hotbar slot is not dropped on death and returns with you on respawn. The protected slot is tinted red.", null, new string[1] { "scavenger" }), new Entry("courier_drone", "Courier Drone", Y4NGZSkillTreeClass.Technician, 4, 3, 0, 3, "courier_drone", "Description: A steampunk courier drone commanded from the Field Operations tablet. The drone has 30 health.\nLevel 1: Hauls up to 150 lb of scrap and defends itself with a flamethrower out to 3.5m.\nLevel 2: Adds a grenade launcher that engages monsters between 8m and 18m on an 8 second cooldown. It checks for nearby crew before firing on its own, but the grenade still detonates if someone walks in, and pilot-fired grenades skip the check.\nLevel 3: Unlocks pilot mode to fly the drone yourself from the tablet.", null, new string[2] { "field_operations", "deathbound" }), new Entry("buddy_system", "Buddy System", Y4NGZSkillTreeClass.Foreman, 1, 0, 0, 2, "buddy_system", "Description: A support aura for the crew. The buffs go to other employees only, never to you.\nLevel 1: Teammates within 10m gain 3% movement speed and 3% damage reduction. You see teammates in that radius outlined when walls or fog hide them.\nLevel 2: Radius rises to 15m and both buffs rise to 6%."), new Entry("ping", "Ping", Y4NGZSkillTreeClass.Foreman, 2, 1, 0, 3, "ping", "Description: A team marking tool on its own key. Reaches 80m, marks last 5 seconds, 3 second cooldown.\nLevel 1: Mark a location, or outline an enemy, item, interactable or trap.\nLevel 2: Marked enemies deal 20% less contact damage.\nLevel 3: Marked teammates take 20% less damage for the mark duration.", null, new string[1] { "buddy_system" }), new Entry("worklight_beacon", "Worklight Beacon", Y4NGZSkillTreeClass.Foreman, 2, 1, 1, 3, "worklight_beacon", "Description: Throws sticky worklights. Each burns for 180 seconds, charges refill at the start of every round, and picking a beacon back up refunds its charge.\nLevel 1: Three charges, 10m lit radius.\nLevel 2: Five charges, 13m lit radius.\nLevel 3: Nine charges, 17m lit radius.", null, new string[1] { "buddy_system" }), new Entry("command_net", "Command Net", Y4NGZSkillTreeClass.Foreman, 2, 1, 2, 3, "command_net", "Description: Passive comms and a tactical display that cost no inventory slot.\nLevel 1: A built-in walkie channel. Hold the Command Net key to transmit with no walkie-talkie in hand.\nLevel 2: Teammates are outlined for 5 seconds whenever they take damage.\nLevel 3: A corner minimap once you step out of the ship room, tracking crew, entrances and enemies, plus security cameras and objectives.", null, new string[1] { "buddy_system" }), new Entry("veteran", "Overachiever", Y4NGZSkillTreeClass.Foreman, 3, 2, 0, 3, "veteran", "Description: Extra upgrade tokens on every promotion. Buying a level also pays the bonus retroactively for promotions you already earned.\nLevel 1: Each promotion grants 1 extra token.\nLevel 2: Each promotion grants 2 extra tokens.\nLevel 3: Each promotion grants 4 extra tokens.", null, new string[3] { "ping", "worklight_beacon", "command_net" }), new Entry("inspire", "Inspire", Y4NGZSkillTreeClass.Foreman, 4, 3, 0, 1, "inspire", "Description: Turns Ping into a revive attempt.\nLevel 1: Ping a dead body within 7m for a 50% chance to revive it. Once per round, consumed only on success, then a 75 second cooldown.", null, new string[1] { "veteran" }), new Entry("quota_guard", "Veteran", Y4NGZSkillTreeClass.Foreman, 4, 3, 1, 2, "quota_guard", "Description: The Company goes easy on a crew that keeps showing up. The whole crew uses the highest level anyone has bought.\nLevel 1: The end-of-round credit penalty for dead crew is halved.\nLevel 2: The next quota sets a 4 day deadline instead of 3.", null, new string[1] { "veteran" }) }; private static readonly Dictionary DerivedTierGates = BuildTierGates(); private static readonly Dictionary ById = BuildIndex(); internal static IReadOnlyList All => Ordered; internal static int[] GatesFor(Y4NGZSkillTreeClass treeClass) { if (DerivedTierGates.TryGetValue(treeClass, out var value)) { return value; } throw new InvalidOperationException($"No gate ladder for skill tree '{treeClass}'."); } internal static int GateForTier(Y4NGZSkillTreeClass treeClass, int tier) { if (tier <= 1) { return 0; } int[] array = GatesFor(treeClass); int num = tier - 1; if (num >= array.Length) { throw new ArgumentOutOfRangeException("tier", $"Skill tree '{treeClass}' has no gate authored for tier {tier}."); } return array[num]; } private static Dictionary BuildTierGates() { Dictionary dictionary = new Dictionary(); Y4NGZSkillTreeClass[] array = (Y4NGZSkillTreeClass[])Enum.GetValues(typeof(Y4NGZSkillTreeClass)); foreach (Y4NGZSkillTreeClass y4NGZSkillTreeClass in array) { int[] array2 = new int[DefaultTierGates.Length]; int num = 0; for (int j = 1; j <= array2.Length; j++) { array2[j - 1] = Math.Min(DefaultTierGates[j - 1], num); for (int k = 0; k < Ordered.Length; k++) { Entry entry = Ordered[k]; if (entry.TreeClass == y4NGZSkillTreeClass && entry.Tier == j && !entry.HasOptionalProviderRequirement) { num += entry.SubTierCount; } } } dictionary[y4NGZSkillTreeClass] = array2; } return dictionary; } internal static Entry Get(string id) { if (TryGet(id, out var entry)) { return entry; } throw new InvalidOperationException("No catalog row for upgrade '" + id + "'."); } internal static bool TryGet(string id, out Entry entry) { entry = null; if (!string.IsNullOrWhiteSpace(id)) { return ById.TryGetValue(id.Trim(), out entry); } return false; } private static Dictionary BuildIndex() { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < Ordered.Length; i++) { dictionary[Ordered[i].Id] = Ordered[i]; } return dictionary; } } internal static class UpgradePriceMath { internal static int GetPriceForLevel(int level, int maxTier, int unlockPrice, int[] tierPrices) { if (level >= maxTier) { return int.MaxValue; } int num; if (level <= 0) { num = unlockPrice; } else { int num2 = level - 1; num = ((tierPrices != null && num2 < tierPrices.Length) ? tierPrices[num2] : int.MaxValue); } if (num != int.MaxValue) { return Math.Max(0, num); } return num; } internal static int GetMaxTier(int[] tierPrices) { return Math.Max(1, ((tierPrices != null) ? tierPrices.Length : 0) + 1); } } internal static class UpgradePriceMigration { internal sealed class LegacyPrices { internal string Id { get; } internal bool OptionalGated { get; } internal int[] UnlockPrices { get; } internal string[] TierLists { get; } internal LegacyPrices(string id, int[] unlockPrices, string[] tierLists, bool optionalGated = false) { Id = id; UnlockPrices = unlockPrices ?? Array.Empty(); TierLists = tierLists ?? Array.Empty(); OptionalGated = optionalGated; } } internal const int CurrentSchemaVersion = 3; internal const int LegacySchemaVersion = 1; private static readonly LegacyPrices[] Legacy = new LegacyPrices[27] { Entry("physical_conditioning", 1, "2,3,5,7"), Entry("thick_skin", 2, "3,5,7"), Entry("lethal_hands_training", 3, "5,7"), Entry("deathbound", 5, ""), Entry("adrenaline_rush", 3, "7"), Entry("lone_wolf", 3, "5,7"), Entry("light_feet", 3, "5,7"), Entry("shadow_step", 3, "5,7"), Entry("sixth_sense", 1, "2,3"), new LegacyPrices("extra_inventory_slot", new int[1] { 3 }, new string[1] { "5,7" }, optionalGated: true), new LegacyPrices("protein_powder", new int[1] { 3 }, new string[2] { "5,7", "3,4" }), Entry("back_muscles", 3, "5,7"), Entry("better_scanner", 3, "5,7"), Entry("quick_hands", 1, "2,3"), Entry("panic_slide", 2, "4,6"), Entry("field_operations", 3, ""), Entry("turret_hacker", 4, "8,12"), Entry("courier_drone", 7, "10,14"), Entry("buddy_system", 2, "4"), Entry("ping", 3, "5,7"), Entry("command_net", 4, "6,8"), Entry("worklight_beacon", 3, "5,7"), Entry("veteran", 4, "6,8"), new LegacyPrices("quota_guard", new int[1] { 7 }, new string[2] { "10", "10,14" }), new LegacyPrices("scavenger", new int[1] { 2 }, new string[1] { "4,6" }, optionalGated: true), new LegacyPrices("chameleon", new int[1] { 2 }, new string[1] { "3,5" }, optionalGated: true), Entry("inspire", 7, "") }; private static readonly Dictionary ById = BuildIndex(); internal static IReadOnlyList All => Legacy; internal static LegacyPrices Find(string id) { if (!string.IsNullOrWhiteSpace(id) && ById.TryGetValue(id.Trim(), out var value)) { return value; } return null; } internal static int NextStamp(int storedStamp, bool rowSetResolved) { if (!rowSetResolved || storedStamp >= 3) { return storedStamp; } return 3; } internal static string ResolveValue(bool stampBelowCurrent, string storedValue, IReadOnlyList oldDefaults, string newDefault, out bool rewrite) { rewrite = false; if (!stampBelowCurrent) { return storedValue; } if (Matches(storedValue, newDefault)) { return storedValue; } if (!MatchesAny(storedValue, oldDefaults)) { return storedValue; } rewrite = true; return newDefault; } internal static int ResolveValue(bool stampBelowCurrent, int storedValue, IReadOnlyList oldDefaults, int newDefault, out bool rewrite) { rewrite = false; if (!stampBelowCurrent || storedValue == newDefault) { return storedValue; } if (oldDefaults != null) { for (int i = 0; i < oldDefaults.Count; i++) { if (oldDefaults[i] == storedValue) { rewrite = true; return newDefault; } } } return storedValue; } private static bool MatchesAny(string storedValue, IReadOnlyList candidates) { if (candidates == null) { return false; } for (int i = 0; i < candidates.Count; i++) { if (Matches(storedValue, candidates[i])) { return true; } } return false; } private static bool Matches(string left, string right) { return string.Equals(Strip(left), Strip(right), StringComparison.Ordinal); } private static string Strip(string value) { if (string.IsNullOrEmpty(value)) { return string.Empty; } char[] array = new char[value.Length]; int length = 0; for (int i = 0; i < value.Length; i++) { if (!char.IsWhiteSpace(value[i])) { array[length++] = value[i]; } } return new string(array, 0, length); } internal static string Format(IReadOnlyList values) { if (values == null || values.Count == 0) { return string.Empty; } string[] array = new string[values.Count]; for (int i = 0; i < values.Count; i++) { array[i] = values[i].ToString(CultureInfo.InvariantCulture); } return string.Join(",", array); } private static LegacyPrices Entry(string id, int unlockPrice, string tierList) { return new LegacyPrices(id, new int[1] { unlockPrice }, new string[1] { tierList }); } private static Dictionary BuildIndex() { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); for (int i = 0; i < Legacy.Length; i++) { dictionary[Legacy[i].Id] = Legacy[i]; } return dictionary; } } internal enum UpgradePurchaseOutcome { Success, Maxed, SaveUnavailable, PriceChanged, NotEnoughCurrency } internal interface IUpgradeWallet { bool TryReserve(string transactionId, int amount); bool Commit(string transactionId); void Cancel(string transactionId); } internal static class UpgradePurchaseFlow { internal const int NoQuotedPrice = -1; internal static UpgradePurchaseOutcome TryPurchase(UpgradeSaveStateStore store, string upgradeId, int maxTier, Func priceForLevel, int quotedPrice, IUpgradeWallet wallet, string transactionId, out int chargedPrice, out int newLevel) { chargedPrice = 0; newLevel = 0; if (store == null || priceForLevel == null || wallet == null || string.IsNullOrWhiteSpace(upgradeId) || string.IsNullOrWhiteSpace(transactionId)) { return UpgradePurchaseOutcome.SaveUnavailable; } if (!store.SwitchToCurrentSave()) { return UpgradePurchaseOutcome.SaveUnavailable; } UpgradeSaveState current = store.Current; if (current == null) { return UpgradePurchaseOutcome.SaveUnavailable; } int level = store.GetLevel(upgradeId, maxTier); if (level >= maxTier) { return UpgradePurchaseOutcome.Maxed; } int num = priceForLevel(level); if (num == int.MaxValue) { return UpgradePurchaseOutcome.Maxed; } if (quotedPrice != -1 && quotedPrice != num) { return UpgradePurchaseOutcome.PriceChanged; } if (num > 0 && !wallet.TryReserve(transactionId, num)) { return UpgradePurchaseOutcome.NotEnoughCurrency; } if (!store.SwitchToCurrentSave() || store.Current != current) { wallet.Cancel(transactionId); return UpgradePurchaseOutcome.SaveUnavailable; } current.Levels[upgradeId] = level + 1; if (num > 0 && !wallet.Commit(transactionId)) { if (level <= 0) { current.Levels.Remove(upgradeId); } else { current.Levels[upgradeId] = level; } wallet.Cancel(transactionId); return UpgradePurchaseOutcome.NotEnoughCurrency; } chargedPrice = num; newLevel = level + 1; return UpgradePurchaseOutcome.Success; } } internal delegate bool TryResolveSaveKeyDelegate(out string key); internal sealed class UpgradeSaveState { internal readonly Dictionary Levels = new Dictionary(StringComparer.OrdinalIgnoreCase); internal bool ImportedLegacyLevels; } internal sealed class UpgradeSaveStateStore { private readonly Dictionary _states = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly TryResolveSaveKeyDelegate _tryResolveKey; private UpgradeSaveState _state; private string _currentKey; internal string CurrentKey => _currentKey; internal UpgradeSaveState Current { get { if (_currentKey != null) { return _state; } return null; } } internal bool HasCurrent { get { if (_currentKey != null) { return _state != null; } return false; } } internal IReadOnlyCollection Keys { get { string[] array = new string[_states.Count]; _states.Keys.CopyTo(array, 0); return (IReadOnlyCollection)(object)array; } } internal IEnumerable> Entries => _states; internal UpgradeSaveStateStore(TryResolveSaveKeyDelegate tryResolveKey) { _tryResolveKey = tryResolveKey ?? throw new ArgumentNullException("tryResolveKey"); } internal bool TryGetState(string key, out UpgradeSaveState state) { state = null; if (!string.IsNullOrWhiteSpace(key)) { return _states.TryGetValue(key, out state); } return false; } internal void SetState(string key, UpgradeSaveState state) { if (!string.IsNullOrWhiteSpace(key)) { _states[key] = state ?? new UpgradeSaveState(); if (string.Equals(key, _currentKey, StringComparison.OrdinalIgnoreCase)) { _state = _states[key]; } } } internal void Clear() { _states.Clear(); _currentKey = null; _state = null; } internal bool SwitchToCurrentSave() { if (_currentKey != null && _state != null) { _states[_currentKey] = _state; } if (!_tryResolveKey(out var key) || string.IsNullOrWhiteSpace(key)) { _currentKey = null; _state = null; return false; } _currentKey = key; if (!_states.TryGetValue(key, out _state) || _state == null) { _state = new UpgradeSaveState(); _states[key] = _state; } return true; } internal int RemoveKeys(IEnumerable keys) { if (keys == null) { return 0; } HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string key in keys) { if (!string.IsNullOrWhiteSpace(key)) { hashSet.Add(key); } } int num = 0; foreach (string item in hashSet) { if (_states.Remove(item)) { num++; } } if (_currentKey != null && hashSet.Contains(_currentKey)) { _currentKey = null; _state = null; } return num; } internal int GetLevel(string upgradeId, int maxTier) { UpgradeSaveState current = Current; if (current == null || string.IsNullOrWhiteSpace(upgradeId)) { return 0; } int value; int num = (current.Levels.TryGetValue(upgradeId, out value) ? value : 0); if (num >= 0) { if (num <= maxTier) { return num; } return maxTier; } return 0; } } internal sealed class WorklightBeaconProjectile : MonoBehaviour { internal static readonly List ActiveBeacons = new List(); private static readonly Dictionary ActiveBeaconsByKey = new Dictionary(); private const float MAX_AIRBORNE_TIME = 6f; private const float VISUAL_SIZE = 0.24f; private const float PICKUP_RADIUS = 0.45f; private const string LAND_SOUND_FILE = "soundreality-switch-150130.mp3"; private static AudioClip _landClip; private static bool _landClipLoadStarted; private Rigidbody _body; private SphereCollider _collider; private Light _light; private InteractTrigger _pickupTrigger; private float _spawnTime; private float _destroyAt; private int _tier; private bool _stuck; private string _key; private ulong _throwerNetObjId; private uint _beaconId; internal ulong ThrowerNetObjId => _throwerNetObjId; internal uint BeaconId => _beaconId; internal static bool TryGetAimedBeacon(PlayerControllerB player, out WorklightBeaconProjectile beacon) { //IL_0039: 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) beacon = null; if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return false; } int num = LayerMask.NameToLayer("InteractableObject"); if (num < 0) { num = 9; } RaycastHit val = default(RaycastHit); if (!Physics.Raycast(new Ray(((Component)player.gameplayCamera).transform.position, ((Component)player.gameplayCamera).transform.forward), ref val, 4f, 1 << num, (QueryTriggerInteraction)2)) { return false; } beacon = (((Object)(object)((RaycastHit)(ref val)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val)).collider).GetComponentInParent() : null); if ((Object)(object)beacon != (Object)null) { return beacon._stuck; } return false; } public static GameObject Spawn(Vector3 position, Vector3 direction, float throwForce, ulong throwerNetObjId, uint beaconId, int tier) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown string key = MakeKey(throwerNetObjId, beaconId); if (ActiveBeaconsByKey.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { return ((Component)value).gameObject; } GameObject val = new GameObject("Y4NGZ_WorklightBeacon"); val.transform.position = position; SphereCollider val2 = val.AddComponent(); val2.radius = 0.12f; ((Collider)val2).isTrigger = false; Rigidbody val3 = val.AddComponent(); val3.useGravity = true; val3.mass = 0.18f; val3.drag = 0.05f; val3.collisionDetectionMode = (CollisionDetectionMode)2; AttachVisual(val.transform); WorklightBeaconProjectile worklightBeaconProjectile = val.AddComponent(); worklightBeaconProjectile._body = val3; worklightBeaconProjectile._tier = Mathf.Clamp(tier, 1, 3); worklightBeaconProjectile._spawnTime = Time.time; worklightBeaconProjectile._destroyAt = Time.time + 180f; worklightBeaconProjectile._key = key; worklightBeaconProjectile._throwerNetObjId = throwerNetObjId; worklightBeaconProjectile._beaconId = beaconId; worklightBeaconProjectile._collider = val2; worklightBeaconProjectile.CreateLight(active: false); EnsureLandSoundLoading(); val3.AddForce(((Vector3)(ref direction)).normalized * throwForce, (ForceMode)2); ActiveBeacons.Add(worklightBeaconProjectile); ActiveBeaconsByKey[key] = worklightBeaconProjectile; return val; } public static void DestroyAllActive() { for (int num = ActiveBeacons.Count - 1; num >= 0; num--) { WorklightBeaconProjectile worklightBeaconProjectile = ActiveBeacons[num]; if ((Object)(object)worklightBeaconProjectile != (Object)null) { Object.Destroy((Object)(object)((Component)worklightBeaconProjectile).gameObject); } } ActiveBeacons.Clear(); ActiveBeaconsByKey.Clear(); } public static void DestroySynced(ulong throwerNetObjId, uint beaconId) { string key = MakeKey(throwerNetObjId, beaconId); if (ActiveBeaconsByKey.TryGetValue(key, out var value) && !((Object)(object)value == (Object)null)) { Object.Destroy((Object)(object)((Component)value).gameObject); } } private static string MakeKey(ulong throwerNetObjId, uint beaconId) { return throwerNetObjId + ":" + beaconId; } private void Update() { //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) if (!_stuck && Time.time - _spawnTime >= 6f) { Stick(((Component)this).transform.position, Vector3.up, null); } if (Time.time >= _destroyAt) { Object.Destroy((Object)(object)((Component)this).gameObject); } } private void OnCollisionEnter(Collision collision) { //IL_0017: 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_0028: 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_003b: 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_0044: 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_0064: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!_stuck) { ContactPoint val = (ContactPoint)((collision != null && collision.contactCount > 0) ? collision.GetContact(0) : default(ContactPoint)); Vector3 point = ((collision != null && collision.contactCount > 0) ? ((ContactPoint)(ref val)).point : ((Component)this).transform.position); Vector3 normal = ((collision != null && collision.contactCount > 0) ? ((ContactPoint)(ref val)).normal : Vector3.up); Transform parent = ((collision != null && (Object)(object)collision.transform != (Object)null) ? collision.transform : null); Stick(point, normal, parent); } } private void Stick(Vector3 point, Vector3 normal, Transform parent) { //IL_001e: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_00cc: Unknown result type (might be due to invalid IL or missing references) _stuck = true; Vector3 val = ((((Vector3)(ref normal)).sqrMagnitude > 0.001f) ? ((Vector3)(ref normal)).normalized : Vector3.up); Vector3 val2 = ((Mathf.Abs(Vector3.Dot(val, Vector3.up)) > 0.95f) ? Vector3.forward : Vector3.up); ((Component)this).transform.position = point + val * 0.025f; ((Component)this).transform.rotation = Quaternion.LookRotation(val, val2); if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponentInParent() == (Object)null && (Object)(object)((Component)parent).GetComponentInParent() == (Object)null) { ((Component)this).transform.SetParent(parent, true); } if ((Object)(object)_body != (Object)null) { _body.velocity = Vector3.zero; _body.angularVelocity = Vector3.zero; _body.isKinematic = true; _body.useGravity = false; } if ((Object)(object)_collider != (Object)null) { ((Collider)_collider).enabled = true; ((Collider)_collider).isTrigger = true; _collider.radius = 0.45f; } if ((Object)(object)_light == (Object)null) { CreateLight(active: true); } else { ((Behaviour)_light).enabled = true; } PlayLandSound(); ConfigurePickupTrigger(); } private void PlayLandSound() { if (!((Object)(object)_landClip == (Object)null)) { AudioSource obj = ((Component)this).gameObject.AddComponent(); obj.playOnAwake = false; obj.loop = false; obj.spatialBlend = 1f; obj.rolloffMode = (AudioRolloffMode)0; obj.minDistance = 1f; obj.maxDistance = 18f; obj.volume = 0.8f; obj.PlayOneShot(_landClip); } } private static void EnsureLandSoundLoading() { if (!((Object)(object)_landClip != (Object)null) && !_landClipLoadStarted && Y4NGZPersistentRunner.Run(LoadLandSoundClip()) != null) { _landClipLoadStarted = true; } } private static IEnumerator LoadLandSoundClip() { string path = FindLandSoundPath(); if (string.IsNullOrWhiteSpace(path)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[WorklightBeacon] Landing sound not found under Assets/Worklight."); } yield break; } UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)13); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[WorklightBeacon] Failed to load landing sound '" + path + "': " + request.error)); } yield break; } _landClip = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)_landClip != (Object)null) { ((Object)_landClip).name = "Y4NGZ_WorklightLand"; } } finally { ((IDisposable)request)?.Dispose(); } } private static string FindLandSoundPath() { string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, "Assets", "Worklight", "soundreality-switch-150130.mp3"); if (File.Exists(text)) { return text; } } string text2 = Path.Combine(Paths.PluginPath, "Y4NGZUpgrades", "Assets", "Worklight", "soundreality-switch-150130.mp3"); if (File.Exists(text2)) { return text2; } string text3 = Path.Combine(Paths.PluginPath, "y4ngz-Y4NGZUpgrades", "Assets", "Worklight", "soundreality-switch-150130.mp3"); if (!File.Exists(text3)) { return null; } return text3; } private void ConfigurePickupTrigger() { //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Expected O, but got Unknown int num = LayerMask.NameToLayer("InteractableObject"); ((Component)this).gameObject.layer = ((num >= 0) ? num : 9); if ((Object)(object)_pickupTrigger == (Object)null) { _pickupTrigger = ((Component)this).gameObject.AddComponent(); } if (!((Object)(object)_pickupTrigger == (Object)null)) { TrySetTag(((Component)this).gameObject, "InteractTrigger"); _pickupTrigger.interactable = true; _pickupTrigger.oneHandedItemAllowed = true; _pickupTrigger.twoHandedItemAllowed = true; _pickupTrigger.holdInteraction = false; _pickupTrigger.interactCooldown = true; _pickupTrigger.cooldownTime = 0.2f; _pickupTrigger.currentCooldownValue = -0.05f; _pickupTrigger.hoverTip = "Pick up worklight : [" + UpgradeInteractInput.DisplayLabel() + "]"; _pickupTrigger.disabledHoverTip = "[ Worklight recovered ]"; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)val.grabItemIcon != (Object)null) { _pickupTrigger.hoverIcon = val.grabItemIcon; } _pickupTrigger.disableTriggerMesh = true; if (_pickupTrigger.onInteract == null) { _pickupTrigger.onInteract = new InteractEvent(); } ((UnityEvent)(object)_pickupTrigger.onInteract).RemoveListener((UnityAction)OnPickupInteract); ((UnityEvent)(object)_pickupTrigger.onInteract).AddListener((UnityAction)OnPickupInteract); } } private static void TrySetTag(GameObject go, string tag) { if ((Object)(object)go == (Object)null || string.IsNullOrWhiteSpace(tag)) { return; } try { go.tag = tag; } catch { } } private void OnPickupInteract(PlayerControllerB player) { WorklightBeaconPatch.TryPickupBeacon(this, player); } private void CreateLight(bool active) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("WorklightBeaconLight"); val.transform.SetParent(((Component)this).transform, false); val.transform.localPosition = new Vector3(0f, 0f, 0.045f); _light = val.AddComponent(); _light.type = (LightType)2; _light.color = new Color(1f, 0.93f, 0.82f, 1f); _light.intensity = WorklightBeaconUpgrade.GetIntensity(_tier); _light.range = WorklightBeaconUpgrade.GetRange(_tier); _light.shadows = (LightShadows)2; ((Behaviour)_light).enabled = active; } private static void AttachVisual(Transform parent) { //IL_0024: 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_0062: 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_00cd: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)2); ((Object)obj).name = "WorklightBeaconBase"; obj.transform.SetParent(parent, false); obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.Euler(90f, 0f, 0f); obj.transform.localScale = new Vector3(0.24f, 0.035f, 0.24f); RemoveCollider(obj); ApplyMaterial(obj, new Color(0.08f, 0.075f, 0.065f, 1f), 0.15f, 0.45f); GameObject obj2 = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj2).name = "WorklightBeaconLens"; obj2.transform.SetParent(parent, false); obj2.transform.localPosition = new Vector3(0f, 0f, 0.055f); obj2.transform.localScale = new Vector3(0.13f, 0.13f, 0.045f); RemoveCollider(obj2); ApplyMaterial(obj2, new Color(1f, 0.9f, 0.72f, 1f), 0f, 0.95f); GameObject obj3 = GameObject.CreatePrimitive((PrimitiveType)3); ((Object)obj3).name = "WorklightBeaconMagnet"; obj3.transform.SetParent(parent, false); obj3.transform.localPosition = new Vector3(0f, -0.015f, -0.045f); obj3.transform.localScale = new Vector3(0.16f, 0.03f, 0.025f); RemoveCollider(obj3); ApplyMaterial(obj3, new Color(0.55f, 0.04f, 0.025f, 1f), 0.3f, 0.55f); } private static void RemoveCollider(GameObject go) { Collider component = go.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } } private static void ApplyMaterial(GameObject go, Color color, float metallic, float smoothness) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Expected O, but got Unknown //IL_0068: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) MeshRenderer component = go.GetComponent(); if ((Object)(object)component == (Object)null) { return; } Shader val = Shader.Find("HDRP/Lit"); if ((Object)(object)val == (Object)null) { val = Shader.Find("Universal Render Pipeline/Lit"); } if ((Object)(object)val == (Object)null) { val = Shader.Find("Standard"); } if (!((Object)(object)val == (Object)null)) { Material val2 = new Material(val); if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", color); } if (val2.HasProperty("_Color")) { val2.SetColor("_Color", color); } if (val2.HasProperty("_Metallic")) { val2.SetFloat("_Metallic", metallic); } if (val2.HasProperty("_Smoothness")) { val2.SetFloat("_Smoothness", smoothness); } if (val2.HasProperty("_EmissionColor")) { val2.SetColor("_EmissionColor", color * 1.4f); } ((Renderer)component).sharedMaterial = val2; } } private void OnDestroy() { if ((Object)(object)_pickupTrigger != (Object)null && _pickupTrigger.onInteract != null) { ((UnityEvent)(object)_pickupTrigger.onInteract).RemoveListener((UnityAction)OnPickupInteract); } ActiveBeacons.Remove(this); if (!string.IsNullOrWhiteSpace(_key)) { ActiveBeaconsByKey.Remove(_key); } } } internal static class Y4NGZPersistentRunner { private sealed class Y4NGZPersistentRunnerBehaviour : MonoBehaviour { private void Update() { HeldItemStowService.Tick(); GameplayUiVisibility.PublishCurrentState(); } } private static Y4NGZPersistentRunnerBehaviour _runner; internal static MonoBehaviour Host { get { Ensure(); return (MonoBehaviour)(object)_runner; } } internal static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown //IL_001e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_runner != (Object)null)) { GameObject val = new GameObject("Y4NGZUpgradesPersistentRunner"); Object.DontDestroyOnLoad((Object)val); ((Object)val).hideFlags = (HideFlags)61; _runner = val.AddComponent(); } } internal static Coroutine Run(IEnumerator routine) { if (routine == null) { return null; } Ensure(); if (!((Object)(object)_runner != (Object)null)) { return null; } return ((MonoBehaviour)_runner).StartCoroutine(routine); } internal static void Stop(Coroutine routine) { if (routine != null && !((Object)(object)_runner == (Object)null)) { ((MonoBehaviour)_runner).StopCoroutine(routine); } } } public static class MyPluginInfo { public const string PLUGIN_GUID = "Y4NGZUpgrades"; public const string PLUGIN_NAME = "Y4NGZUpgrades"; public const string PLUGIN_VERSION = "1.0.0"; } } namespace Y4NGZUpgrades.Upgrades { internal readonly struct EffectiveUpgradePrices { internal int UnlockPrice { get; } internal int[] TierPrices { get; } internal EffectiveUpgradePrices(int unlockPrice, int[] tierPrices) { UnlockPrice = Math.Max(0, unlockPrice); TierPrices = tierPrices ?? Array.Empty(); } } internal sealed class PerUpgradeConfig { private readonly struct AuditRow { internal string Id { get; } internal string DisplayName { get; } internal EffectiveUpgradePrices Prices { get; } internal AuditRow(string id, string displayName, EffectiveUpgradePrices prices) { Id = id; DisplayName = displayName; Prices = prices; } } private readonly List _audit = new List(); internal EffectiveUpgradePrices Resolve(UpgradeCatalogTable.Entry catalogEntry, bool active) { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Expected O, but got Unknown if (catalogEntry == null) { throw new ArgumentNullException("catalogEntry"); } Y4NGZConfigScope target = Y4NGZConfigFiles.Upgrade(catalogEntry); bool flag = Y4NGZConfigFiles.TargetAlreadyDefines(target, "Prices", "Unlock Cost"); ConfigEntry val = Y4NGZConfigFiles.BindMigrated(target, "Prices", "Unlock Cost", Math.Max(0, catalogEntry.UnlockPrice), new ConfigDescription("Tokens required to unlock " + catalogEntry.DisplayName + " at level 1.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty()), new LegacyConfigKey("30 - Upgrade Prices", catalogEntry.Id + ".Unlock")); if (!flag) { val.Value = ResolveLegacyUnlock(catalogEntry, val.Value); } int[] array = catalogEntry.TierPrices ?? Array.Empty(); int[] array2 = ReadLegacyTiers(catalogEntry, array); int[] array3 = new int[array.Length]; for (int i = 0; i < array.Length; i++) { string key = $"Level {i + 2} Cost"; bool flag2 = Y4NGZConfigFiles.TargetAlreadyDefines(target, "Prices", key); ConfigEntry val2 = Y4NGZConfigFiles.BindMigrated(target, "Prices", key, Math.Max(0, array[i]), new ConfigDescription($"Tokens required to purchase {catalogEntry.DisplayName} level {i + 2}.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty())); if (!flag2 && array2 != null) { val2.Value = array2[i]; } array3[i] = Math.Max(0, val2.Value); } EffectiveUpgradePrices effectiveUpgradePrices = new EffectiveUpgradePrices(Math.Max(0, val.Value), array3); if (active) { _audit.Add(new AuditRow(catalogEntry.Id, catalogEntry.DisplayName, effectiveUpgradePrices)); } return effectiveUpgradePrices; } internal string BuildAuditReport() { StringBuilder stringBuilder = new StringBuilder(); int num = 0; foreach (AuditRow item in _audit.OrderBy((AuditRow value) => value.Id, StringComparer.Ordinal)) { int num2 = item.Prices.UnlockPrice + item.Prices.TierPrices.Sum(); num += num2; stringBuilder.Append(item.Id).Append(" | ").Append(item.DisplayName) .Append(" | unlock=") .Append(item.Prices.UnlockPrice) .Append(" | tiers=") .Append(UpgradePriceMigration.Format(item.Prices.TierPrices)) .Append(" | total=") .Append(num2) .AppendLine(); } stringBuilder.Append("CATALOG TOTAL = ").Append(num).AppendLine(); int earnableRankCount = RankCatalog.EarnableRankCount; int tokenGrantForRankRange = RankCatalog.GetTokenGrantForRankRange(1, earnableRankCount); int num3 = earnableRankCount * OverachieverUpgrade.MaxBonusTokensPerRank; int num4 = tokenGrantForRankRange + num3; int num5 = num4 - num; stringBuilder.Append("LIFETIME TOKEN INCOME = ").Append(num4).Append(" (ranks 1-") .Append(earnableRankCount) .Append(" = ") .Append(tokenGrantForRankRange) .Append(" + Overachiever max ") .Append(num3) .Append(")") .AppendLine(); stringBuilder.Append("MARGIN = ").Append(num5); if (num5 < 0) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)($"[UpgradePrices] Lifetime token income ({num4}) no longer covers " + $"the active catalog cost ({num}); shortfall {-num5} token(s).")); } } return stringBuilder.ToString(); } private static int ResolveLegacyUnlock(UpgradeCatalogTable.Entry entry, int storedValue) { UpgradePriceMigration.LegacyPrices legacyPrices = UpgradePriceMigration.Find(entry.Id); if (legacyPrices == null) { return storedValue; } bool rewrite; return UpgradePriceMigration.ResolveValue(IsLegacySchemaBelowCurrent(entry.HasOptionalProviderRequirement), storedValue, legacyPrices.UnlockPrices, entry.UnlockPrice, out rewrite); } private static int[] ReadLegacyTiers(UpgradeCatalogTable.Entry entry, int[] authoredTiers) { int num = ((authoredTiers != null) ? authoredTiers.Length : 0); if (!Y4NGZConfigFiles.TryGetLegacy("30 - Upgrade Prices", entry.Id + ".Tiers", out var value)) { return null; } UpgradePriceMigration.LegacyPrices legacyPrices = UpgradePriceMigration.Find(entry.Id); if (legacyPrices != null) { value = UpgradePriceMigration.ResolveValue(IsLegacySchemaBelowCurrent(entry.HasOptionalProviderRequirement), value, legacyPrices.TierLists, UpgradePriceMigration.Format(authoredTiers), out var _); } if (num == 0) { if (!string.IsNullOrWhiteSpace(value)) { return null; } return Array.Empty(); } string[] array = value.Split(','); if (array.Length != num) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[Config] Ignored invalid legacy price list for {entry.Id}; expected {num} value(s)."); } return null; } int[] array2 = new int[num]; for (int i = 0; i < array.Length; i++) { if (!int.TryParse(array[i].Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out array2[i]) || array2[i] < 0) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Config] Ignored invalid legacy price list for " + entry.Id + ".")); } return null; } } return array2; } private static bool IsLegacySchemaBelowCurrent(bool optionalProviderPrice) { string key = (optionalProviderPrice ? "SchemaVersion.Company" : "SchemaVersion"); int value = 1; Y4NGZConfigFiles.TryGetLegacy("30 - Upgrade Prices", key, out value); return value < 3; } } internal static class Y4NGZUpgradeState { internal static bool GetActiveUpgrade(string name) { return Y4NGZUpgradeManager.IsExactUnlocked(name); } internal static int GetUpgradeLevel(string name) { return Mathf.Max(0, Y4NGZUpgradeManager.GetExactLevel(name) - 1); } internal static int GetTier(string name) { return Y4NGZUpgradeManager.GetExactLevel(name); } } internal static class NativeFistsUpgrade { public const string UPGRADE_NAME = "Lethal Hands"; public const string UPGRADE_ID = "lethal_hands_training"; private const float TIER_1_DAMAGE = 0.5f; private const float TIER_2_DAMAGE = 1f; private const float TIER_3_DAMAGE = 1.5f; public const float TIER_3_STUN_SECONDS = 1f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Lethal Hands"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Lethal Hands"); } public static float GetCurrentDamageMultiplier() { return GetDamageForTier(GetTier()); } public static float GetDamageForTier(int tier) { return tier switch { 1 => 0.5f, 2 => 1f, 3 => 1.5f, _ => 0f, }; } public static bool ShouldStun() { if (IsUnlocked()) { return Y4NGZUpgradeState.GetUpgradeLevel("Lethal Hands") >= 2; } return false; } } internal static class AdrenalineRushUpgrade { public const string UPGRADE_NAME = "Adrenaline Rush"; public const int LOW_HP_THRESHOLD = 20; public const float SPEED_MULTIPLIER = 1.3f; public const float INVINCIBILITY_SECONDS = 2f; public const string SPEED_SOURCE_ID = "AdrenalineRush"; public static bool IsAdrenalineActive; public static bool InsuranceUsedThisRound; public static bool IsInvincible; public static float InvincibilityEndTime; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Adrenaline Rush"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Adrenaline Rush"); } public static bool HasInsurance() { return GetTier() >= 2; } } internal static class ShoulderCheckUpgrade { public const string UPGRADE_NAME = "Shoulder Check"; public const float BASE_ARM_SECONDS = 2f; public const float TIER3_ARM_SECONDS = 1.65f; public const float READY_MIN_SPRINT_METER = 0.12f; public const float IMPACT_STUN_SECONDS = 0.65f; public const float DOOR_CHECK_RANGE = 1.35f; public const float DOOR_CHECK_RADIUS = 0.45f; private static readonly int[] DamageByTier = new int[3] { 1, 2, 2 }; private static readonly float[] KnockbackByTier = new float[3] { 3.4f, 5.1f, 5.7f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Shoulder Check"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Shoulder Check"); } public static float GetArmSeconds() { if (GetTier() < 3) { return 2f; } return 1.65f; } public static int GetDamage() { int tier = GetTier(); if (tier > 0) { return DamageByTier[Mathf.Clamp(tier - 1, 0, DamageByTier.Length - 1)]; } return 0; } public static float GetKnockbackMeters() { int tier = GetTier(); if (tier > 0) { return KnockbackByTier[Mathf.Clamp(tier - 1, 0, KnockbackByTier.Length - 1)]; } return 0f; } } internal static class EscapeReflexUpgrade { public const string UPGRADE_NAME = "Escape Reflex"; public const int HEALTH_THRESHOLD = 35; public const float INVISIBILITY_SECONDS = 2f; public const float SPEED_BOOST_SECONDS = 5f; public const float SPEED_BOOST_MULTIPLIER = 0.15f; public const float VISUAL_SECONDS = 1.15f; public static bool UsedThisRound; public static float SpeedBoostEndTime; public static float AppliedSpeedBonus; public static float VisualEndTime; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Escape Reflex"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Escape Reflex"); } public static bool HasCloak() { return GetTier() >= 2; } public static bool HasSpeedBoost() { return GetTier() >= 3; } } internal static class LoneWolfUpgrade { private struct RevealLight { internal EnemyAI Enemy; internal Light Light; } public const string UPGRADE_NAME = "Lone Wolf"; public const string SPEED_SOURCE_ID = "lone_wolf"; private const float SPEED_MULTIPLIER = 1.3f; private const float STAMINA_RECOVERY_RATE = 0.015f; private const int TIER_STAMINA = 2; private const int TIER_ENEMY_REVEAL = 3; private const float ENEMY_REVEAL_RANGE = 30f; private const float ENEMY_REVEAL_DURATION = 5f; private const float ENEMY_REVEAL_PERIOD = 20f; private const float EVALUATION_INTERVAL = 0.5f; internal static bool LoneWolfActive = false; internal static int ActiveLevel = 0; private static float _nextEvaluationTime = 0f; private static Coroutine _revealRoutine; private static readonly List RevealLights = new List(); internal static void Evaluate(PlayerControllerB localPlayer) { if ((Object)(object)localPlayer == (Object)null) { return; } if (LoneWolfActive && (localPlayer.isPlayerDead || localPlayer.isInHangarShipRoom)) { Deactivate(announce: true); } else { if (Time.time < _nextEvaluationTime) { return; } _nextEvaluationTime = Time.time + 0.5f; bool flag = IsOnlySurvivorOutside(localPlayer); if (flag && !LoneWolfActive) { Activate(Y4NGZUpgradeState.GetTier("Lone Wolf")); } else if (!flag && LoneWolfActive) { Deactivate(announce: true); } else { if (!LoneWolfActive) { return; } int tier = Y4NGZUpgradeState.GetTier("Lone Wolf"); if (tier != ActiveLevel) { ActiveLevel = tier; ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)$"Lone Wolf level changed to {tier} while active."); } } SyncRevealRoutine(); } } } private static bool IsOnlySurvivorOutside(PlayerControllerB localPlayer) { if (!Y4NGZUpgradeState.GetActiveUpgrade("Lone Wolf")) { return false; } if (localPlayer.isPlayerDead || localPlayer.isInHangarShipRoom || !localPlayer.isPlayerControlled) { return false; } PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return false; } int num = 0; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled && !val.isPlayerDead && !val.isInHangarShipRoom) { num++; if (num > 1) { return false; } } } return num == 1; } private static void Activate(int level) { if (!LoneWolfActive) { LoneWolfActive = true; ActiveLevel = level; MergedUpgradePatches.SetSpeedMultiplier("lone_wolf", 1.3f); SyncRevealRoutine(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Lone Wolf activated (level {level}, speed x{1.3f:F2})."); } HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LONE WOLF", GetActivationMessage(level), false, false, "LC_Tip1"); } } } internal static void Deactivate(bool announce = false) { bool loneWolfActive = LoneWolfActive; LoneWolfActive = false; ActiveLevel = 0; MergedUpgradePatches.ClearSpeedMultiplier("lone_wolf"); StopRevealRoutine(); if (!loneWolfActive) { return; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)"Lone Wolf deactivated."); } if (announce) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LONE WOLF", "You are no longer alone out here.", false, false, "LC_Tip1"); } } } internal static void Cleanup() { _nextEvaluationTime = 0f; Deactivate(); } private static string GetActivationMessage(int level) { return level switch { 1 => "You're the last one standing. Movement speed increased.", 2 => "You're the last one standing. Speed and stamina enhanced.", _ => "You're the last one standing. Full survival mode activated.", }; } private static void SyncRevealRoutine() { bool flag = LoneWolfActive && ActiveLevel >= 3; if (flag && _revealRoutine == null) { _revealRoutine = Y4NGZPersistentRunner.Run(RevealLoop()); if (_revealRoutine == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"Lone Wolf: could not start the enemy reveal loop."); } } } else if (!flag && _revealRoutine != null) { StopRevealRoutine(); } } private static void StopRevealRoutine() { if (_revealRoutine != null) { Y4NGZPersistentRunner.Stop(_revealRoutine); _revealRoutine = null; } ClearRevealLights(); } private static IEnumerator RevealLoop() { while (LoneWolfActive && ActiveLevel >= 3) { AddRevealLights(GameNetworkManager.Instance?.localPlayerController); float litUntil = Time.time + 5f; while (Time.time < litUntil && LoneWolfActive && ActiveLevel >= 3) { PruneRevealLights(); yield return null; } ClearRevealLights(); float darkUntil = Time.time + Mathf.Max(0f, 15f); while (Time.time < darkUntil && LoneWolfActive && ActiveLevel >= 3) { yield return null; } } ClearRevealLights(); _revealRoutine = null; } private static void AddRevealLights(PlayerControllerB player) { //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_0064: 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_00b4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || player.isPlayerDead) { return; } EnemyAI[] array = Object.FindObjectsOfType(); Vector3 position = ((Component)player).transform.position; int num = 0; EnemyAI[] array2 = array; foreach (EnemyAI val in array2) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !((Object)(object)((Component)val).transform == (Object)null) && !(Vector3.Distance(((Component)val).transform.position, position) > 30f) && !((Object)(object)((Component)val).gameObject.GetComponent() != (Object)null)) { Light val2 = ((Component)val).gameObject.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.2f, 0.2f); val2.intensity = 4f; val2.range = 10f; val2.shadows = (LightShadows)0; RevealLights.Add(new RevealLight { Enemy = val, Light = val2 }); num++; } } if (num > 0) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)$"Lone Wolf tier 3: revealed {num} nearby enemies."); } } } private static void PruneRevealLights() { for (int num = RevealLights.Count - 1; num >= 0; num--) { RevealLight revealLight = RevealLights[num]; if (!((Object)(object)revealLight.Enemy != (Object)null) || revealLight.Enemy.isEnemyDead || !((Object)(object)revealLight.Light != (Object)null)) { if ((Object)(object)revealLight.Light != (Object)null) { Object.Destroy((Object)(object)revealLight.Light); } RevealLights.RemoveAt(num); } } } private static void ClearRevealLights() { for (int i = 0; i < RevealLights.Count; i++) { Light light = RevealLights[i].Light; if ((Object)(object)light != (Object)null) { Object.Destroy((Object)(object)light); } } RevealLights.Clear(); } internal static void ApplyStaminaBonus(PlayerControllerB player) { if (LoneWolfActive && ActiveLevel >= 2 && !((Object)(object)player == (Object)null) && !player.isPlayerDead) { player.sprintMeter = Mathf.Clamp01(player.sprintMeter + Time.deltaTime * 0.015f); } } } internal static class SpatialAwarenessUpgrade { public const string UPGRADE_NAME = "Spatial Awareness"; public const int TIER_LIGHT_FEET = 1; public const int TIER_DONT_SHOOT = 2; public const int TIER_GROUNDED = 3; public const int TIER_NPC = 4; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Spatial Awareness"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Spatial Awareness"); } public static bool HasTier(int requiredTier) { return GetTier() >= requiredTier; } } internal static class LightFeetUpgrade { public const string UPGRADE_NAME = "Light Feet"; public const int TIER_LIGHT_FEET = 1; public const int TIER_TURRET_DELAY = 2; public const int TIER_DONT_SHOOT = 2; public const int TIER_GROUNDED = 3; public const float TURRET_FIRE_DELAY_SECONDS = 2.5f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Light Feet"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Light Feet"); } public static bool HasTier(int requiredTier) { return GetTier() >= requiredTier; } } internal static class SalvagerUpgrade { public const string UPGRADE_NAME = "Salvager"; public const int TIER_GLOW = 1; public const int TIER_BEACON = 2; public const int TIER_TRAIL = 3; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Salvager"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Salvager"); } public static bool HasTier(int requiredTier) { return GetTier() >= requiredTier; } } internal static class PredatorInstinctUpgrade { public const string UPGRADE_NAME = "Predator Instinct"; public static readonly float[] RANGE_BY_LEVEL = new float[3] { 10f, 20f, 30f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Predator Instinct"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Predator Instinct"); } public static float GetRange() { int tier = GetTier(); if (tier > 0) { return RANGE_BY_LEVEL[Mathf.Clamp(tier - 1, 0, RANGE_BY_LEVEL.Length - 1)]; } return 0f; } public static bool ShouldHeartbeat() { return GetTier() >= 3; } } internal static class SixthSenseUpgrade { public const string UPGRADE_NAME = "Sixth Sense"; public const float BASE_RANGE = 15f; public const float HAZARD_RANGE = 5f; public const float ITEM_RANGE = 10f; public const float ENEMY_RANGE = 15f; public const float REFRESH_INTERVAL = 0.25f; public const float OUTLINE_SECONDS = 0.6f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Sixth Sense"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Sixth Sense"); } public static bool ShowsItems() { return GetTier() >= 2; } public static bool ShowsEnemies() { return GetTier() >= 3; } } internal static class FieldOpticsUpgrade { public const string UPGRADE_ID = "better_scanner"; public const string UPGRADE_NAME = "Field Optics"; public const float RANGE_BONUS_PER_TIER = 0.15f; private static readonly float[] LIGHT_INTENSITY_BONUS_BY_TIER = new float[3] { 0.1f, 0.15f, 0.4f }; private static readonly float[] LIGHT_CONE_BONUS_BY_TIER = new float[3] { 0.1f, 0.2f, 0.3f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("better_scanner"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("better_scanner"); } public static float GetRangeMultiplier() { return 1f + (float)Mathf.Max(0, GetTier()) * 0.15f; } public static float GetLightIntensityMultiplier() { return 1f + BonusForTier(LIGHT_INTENSITY_BONUS_BY_TIER); } public static float GetLightConeMultiplier() { return 1f + BonusForTier(LIGHT_CONE_BONUS_BY_TIER); } private static float BonusForTier(float[] table) { int tier = GetTier(); if (tier > 0) { return table[Mathf.Clamp(tier - 1, 0, table.Length - 1)]; } return 0f; } } internal static class TransporterUpgrade { public const string UPGRADE_NAME = "Transporter"; public const float WEIGHT_REDUCTION_PER_TIER = 0.2f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Transporter"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Transporter"); } public static float GetCarryWeightMultiplier() { return Mathf.Clamp01(1f - (float)Mathf.Max(0, GetTier()) * 0.2f); } public static bool CanCarryTwoTwoHandedItems() { return false; } } internal static class ShadowStepUpgrade { public const string UPGRADE_NAME = "Shadow Step"; public const float INVISIBILITY_DURATION = 6f; public const float COOLDOWN_DURATION = 120f; public const float REDUCED_DETECTION_MULTIPLIER = 0.75f; public static bool IsInvisible; public static float InvisibilityEndTime; public static float CooldownEndTime; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Shadow Step"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Shadow Step"); } public static bool HasActiveAbility() { return GetTier() >= 3; } } internal static class RetaliationUpgrade { public const string UPGRADE_NAME = "Resilience"; public const float REFLECT_CHANCE = 0.5f; public const float TIER2_STUN_SECONDS = 1f; public static bool HasMergedRetaliation() { return Y4NGZUpgradeState.GetTier("Resilience") >= 4; } } internal static class DeathboundUpgrade { public const string UPGRADE_NAME = "Deathbound"; public const int PROTECTED_SLOT_INDEX = 0; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Deathbound"); } } internal static class GlowInTheDarkUpgrade { public const string UPGRADE_NAME = "Night Vision"; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Night Vision"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Night Vision"); } public static float GetRange() { return GetTier() switch { 1 => 24f, 2 => 32f, 3 => 40f, _ => 0f, }; } public static float GetIntensity() { return GetTier() switch { 1 => 0.12f, 2 => 0.16f, 3 => 0.22f, _ => 0f, }; } } internal static class ExtraSlotUpgrade { public const string UPGRADE_NAME = "Deeper Pockets"; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Deeper Pockets"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Deeper Pockets"); } public static bool CanCarryTwoTwoHandedItems() { return GetTier() >= 3; } } internal static class SquadSightUpgrade { public const string UPGRADE_NAME = "Squad Sight"; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Squad Sight"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Squad Sight"); } public static float GetRange() { return GetTier() switch { 1 => 15f, 2 => 30f, _ => 0f, }; } public static float GetVisibilityMultiplier() { return GetTier() switch { 1 => 0.6f, 2 => 0.85f, 3 => 1f, _ => 0f, }; } } internal static class PanicSlideUpgrade { public const string UPGRADE_ID = "panic_slide"; public const float COOLDOWN_SECONDS = 2.25f; public const float STAMINA_COST = 0.14f; public const float SLIDE_FORCE = 15.5f; public const float MIN_SPRINT_METER = 0.16f; public const float SLIDE_DURATION_SECONDS = 1.35f; public const float SLIDE_SUSTAIN_FORCE = 4.5f; public const float SLIDE_STEERING_DEGREES_PER_SECOND = 60f; public const float SLIDE_CAMERA_DIP = 0.5f; public const float SLIDE_CAMERA_HEAD_UP_OFFSET = 0.1f; public const float SLIDE_CAMERA_HEAD_FORWARD_OFFSET = 0.1f; public const float SLIDE_CAMERA_HEAD_SMOOTH_TIME = 0.08f; public const float SLIDE_CAMERA_HEAD_MAX_OFFSET_METERS = 1f; public const float SLIDE_CAMERA_HEAD_BLEND_IN_SECONDS = 0.12f; public const float SLIDE_CAMERA_HEAD_BLEND_OUT_SECONDS = 0.15f; public const float SLIDE_CAMERA_ROLL_DEGREES = 7f; public const float SLIDE_CAMERA_DIP_IN_SECONDS = 0.15f; public const float SLIDE_CAMERA_DIP_OUT_SECONDS = 0.2f; public const float SLIDE_EXIT_ANIMATION_SECONDS = 0.55f; public const float SLIDE_AIRBORNE_CANCEL_SECONDS = 0.35f; public const float SLIDE_MIN_SPEED_GRACE_SECONDS = 0.4f; public const float SLIDE_MIN_HORIZONTAL_SPEED = 2.5f; public const float MANTLE_RETRY_SECONDS = 0.05f; public const float MANTLE_COOLDOWN_SECONDS = 0.8f; public const float MANTLE_FORWARD_REACH = 1.35f; public const float MANTLE_MIN_LEDGE_HEIGHT = 0.95f; public const float MANTLE_MAX_LEDGE_HEIGHT = 3f; public const float MANTLE_TALL_THRESHOLD = 1.35f; public const float MANTLE_STAMINA_COST = 0.08f; public const float MANTLE_ONE_METER_SECONDS = 0.667f; public const float MANTLE_TWO_METER_SECONDS = 1.3f; public const float MANTLE_CAMERA_DIP = 0.25f; public const float MANTLE_CAMERA_DIP_IN_SECONDS = 0.12f; public const float MANTLE_CAMERA_DIP_OUT_SECONDS = 0.18f; public const float MANTLE_BODY_LOWER_METERS = 0.25f; public const float MANTLE_BODY_LOWER_RAMP_OUT_FRACTION = 0.25f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("panic_slide"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("panic_slide"); } public static bool HasDoubleJump() { return GetTier() >= 3; } } internal static class TurretHackerUpgrade { public const string UPGRADE_NAME = "Field Mechanic"; public const string UPGRADE_ID = "turret_hacker"; public const float COOLDOWN_SECONDS = 20f; public const float HACK_HOLD_SECONDS = 1.2f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Field Mechanic"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Field Mechanic"); } public static bool CanHackCameras() { return GetTier() >= 1; } public static bool CanHackDoors() { return GetTier() >= 2; } public static bool CanHackTurrets() { return GetTier() >= 3; } public static bool CanRepairBatteries() { return GetTier() >= 2; } public static float GetDrillPumpRepairSpeedMultiplier() { if (GetTier() < 1) { return 1f; } return 1.5f; } public static float GetBreakChanceMultiplier() { if (GetTier() < 1) { return 1f; } return 0.5f; } public static float GetDuration() { if (GetTier() < 2) { return 30f; } return 90f; } } internal static class FieldOperationsUpgrade { public const string UPGRADE_NAME = "Field Operations"; public const string UPGRADE_ID = "field_operations"; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Field Operations"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Field Operations"); } } internal static class CourierDroneUpgrade { public const string UPGRADE_NAME = "Courier Drone"; public const float COMMAND_COOLDOWN_SECONDS = 3f; public const float PICKUP_RADIUS = 10f; public const int MAX_ITEMS_PER_SWEEP = 12; public const float MAX_CARGO_WEIGHT_LB = 150f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Courier Drone"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Courier Drone"); } } internal static class BuddySystemUpgrade { public const string UPGRADE_NAME = "Buddy System"; private static readonly float[] RangeByTier = new float[2] { 10f, 15f }; private static readonly float[] BuffByTier = new float[2] { 0.03f, 0.06f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Buddy System"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Buddy System"); } public static float GetRange() { return GetRange(GetTier()); } public static float GetRange(int tier) { if (tier > 0) { return RangeByTier[Mathf.Clamp(tier - 1, 0, RangeByTier.Length - 1)]; } return 0f; } public static float GetBuff() { return GetBuff(GetTier()); } public static float GetBuff(int tier) { if (tier > 0) { return BuffByTier[Mathf.Clamp(tier - 1, 0, BuffByTier.Length - 1)]; } return 0f; } } internal static class PingUpgrade { public const string UPGRADE_NAME = "Ping"; public const float COOLDOWN_SECONDS = 3f; public const float MARK_DURATION = 5f; public const float TARGET_RANGE = 80f; public const float ENEMY_DAMAGE_REDUCTION = 0.2f; public const float TEAMMATE_DAMAGE_REDUCTION = 0.2f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Ping"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Ping"); } public static bool ReducesMarkedEnemyDamage() { return GetTier() >= 2; } public static bool CanMarkTeammates() { return GetTier() >= 3; } } internal static class CommandNetUpgrade { public const string UPGRADE_NAME = "Command Net"; public const float DAMAGE_OUTLINE_SECONDS = 5f; public const float MINIMAP_RANGE_METERS = 80f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Command Net"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Command Net"); } public static bool HasVirtualWalkie() { return GetTier() >= 1; } public static bool HasDamageOutline() { return GetTier() >= 2; } public static bool HasMinimap() { return GetTier() >= 3; } } internal static class RallyCallUpgrade { public const string UPGRADE_NAME = "Rally Call"; public const float RANGE = 20f; public const float DURATION_SECONDS = 8f; public const float COOLDOWN_SECONDS = 60f; private static readonly float[] SpeedByTier = new float[3] { 0.2f, 0.25f, 0.3f }; private static readonly float[] DamageReductionByTier = new float[3] { 0.2f, 0.3f, 0.4f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Rally Call"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Rally Call"); } public static float GetSpeedBonus(int tier) { if (tier > 0) { return SpeedByTier[Mathf.Clamp(tier - 1, 0, SpeedByTier.Length - 1)]; } return 0f; } public static float GetDamageReduction(int tier) { if (tier > 0) { return DamageReductionByTier[Mathf.Clamp(tier - 1, 0, DamageReductionByTier.Length - 1)]; } return 0f; } } internal static class WorklightBeaconUpgrade { public const string UPGRADE_NAME = "Worklight Beacon"; public const float COOLDOWN_SECONDS = 0.35f; public const float THROW_FORCE = 28f; public const float LIFE_SECONDS = 180f; private static readonly int[] ChargesByTier = new int[3] { 3, 5, 9 }; private static readonly float[] IntensityByTier = new float[3] { 12f, 18f, 26f }; private static readonly float[] RangeByTier = new float[3] { 10f, 13f, 17f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Worklight Beacon"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Worklight Beacon"); } public static int GetMaxCharges() { return GetValue(ChargesByTier, GetTier()); } public static float GetIntensity(int tier) { return GetValue(IntensityByTier, tier); } public static float GetRange(int tier) { return GetValue(RangeByTier, tier); } private static T GetValue(T[] values, int tier) { if (values == null || values.Length == 0 || tier <= 0) { return default(T); } return values[Mathf.Clamp(tier - 1, 0, values.Length - 1)]; } } internal static class InspireUpgrade { public const string UPGRADE_NAME = "Inspire"; public const float REVIVE_RANGE = 7f; public const float REVIVE_CHANCE = 0.5f; public const float COOLDOWN_SECONDS = 75f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Inspire"); } } internal static class OverachieverUpgrade { public const string UPGRADE_ID = "veteran"; private static readonly int[] BonusTokensByTier = new int[3] { 1, 2, 4 }; public static int MaxBonusTokensPerRank => BonusTokensByTier[BonusTokensByTier.Length - 1]; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("veteran"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("veteran"); } public static int GetBonusTokensPerRank() { return GetBonusTokensForTier(GetTier()); } public static int GetBonusTokensForTier(int tier) { if (tier <= 0) { return 0; } return BonusTokensByTier[Mathf.Clamp(tier - 1, 0, BonusTokensByTier.Length - 1)]; } } internal static class ProteinPowderUpgrade { public const string UPGRADE_ID = "protein_powder"; public const int MELEE_FORCE_BONUS = 1; public const int STUN_TIER = 2; public const float STUN_CHANCE = 0.25f; public const float STUN_SECONDS = 1f; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("protein_powder"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("protein_powder"); } public static bool HasStagger() { return GetTier() >= 2; } } internal static class QuotaGuardUpgrade { public const string UPGRADE_ID = "quota_guard"; public const float DEATH_CREDIT_PENALTY_MULTIPLIER = 0.5f; public const float DEATH_PENALTY_FRACTION_CAP = 0.1f; public const int EXTENDED_DEADLINE_DAYS = 4; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("quota_guard"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("quota_guard"); } public static bool HasCreditPenaltyRelief() { return GetTier() >= 1; } public static bool HasQuotaCap() { return GetTier() >= 1; } public static bool HasExtendedDeadline() { return GetTier() >= 2; } } internal static class ChameleonUpgrade { public const string UPGRADE_NAME = "Chameleon"; public const string UPGRADE_ID = "chameleon"; private static readonly float[] ExtraDetectionTimeByTier = new float[3] { 0.15f, 0.3f, 0.5f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Chameleon"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Chameleon"); } public static float GetDetectionTimeMultiplier() { return GetDetectionTimeMultiplier(GetTier()); } public static float GetDetectionTimeMultiplier(int tier) { if (tier <= 0) { return 1f; } return 1f + ExtraDetectionTimeByTier[Mathf.Clamp(tier - 1, 0, ExtraDetectionTimeByTier.Length - 1)]; } } internal static class ScavengerUpgrade { public const string UPGRADE_NAME = "Scavenger"; public const string UPGRADE_ID = "scavenger"; private static readonly float[] BonusByTier = new float[3] { 0.1f, 0.2f, 0.3f }; public static bool IsUnlocked() { return Y4NGZUpgradeState.GetActiveUpgrade("Scavenger"); } public static int GetTier() { if (!IsUnlocked()) { return 0; } return Y4NGZUpgradeState.GetTier("Scavenger"); } public static float GetAmmoMultiplier() { return GetMultiplier(GetTier()); } public static float GetFuelMultiplier(int tier) { return GetMultiplier(tier); } private static float GetMultiplier(int tier) { if (tier <= 0) { return 1f; } return 1f + BonusByTier[Mathf.Clamp(tier - 1, 0, BonusByTier.Length - 1)]; } } public enum Y4NGZPurchaseMode { UpgradeCurrency, CompanyCredits, Both } public enum Y4NGZSkillTreeClass { Enforcer, Ghost, Technician, Foreman } public sealed class Y4NGZSkillTreeDefinition { public Y4NGZSkillTreeClass TreeClass { get; } public string Id { get; } public string DisplayName { get; } public int Order { get; } public int[] TierGateRequirements { get; } public Y4NGZSkillTreeDefinition(Y4NGZSkillTreeClass treeClass, string displayName, int order, int[] tierGateRequirements) { TreeClass = treeClass; DisplayName = (string.IsNullOrWhiteSpace(displayName) ? treeClass.ToString() : displayName); Id = Y4NGZUpgradeDefinition.NormalizeId(DisplayName); Order = Math.Max(0, order); TierGateRequirements = tierGateRequirements ?? Array.Empty(); } public int GetGateRequirement(int tier) { if (tier <= 1) { return 0; } int num = tier - 1; if (num >= TierGateRequirements.Length) { throw new ArgumentOutOfRangeException("tier", $"Skill tree '{DisplayName}' has no gate authored for tier {tier}."); } return Math.Max(0, TierGateRequirements[num]); } } public sealed class Y4NGZSkillTreeNodeDefinition { public string UpgradeId { get; } public Y4NGZSkillTreeClass TreeClass { get; } public int Tier { get; } public int Column { get; } public int Row { get; } public string IconKey { get; } public int GateRequirement { get; } public string DisplayName { get; } public string PrerequisiteUpgradeId { get; } public IReadOnlyList PrerequisiteUpgradeIds { get; } public IReadOnlyList ConnectionUpgradeIds { get; } public Y4NGZSkillTreeNodeDefinition(string upgradeId, Y4NGZSkillTreeClass treeClass, int tier, int column, int row, string iconKey, int gateRequirement, string displayName = null, string prerequisiteUpgradeId = null, IEnumerable prerequisiteUpgradeIds = null, IEnumerable connectionUpgradeIds = null) { UpgradeId = Y4NGZUpgradeDefinition.NormalizeId(upgradeId); TreeClass = treeClass; Tier = Math.Max(1, tier); Column = Math.Max(0, column); Row = Math.Max(0, row); IconKey = (string.IsNullOrWhiteSpace(iconKey) ? UpgradeId : Y4NGZUpgradeDefinition.NormalizeId(iconKey)); GateRequirement = Math.Max(0, gateRequirement); DisplayName = (string.IsNullOrWhiteSpace(displayName) ? (upgradeId ?? string.Empty) : displayName); List list = NormalizeIds(prerequisiteUpgradeIds); string text = Y4NGZUpgradeDefinition.NormalizeId(prerequisiteUpgradeId); if (!string.IsNullOrWhiteSpace(text) && !list.Contains(text, StringComparer.OrdinalIgnoreCase)) { list.Insert(0, text); } List list2 = NormalizeIds(connectionUpgradeIds); if (list2.Count == 0) { list2.AddRange(list); } PrerequisiteUpgradeIds = list; ConnectionUpgradeIds = list2; PrerequisiteUpgradeId = ((list.Count > 0) ? list[0] : string.Empty); } private static List NormalizeIds(IEnumerable ids) { List list = new List(); if (ids == null) { return list; } foreach (string id in ids) { string text = Y4NGZUpgradeDefinition.NormalizeId(id); if (!string.IsNullOrWhiteSpace(text) && !list.Contains(text, StringComparer.OrdinalIgnoreCase)) { list.Add(text); } } return list; } } internal static class Y4NGZUpgradeCatalog { internal static void RegisterDefaults() { Y4NGZUpgradeManager.ClearDefinitions(); RegisterSkillTrees(); OptionalUpgradeProvider loadedUpgradeProviders = OptionalPluginCapabilities.LoadedUpgradeProviders; foreach (UpgradeCatalogTable.Entry item in UpgradeCatalogTable.All) { bool flag = item.IsAvailable(loadedUpgradeProviders); EffectiveUpgradePrices prices = Plugin.ProgressionConfig?.UpgradePrices?.Resolve(item, flag) ?? new EffectiveUpgradePrices(item.UnlockPrice, item.TierPrices); if (!flag) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[UpgradeCatalog] Hiding " + item.DisplayName + "; provider requirement not met " + $"(all={item.RequiredProviders}, any={item.AnyProviders}, " + $"loaded={loadedUpgradeProviders}).")); } } else { Register(item, prices); } } RegisterMigrationDefaults(); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[UpgradePrices] Effective catalog:\n" + Plugin.ProgressionConfig?.UpgradePrices?.BuildAuditReport())); } } private static void Register(UpgradeCatalogTable.Entry entry, EffectiveUpgradePrices prices) { Y4NGZUpgradeManager.RegisterDefinition(new Y4NGZUpgradeDefinition(entry.Id, entry.DisplayName, entry.Description, prices.UnlockPrice, prices.TierPrices)); Y4NGZUpgradeManager.RegisterSkillTreeNode(new Y4NGZSkillTreeNodeDefinition(entry.Id, entry.TreeClass, entry.Tier, entry.Column, entry.Row, entry.IconKey, entry.GateRequirement, entry.DisplayName, null, entry.PrerequisiteUpgradeIds, entry.ConnectionUpgradeIds)); } private static void RegisterSkillTrees() { Y4NGZUpgradeManager.RegisterSkillTree(new Y4NGZSkillTreeDefinition(Y4NGZSkillTreeClass.Enforcer, "Enforcer", 0, UpgradeCatalogTable.GatesFor(Y4NGZSkillTreeClass.Enforcer))); Y4NGZUpgradeManager.RegisterSkillTree(new Y4NGZSkillTreeDefinition(Y4NGZSkillTreeClass.Ghost, "Ghost", 1, UpgradeCatalogTable.GatesFor(Y4NGZSkillTreeClass.Ghost))); Y4NGZUpgradeManager.RegisterSkillTree(new Y4NGZSkillTreeDefinition(Y4NGZSkillTreeClass.Technician, "Technician", 2, UpgradeCatalogTable.GatesFor(Y4NGZSkillTreeClass.Technician))); Y4NGZUpgradeManager.RegisterSkillTree(new Y4NGZSkillTreeDefinition(Y4NGZSkillTreeClass.Foreman, "Foreman", 3, UpgradeCatalogTable.GatesFor(Y4NGZSkillTreeClass.Foreman))); } private static void RegisterMigrationDefaults() { RegisterMigration("lethal_hands", "lethal_hands_training", "Lethal Hands Training display rename."); RegisterMigration("lethal_hands_haymaker", "lethal_hands_training", "Legacy Haymaker investment maps to native Lethal Hands."); RegisterMigration("deeper_pockets", "extra_inventory_slot", "Deeper Pockets legacy display-name save key."); RegisterMigration("glow_in_the_dark", "sixth_sense", "Glow in the Dark legacy save key became Sixth Sense."); RegisterMigration("night_vision", "sixth_sense", "Night Vision became Sixth Sense."); RegisterMigration("escape_reflex", "sixth_sense", "Escape Reflex investment became Sixth Sense."); RegisterMigration("escape_protocol", "sixth_sense", "Escape Protocol legacy slot now maps into Sixth Sense."); RegisterMigration("squad_sight", "buddy_system", "Squad Sight merged into Buddy System."); RegisterMigration("retaliation", "thick_skin", "Retaliation merged into Resilience."); RegisterMigration("force_field", "veteran", "Force Field retired; investment becomes Overachiever."); } private static void RegisterMigration(string sourceIdOrName, string targetId, string reason) { Y4NGZUpgradeManager.RegisterMigrationRule(new Y4NGZUpgradeMigrationRule(sourceIdOrName, targetId, reason)); } } public sealed class Y4NGZUpgradeDefinition { public string Id { get; } public string Name { get; } public string Description { get; } public int UnlockPrice { get; } public int[] Prices { get; } public bool SharedUpgrade { get; } public bool Visible { get; } public Y4NGZPurchaseMode PurchaseMode { get; } public int MaxTier => Math.Max(1, Prices.Length + 1); public Y4NGZUpgradeDefinition(string id, string name, string description, int unlockPrice, int[] tierPrices, bool sharedUpgrade = false, bool visible = true, Y4NGZPurchaseMode purchaseMode = Y4NGZPurchaseMode.UpgradeCurrency) { Id = NormalizeId(id); Name = name ?? id; Description = description ?? string.Empty; UnlockPrice = Math.Max(0, unlockPrice); Prices = tierPrices ?? Array.Empty(); SharedUpgrade = sharedUpgrade; Visible = visible; PurchaseMode = purchaseMode; } internal static string NormalizeId(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } char[] array = value.Trim().ToLowerInvariant().ToCharArray(); for (int i = 0; i < array.Length; i++) { char c = array[i]; if ((c < 'a' || c > 'z') && (c < '0' || c > '9')) { array[i] = '_'; } } return new string(array).Trim('_'); } } public enum Y4NGZUpgradePurchaseResult { Success, UnknownUpgrade, Maxed, GateLocked, PrerequisiteLocked, NotEnoughCurrency, SaveUnavailable, PriceChanged } public static class Y4NGZUpgradeManager { private sealed class ProgressionWallet : IUpgradeWallet { internal static readonly ProgressionWallet Instance = new ProgressionWallet(); public bool TryReserve(string transactionId, int amount) { return ProgressionApi.TryReserveTokenSpend(transactionId, amount); } public bool Commit(string transactionId) { return ProgressionApi.CommitTokenSpend(transactionId); } public void Cancel(string transactionId) { ProgressionApi.CancelTokenSpend(transactionId); } } private sealed class RemovedTierRefund { internal string DisplayName { get; } internal string UpgradeId { get; } internal int RemovedTier { get; } internal int Tokens { get; } internal string GrantId { get; } internal RemovedTierRefund(string displayName, string upgradeId, int removedTier, int tokens, string grantId) { DisplayName = displayName; UpgradeId = upgradeId; RemovedTier = removedTier; Tokens = tokens; GrantId = grantId; } } private static readonly Dictionary Definitions = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary Nodes = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary SkillTrees = new Dictionary(); private static readonly Dictionary SkillTreeNodes = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary MigrationRules = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary ExactIdCache = new Dictionary(StringComparer.Ordinal); private static readonly Dictionary ResolvedIdCache = new Dictionary(StringComparer.Ordinal); private static readonly string[] PhysicalConditioningMergeIds = new string[3] { "physical_conditioning", "reinforced_boots", "climbing_gloves" }; private static readonly string[] LightFeetMergeIds = new string[5] { "light_feet", "dont_shoot", "don_t_shoot", "grounded", "spatial_awareness" }; private static readonly string[] RemovedUpgradeIds = new string[19] { "aluminium_coils", "escape_protocol", "glow_in_the_dark", "lithium_batteries", "npc", "locksmith", "mechanical_arms", "sleight_of_hand", "predator_instinct", "salvager", "bandaids", "stimpack", "deeper_pockets", "shoulder_check", "pipe_bomb", "bait_bomb", "bait_beacon", "flare_burst", "rally_call" }; private static readonly RemovedTierRefund[] RemovedTierRefunds = new RemovedTierRefund[2] { new RemovedTierRefund("Veteran", "quota_guard", 3, 14, "quota_guard_tier3_refund"), new RemovedTierRefund("Pumping Iron", "protein_powder", 3, 4, "protein_powder_tier3_refund") }; private static readonly Dictionary> PendingRemovedTierRefunds = new Dictionary>(StringComparer.OrdinalIgnoreCase); private static readonly string SaveDir = Path.Combine(Application.persistentDataPath, "Y4NGZUpgrades"); private static readonly string SavePath = Path.Combine(SaveDir, "upgrade_levels.txt"); private static readonly UpgradeSaveStateStore Store = new UpgradeSaveStateStore(SaveKey.TryGetCurrent); public static int Currency => ProgressionApi.UpgradeCurrency; public static event Action UpgradesChanged; internal static void Load() { Store.Clear(); PendingRemovedTierRefunds.Clear(); try { if (File.Exists(SavePath)) { string[] array = File.ReadAllLines(SavePath); bool result = default(bool); foreach (string text in array) { if (string.IsNullOrWhiteSpace(text)) { continue; } string[] array2 = text.Split('|'); if (array2.Length >= 2) { string text2 = array2[0].Trim(); if (!string.IsNullOrWhiteSpace(text2)) { UpgradeSaveState upgradeSaveState = new UpgradeSaveState(); ParseLevels(array2[1], upgradeSaveState.Levels); upgradeSaveState.ImportedLegacyLevels = array2.Length >= 3 && bool.TryParse(array2[2], out result) && result; RecordRemovedTierRefunds(text2, upgradeSaveState); Store.SetState(text2, upgradeSaveState); } } } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Y4NGZUpgrades] Failed to load upgrade levels: {arg}"); } } FlushPendingRemovedTierRefunds(); SwitchToCurrentSave(); } private static void RecordRemovedTierRefunds(string saveKey, UpgradeSaveState state) { if (string.IsNullOrWhiteSpace(saveKey) || state == null) { return; } for (int i = 0; i < RemovedTierRefunds.Length; i++) { RemovedTierRefund removedTierRefund = RemovedTierRefunds[i]; if (state.Levels.TryGetValue(removedTierRefund.UpgradeId, out var value) && value >= removedTierRefund.RemovedTier) { if (!PendingRemovedTierRefunds.TryGetValue(saveKey, out var value2)) { value2 = new HashSet(); PendingRemovedTierRefunds[saveKey] = value2; } value2.Add(i); } } } private static void FlushPendingRemovedTierRefunds(string onlySaveKey = null) { if (PendingRemovedTierRefunds.Count == 0) { return; } string[] array = PendingRemovedTierRefunds.Keys.ToArray(); foreach (string text in array) { if (onlySaveKey != null && !string.Equals(text, onlySaveKey, StringComparison.OrdinalIgnoreCase)) { continue; } HashSet hashSet = PendingRemovedTierRefunds[text]; int[] array2 = hashSet.ToArray(); foreach (int num in array2) { RemovedTierRefund removedTierRefund = RemovedTierRefunds[num]; if (ProgressionManager.TryApplyLedgeredTokenGrant(text, removedTierRefund.GrantId, removedTierRefund.Tokens)) { hashSet.Remove(num); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Y4NGZUpgrades] {removedTierRefund.DisplayName} tier {removedTierRefund.RemovedTier} was removed; save '{text}' drops to level {removedTierRefund.RemovedTier - 1} and is refunded {removedTierRefund.Tokens} token(s)."); } } } if (hashSet.Count == 0) { PendingRemovedTierRefunds.Remove(text); } } } internal static void Save() { try { if (SwitchToCurrentSave()) { WriteStatesToDisk(); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Y4NGZUpgrades] Failed to save upgrade levels: {arg}"); } } } internal static bool SwitchToCurrentSave() { if (!Store.SwitchToCurrentSave()) { return false; } UpgradeSaveState current = Store.Current; RecordRemovedTierRefunds(Store.CurrentKey, current); FlushPendingRemovedTierRefunds(Store.CurrentKey); NormalizeStateLevels(current); TryImportLegacyLevels(); ProgressionManager.ApplyOverachieverRankBonusBackfill(); return true; } internal static void ResetCurrentSave() { if (!SaveKey.TryGetCurrentExistingOrSlot(out var key)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Y4NGZUpgrades] Upgrade reset skipped; no active save file."); } return; } DeleteForKeys(new string[1] { key }); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Y4NGZUpgrades] Reset upgrade levels for save '" + key + "'.")); } } internal static IReadOnlyCollection GetKnownSaveKeys() { return Store.Keys; } internal static int DeleteForKeys(IEnumerable keys) { int num = Store.RemoveKeys(keys); if (num > 0) { WriteStatesToDisk(); Action upgradesChanged = Y4NGZUpgradeManager.UpgradesChanged; if (upgradesChanged == null) { return num; } upgradesChanged(); } return num; } internal static void ClearDefinitions() { Definitions.Clear(); Nodes.Clear(); SkillTrees.Clear(); SkillTreeNodes.Clear(); MigrationRules.Clear(); ExactIdCache.Clear(); ResolvedIdCache.Clear(); } internal static void RegisterDefinition(Y4NGZUpgradeDefinition definition) { if (definition != null && !string.IsNullOrWhiteSpace(definition.Id)) { Definitions[definition.Id] = definition; Nodes[definition.Id] = new Y4NGZUpgradeNode(definition); } } internal static void RegisterSkillTree(Y4NGZSkillTreeDefinition definition) { if (definition != null) { SkillTrees[definition.TreeClass] = definition; } } internal static void RegisterSkillTreeNode(Y4NGZSkillTreeNodeDefinition definition) { if (definition != null && !string.IsNullOrWhiteSpace(definition.UpgradeId)) { SkillTreeNodes[definition.UpgradeId] = definition; } } internal static void RegisterMigrationRule(Y4NGZUpgradeMigrationRule rule) { if (rule != null && !string.IsNullOrWhiteSpace(rule.SourceId) && !string.IsNullOrWhiteSpace(rule.TargetId) && !string.Equals(rule.SourceId, rule.TargetId, StringComparison.OrdinalIgnoreCase)) { MigrationRules[rule.SourceId] = rule; } } public static IReadOnlyList GetUpgradeNodes() { return Nodes.Values.OrderBy((Y4NGZUpgradeNode x) => x.Name, StringComparer.OrdinalIgnoreCase).ToList(); } public static IReadOnlyList GetSkillTrees() { return SkillTrees.Values.OrderBy((Y4NGZSkillTreeDefinition x) => x.Order).ToList(); } public static IReadOnlyList GetSkillTreeNodes() { Y4NGZSkillTreeDefinition value; return (from x in SkillTreeNodes.Values orderby (!SkillTrees.TryGetValue(x.TreeClass, out value)) ? int.MaxValue : value.Order, x.Tier, x.Row, x.Column select x).ThenBy((Y4NGZSkillTreeNodeDefinition x) => x.DisplayName, StringComparer.OrdinalIgnoreCase).ToList(); } public static IReadOnlyList GetSkillTreeNodes(Y4NGZSkillTreeClass treeClass) { return (from x in SkillTreeNodes.Values where x.TreeClass == treeClass orderby x.Tier, x.Row, x.Column select x).ThenBy((Y4NGZSkillTreeNodeDefinition x) => x.DisplayName, StringComparer.OrdinalIgnoreCase).ToList(); } public static Y4NGZSkillTreeNodeDefinition GetSkillTreeNode(string idOrName) { string text = ResolveId(idOrName); if (text != null && SkillTreeNodes.TryGetValue(text, out var value)) { return value; } string b = Y4NGZUpgradeDefinition.NormalizeId(idOrName); foreach (Y4NGZSkillTreeNodeDefinition value2 in SkillTreeNodes.Values) { if (string.Equals(value2.DisplayName, idOrName, StringComparison.OrdinalIgnoreCase) || string.Equals(Y4NGZUpgradeDefinition.NormalizeId(value2.DisplayName), b, StringComparison.OrdinalIgnoreCase)) { return value2; } } return null; } public static int GetTreeInvestment(Y4NGZSkillTreeClass treeClass) { int num = 0; foreach (Y4NGZSkillTreeNodeDefinition value in SkillTreeNodes.Values) { if (value != null && value.TreeClass == treeClass) { num += Mathf.Max(0, GetLevel(value.UpgradeId)); } } return num; } public static bool IsGateLocked(Y4NGZSkillTreeNodeDefinition node, int currentLevel) { if (node == null || currentLevel > 0 || node.GateRequirement <= 0) { return false; } return GetTreeInvestment(node.TreeClass) < node.GateRequirement; } public static bool IsPrerequisiteLocked(Y4NGZSkillTreeNodeDefinition node, int currentLevel) { if (node == null || currentLevel > 0 || node.PrerequisiteUpgradeIds == null || node.PrerequisiteUpgradeIds.Count == 0) { return false; } for (int i = 0; i < node.PrerequisiteUpgradeIds.Count; i++) { if (GetLevel(node.PrerequisiteUpgradeIds[i]) <= 0) { return true; } } return false; } public static string GetPrerequisiteDisplayName(Y4NGZSkillTreeNodeDefinition node) { if (node == null || node.PrerequisiteUpgradeIds == null || node.PrerequisiteUpgradeIds.Count == 0) { return string.Empty; } List list = new List(); for (int i = 0; i < node.PrerequisiteUpgradeIds.Count; i++) { string text = node.PrerequisiteUpgradeIds[i]; if (Definitions.TryGetValue(text, out var value)) { list.Add(value.Name); continue; } Y4NGZSkillTreeNodeDefinition skillTreeNode = GetSkillTreeNode(text); list.Add((skillTreeNode != null) ? skillTreeNode.DisplayName : text); } return string.Join(" + ", list); } public static Y4NGZUpgradeNode GetUpgradeNode(string idOrName) { string text = ResolveId(idOrName); if (text == null || !Nodes.TryGetValue(text, out var value)) { return null; } return value; } public static bool IsUnlocked(string idOrName) { return GetLevel(idOrName) > 0; } public static bool IsExactUnlocked(string idOrName) { return GetExactLevel(idOrName) > 0; } public static int GetLevel(string idOrName) { string text = ResolveId(idOrName); if (text == null || !Definitions.TryGetValue(text, out var value)) { return 0; } return Store.GetLevel(text, value.MaxTier); } public static int GetExactLevel(string idOrName) { if (string.IsNullOrWhiteSpace(idOrName) || Store.Current == null) { return 0; } if (!ExactIdCache.TryGetValue(idOrName, out var value)) { string text = Y4NGZUpgradeDefinition.NormalizeId(idOrName); if (Definitions.ContainsKey(text)) { value = text; } else { foreach (Y4NGZUpgradeDefinition value3 in Definitions.Values) { if (string.Equals(value3.Name, idOrName, StringComparison.OrdinalIgnoreCase) || string.Equals(Y4NGZUpgradeDefinition.NormalizeId(value3.Name), text, StringComparison.OrdinalIgnoreCase)) { value = value3.Id; break; } } } if (value != null) { ExactIdCache[idOrName] = value; } } if (value == null || !Definitions.TryGetValue(value, out var value2)) { return 0; } return Store.GetLevel(value, value2.MaxTier); } public static void SetLevel(string idOrName, int level) { string text = ResolveId(idOrName); if (text == null || !Definitions.TryGetValue(text, out var value)) { return; } if (!SwitchToCurrentSave()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Ignored level change for '" + text + "': no save is active yet.")); } return; } UpgradeSaveState current = Store.Current; int num = Mathf.Clamp(level, 0, value.MaxTier); if (num <= 0) { current.Levels.Remove(text); } else { current.Levels[text] = num; } Save(); ApplyOverachieverBackfillFor(text); Y4NGZUpgradeManager.UpgradesChanged?.Invoke(); } private static void ApplyOverachieverBackfillFor(string upgradeId) { if (string.Equals(upgradeId, "veteran", StringComparison.OrdinalIgnoreCase)) { ProgressionManager.ApplyOverachieverRankBonusBackfill(); } } public static int GetCurrentPrice(string idOrName) { return GetUpgradeNode(idOrName)?.GetCurrentPrice() ?? int.MaxValue; } public static Y4NGZUpgradePurchaseResult Purchase(string idOrName, int quotedPrice = -1) { Y4NGZUpgradeNode upgradeNode = GetUpgradeNode(idOrName); if (upgradeNode == null) { return Y4NGZUpgradePurchaseResult.UnknownUpgrade; } if (!SwitchToCurrentSave()) { return Y4NGZUpgradePurchaseResult.SaveUnavailable; } int level = GetLevel(upgradeNode.Id); if (level >= upgradeNode.Definition.MaxTier) { return Y4NGZUpgradePurchaseResult.Maxed; } Y4NGZSkillTreeNodeDefinition skillTreeNode = GetSkillTreeNode(upgradeNode.Id); if (IsGateLocked(skillTreeNode, level)) { return Y4NGZUpgradePurchaseResult.GateLocked; } if (IsPrerequisiteLocked(skillTreeNode, level)) { return Y4NGZUpgradePurchaseResult.PrerequisiteLocked; } string transactionId = "upgrade_purchase:" + upgradeNode.Id + ":" + Guid.NewGuid().ToString("N"); int chargedPrice; int newLevel; switch (UpgradePurchaseFlow.TryPurchase(Store, upgradeNode.Id, upgradeNode.Definition.MaxTier, upgradeNode.GetPriceForLevel, quotedPrice, ProgressionWallet.Instance, transactionId, out chargedPrice, out newLevel)) { case UpgradePurchaseOutcome.Maxed: return Y4NGZUpgradePurchaseResult.Maxed; case UpgradePurchaseOutcome.SaveUnavailable: return Y4NGZUpgradePurchaseResult.SaveUnavailable; case UpgradePurchaseOutcome.PriceChanged: { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)$"[Y4NGZUpgrades] Refused '{upgradeNode.Id}': quoted {quotedPrice} token(s), live price is {upgradeNode.GetCurrentPrice()}."); } return Y4NGZUpgradePurchaseResult.PriceChanged; } default: return Y4NGZUpgradePurchaseResult.NotEnoughCurrency; case UpgradePurchaseOutcome.Success: { Save(); ApplyOverachieverBackfillFor(upgradeNode.Id); Y4NGZUpgradeManager.UpgradesChanged?.Invoke(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Y4NGZUpgrades] Purchased '{upgradeNode.Id}' level {newLevel} for {chargedPrice} token(s) on save '{Store.CurrentKey}'."); } return Y4NGZUpgradePurchaseResult.Success; } } } private static string ResolveId(string idOrName) { if (string.IsNullOrWhiteSpace(idOrName)) { return null; } if (ResolvedIdCache.TryGetValue(idOrName, out var value)) { return value; } string text = Y4NGZUpgradeDefinition.NormalizeId(idOrName); if (Definitions.ContainsKey(text)) { ResolvedIdCache[idOrName] = text; return text; } if (MigrationRules.TryGetValue(text, out var value2)) { ResolvedIdCache[idOrName] = value2.TargetId; return value2.TargetId; } foreach (Y4NGZUpgradeDefinition value3 in Definitions.Values) { if (string.Equals(value3.Name, idOrName, StringComparison.OrdinalIgnoreCase) || string.Equals(Y4NGZUpgradeDefinition.NormalizeId(value3.Name), text, StringComparison.OrdinalIgnoreCase)) { ResolvedIdCache[idOrName] = value3.Id; return value3.Id; } } return text; } private static void ParseLevels(string encoded, Dictionary levels) { levels.Clear(); if (string.IsNullOrWhiteSpace(encoded)) { return; } string[] array = encoded.Split(';'); foreach (string text in array) { if (string.IsNullOrWhiteSpace(text)) { continue; } int num = text.IndexOf('='); if (num > 0 && num < text.Length - 1) { string text2 = Y4NGZUpgradeDefinition.NormalizeId(text.Substring(0, num)); if (!string.IsNullOrWhiteSpace(text2) && int.TryParse(text.Substring(num + 1), out var result) && result > 0) { levels[text2] = result; } } } } private static void NormalizeStateLevels(UpgradeSaveState state) { if (state == null) { return; } ApplyMigrationRules(state); MergeLevels(state, "physical_conditioning", PhysicalConditioningMergeIds); MergeLevels(state, "light_feet", LightFeetMergeIds); for (int i = 0; i < RemovedUpgradeIds.Length; i++) { string key = RemovedUpgradeIds[i]; if (!SkillTreeNodes.ContainsKey(key)) { state.Levels.Remove(key); } } foreach (string item in state.Levels.Keys.ToList()) { if (!Definitions.TryGetValue(item, out var value)) { if (UpgradeCatalogTable.TryGet(item, out var entry) && entry.HasOptionalProviderRequirement) { int num = Mathf.Clamp(state.Levels[item], 0, entry.MaxTier); if (num <= 0) { state.Levels.Remove(item); } else { state.Levels[item] = num; } } else if (!SkillTreeNodes.ContainsKey(item)) { state.Levels.Remove(item); } } else { int num2 = Mathf.Clamp(state.Levels[item], 0, value.MaxTier); if (num2 <= 0) { state.Levels.Remove(item); } else { state.Levels[item] = num2; } } } } private static void MergeLevels(UpgradeSaveState state, string targetId, string[] sourceIds) { if (state == null || sourceIds == null || !Definitions.TryGetValue(targetId, out var value)) { return; } int num = (state.Levels.TryGetValue(targetId, out var value2) ? value2 : 0); foreach (string key in sourceIds) { if (state.Levels.TryGetValue(key, out var value3)) { num = Mathf.Max(num, value3); } } for (int j = 0; j < sourceIds.Length; j++) { if (!string.Equals(sourceIds[j], targetId, StringComparison.OrdinalIgnoreCase)) { state.Levels.Remove(sourceIds[j]); } } num = Mathf.Clamp(num, 0, value.MaxTier); if (num > 0) { state.Levels[targetId] = num; } else { state.Levels.Remove(targetId); } } private static void ApplyMigrationRules(UpgradeSaveState state) { if (state == null || MigrationRules.Count == 0) { return; } foreach (Y4NGZUpgradeMigrationRule value4 in MigrationRules.Values) { if (state.Levels.TryGetValue(value4.SourceId, out var value)) { int num = value; if (state.Levels.TryGetValue(value4.TargetId, out var value2)) { num = Mathf.Max(num, value2); } if (Definitions.TryGetValue(value4.TargetId, out var value3)) { num = Mathf.Clamp(num, 0, value3.MaxTier); } state.Levels.Remove(value4.SourceId); if (num > 0) { state.Levels[value4.TargetId] = num; } } } } private static void TryImportLegacyLevels() { UpgradeSaveState current = Store.Current; if (current != null && !current.ImportedLegacyLevels) { current.ImportedLegacyLevels = true; Save(); } } private static void WriteStatesToDisk() { Directory.CreateDirectory(SaveDir); List list = new List(); foreach (KeyValuePair item in Store.Entries.OrderBy, string>((KeyValuePair x) => x.Key, StringComparer.OrdinalIgnoreCase)) { if (!string.IsNullOrWhiteSpace(item.Key)) { UpgradeSaveState upgradeSaveState = item.Value ?? new UpgradeSaveState(); NormalizeStateLevels(upgradeSaveState); string arg = string.Join(";", from x in upgradeSaveState.Levels.Where((KeyValuePair x) => x.Value > 0).OrderBy, string>((KeyValuePair x) => x.Key, StringComparer.OrdinalIgnoreCase) select $"{x.Key}={Mathf.Max(0, x.Value)}"); list.Add($"{item.Key}|{arg}|{upgradeSaveState.ImportedLegacyLevels}"); } } SaveDataFile.WriteAllLinesAtomic(SavePath, list); } } public sealed class Y4NGZUpgradeMigrationRule { public string SourceId { get; } public string TargetId { get; } public string Reason { get; } public Y4NGZUpgradeMigrationRule(string sourceIdOrName, string targetId, string reason = null) { SourceId = Y4NGZUpgradeDefinition.NormalizeId(sourceIdOrName); TargetId = Y4NGZUpgradeDefinition.NormalizeId(targetId); Reason = reason ?? string.Empty; } } public sealed class Y4NGZUpgradeNode : IComparable { public Y4NGZUpgradeDefinition Definition { get; } public string Id => Definition.Id; public string Name => Definition.Name; public string OriginalName => Definition.Name; public int[] Prices => Definition.Prices; public int UnlockPrice => Definition.UnlockPrice; public string Description => Definition.Description; public bool SharedUpgrade => Definition.SharedUpgrade; public bool Visible => Definition.Visible; public bool Refundable => false; public float RefundPercentage => 1f; public int CurrentUpgrade { get { int level = Y4NGZUpgradeManager.GetLevel(Id); if (level > 0) { return Mathf.Clamp(level - 1, 0, MaxUpgrade); } return 0; } } public int MaxUpgrade => Mathf.Max(0, Definition.MaxTier - 1); public bool Unlocked => Y4NGZUpgradeManager.GetLevel(Id) > 0; internal Y4NGZUpgradeNode(Y4NGZUpgradeDefinition definition) { Definition = definition; } public int CompareTo(object obj) { if (!(obj is Y4NGZUpgradeNode y4NGZUpgradeNode)) { return -1; } return string.Compare(Name, y4NGZUpgradeNode.Name, StringComparison.OrdinalIgnoreCase); } public int GetCurrentPrice() { return GetPriceForLevel(Y4NGZUpgradeManager.GetLevel(Id)); } internal int GetPriceForLevel(int level) { return UpgradePriceMath.GetPriceForLevel(level, Definition.MaxTier, UnlockPrice, Prices); } public int GetCurrentLevel() { return Mathf.Clamp(Y4NGZUpgradeManager.GetLevel(Id), 0, Definition.MaxTier); } public int GetRemainingLevels() { return Mathf.Max(0, Definition.MaxTier - GetCurrentLevel()); } } [HarmonyPatch] internal static class Y4NGZUpgradePatches { [HarmonyPatch(typeof(StartOfRound), "Start")] [HarmonyPostfix] private static void PostStartOfRoundStart() { Y4NGZUpgradeManager.SwitchToCurrentSave(); } } } namespace Y4NGZUpgrades.UITheme { internal enum HudColorPreset { Default, Orange, Green, Blue } internal enum UiColorTheme { Orange, Green, Blue } internal static class UiTheme { private readonly struct PaletteData { internal readonly Color Accent; internal readonly Color Dim; internal readonly Color Faint; internal readonly Color Panel; internal readonly Color Muted; internal readonly Color Warning; internal readonly Color Danger; private PaletteData(Color accent, Color dim, Color faint, Color panel, Color muted, Color warning) { //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_0008: 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_000f: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_0026: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) Accent = accent; Dim = dim; Faint = faint; Panel = panel; Muted = muted; Warning = warning; Danger = new Color(0.86f, 0.13f, 0.1f, 1f); } internal static PaletteData FromHue(float hue, float dimValue, float panelValue, float saturation) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_00a5: 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_00ac: 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_00ae: 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) Color accent = FromHsv(hue, saturation, 1f, 1f); Color dim = FromHsv(hue, Mathf.Max(0.38f, saturation - 0.22f), dimValue, 0.88f); Color faint = FromHsv(hue, Mathf.Max(0.42f, saturation - 0.14f), 0.54f, 0.24f); Color panel = FromHsv(hue, Mathf.Max(0.56f, saturation - 0.1f), panelValue, 0.88f); Color muted = FromHsv(hue, 0.28f, 0.62f, 0.85f); Color warning = FromHsv(Mathf.Repeat(hue * 0.3f, 1f), 0.94f, 1f, 1f); return new PaletteData(accent, dim, faint, panel, muted, warning); } private static Color FromHsv(float hue, float saturation, float value, float alpha) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) Color result = Color.HSVToRGB(hue, saturation, value); result.a = alpha; return result; } } private const string ExternalTypeName = "Y4NGZCompany.Experience.UITheme.UiTheme, Y4NGZCompany"; private static Type _externalType; private static EventInfo _externalThemeChanged; private static Delegate _externalThemeHandler; private static Func _protectedSlotResolver; private static bool _initialized; private static readonly PaletteData Orange = PaletteData.FromHue(0.065f, 0.88f, 0.1f, 0.94f); internal static Func ProtectedSlotResolver { get { return _protectedSlotResolver; } set { _protectedSlotResolver = value; WriteExternalProtectedSlotResolver(value); } } internal static HudColorPreset CurrentPreset { get { object obj = ReadExternalProperty("CurrentPreset"); if (obj != null) { try { int num = Convert.ToInt32(obj); if (num >= 0 && num <= 3) { return (HudColorPreset)num; } } catch { } } return HudColorPreset.Default; } } internal static UiColorTheme CurrentTheme => CurrentPreset switch { HudColorPreset.Blue => UiColorTheme.Blue, HudColorPreset.Green => UiColorTheme.Green, _ => UiColorTheme.Orange, }; internal static Color Accent => ReadExternalColor("Accent", Orange.Accent); internal static Color Dim => ReadExternalColor("Dim", Orange.Dim); internal static Color Faint => ReadExternalColor("Faint", Orange.Faint); internal static Color Panel => ReadExternalColor("Panel", Orange.Panel); internal static Color Muted => ReadExternalColor("Muted", Orange.Muted); internal static Color Warning => ReadExternalColor("Warning", Orange.Warning); internal static Color Danger => ReadExternalColor("Danger", Orange.Danger); internal static event Action ThemeChanged; internal static void Initialize() { if (!_initialized) { _initialized = true; ResolveExternalTheme(); SubscribeToExternalTheme(); WriteExternalProtectedSlotResolver(_protectedSlotResolver); } } internal static void Shutdown() { if (_externalThemeChanged != null && (object)_externalThemeHandler != null) { try { _externalThemeChanged.RemoveEventHandler(null, _externalThemeHandler); } catch { } } WriteExternalProtectedSlotResolver(null); _externalThemeChanged = null; _externalThemeHandler = null; _externalType = null; UiTheme.ThemeChanged = null; _initialized = false; } internal static void Refresh() { ResolveExternalTheme(); MethodInfo methodInfo = _externalType?.GetMethod("Refresh", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (methodInfo != null) { try { methodInfo.Invoke(null, null); if ((object)_externalThemeHandler != null) { return; } } catch { } } RaiseThemeChanged(); } private static void ResolveExternalTheme() { if (!(_externalType != null) && OptionalPluginCapabilities.Contracted) { _externalType = Type.GetType("Y4NGZCompany.Experience.UITheme.UiTheme, Y4NGZCompany", throwOnError: false); } } private static void SubscribeToExternalTheme() { if (_externalType == null || (object)_externalThemeHandler != null) { return; } try { _externalThemeChanged = _externalType.GetEvent("ThemeChanged", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); Type type = _externalThemeChanged?.EventHandlerType; Type[] array = type?.GetGenericArguments(); if (!(type == null) && array != null && array.Length == 1) { MethodInfo methodInfo = typeof(UiTheme).GetMethod("OnExternalThemeChanged", BindingFlags.Static | BindingFlags.NonPublic)?.MakeGenericMethod(array[0]); if (!(methodInfo == null)) { _externalThemeHandler = Delegate.CreateDelegate(type, methodInfo); _externalThemeChanged.AddEventHandler(null, _externalThemeHandler); } } } catch { _externalThemeChanged = null; _externalThemeHandler = null; } } private static void OnExternalThemeChanged(T ignored) { RaiseThemeChanged(); } private static void RaiseThemeChanged() { Action themeChanged = UiTheme.ThemeChanged; if (themeChanged == null) { return; } HudColorPreset currentPreset = CurrentPreset; Delegate[] invocationList = themeChanged.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action)obj)(currentPreset); } catch (Exception ex) { Debug.LogWarning((object)("[Y4NGZUpgrades] UI theme listener failed: " + ex.Message)); } } } private static object ReadExternalProperty(string name) { ResolveExternalTheme(); try { return _externalType?.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null); } catch { return null; } } private static Color ReadExternalColor(string name, Color fallback) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) object obj = ReadExternalProperty(name); if (obj is Color) { return (Color)obj; } return fallback; } private static void WriteExternalProtectedSlotResolver(Func resolver) { ResolveExternalTheme(); try { FieldInfo fieldInfo = _externalType?.GetField("ProtectedSlotResolver", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (fieldInfo != null && (resolver == null || fieldInfo.FieldType.IsInstanceOfType(resolver))) { fieldInfo.SetValue(null, resolver); } } catch { } } } internal static class GameplayUiVisibility { private const string GameplaySceneName = "SampleSceneRelay"; private const string ReportTypeName = "Y4NGZCompany.Contracts._Shared.ContractPerformanceReportUi, Y4NGZCompany"; private static bool _initialized; private static bool _lastPublishedVisibility; private static PropertyInfo _reportActiveProperty; private static bool _reportProbeResolved; internal static bool IsVisible => ComputeVisibility(); internal static event Action VisibilityChanged; internal static void Initialize() { if (!_initialized) { _initialized = true; SceneManager.sceneLoaded += OnSceneLoaded; _lastPublishedVisibility = ComputeVisibility(); } } internal static void Shutdown() { if (_initialized) { SceneManager.sceneLoaded -= OnSceneLoaded; GameplayUiVisibility.VisibilityChanged = null; _initialized = false; } } internal static void PublishCurrentState(bool force = false) { bool flag = ComputeVisibility(); if (!force && flag == _lastPublishedVisibility) { return; } _lastPublishedVisibility = flag; Action visibilityChanged = GameplayUiVisibility.VisibilityChanged; if (visibilityChanged == null) { return; } Delegate[] invocationList = visibilityChanged.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action)obj)(flag); } catch { } } } private static bool ComputeVisibility() { //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) Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).IsValid() || !((Scene)(ref activeScene)).isLoaded || ((Scene)(ref activeScene)).name != "SampleSceneRelay") { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)val.quickMenuManager != (Object)null && val.quickMenuManager.isMenuOpen) { return false; } if (PlayerIsUsingTerminal(val)) { return false; } return !IsRoundEndReportActive(); } private static bool PlayerIsUsingTerminal(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } try { FieldInfo field = typeof(PlayerControllerB).GetField("inTerminalMenu", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); bool flag = default(bool); int num; if (field != null) { object value = field.GetValue(player); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static bool IsRoundEndReportActive() { if (!_reportProbeResolved) { _reportProbeResolved = true; _reportActiveProperty = (OptionalPluginCapabilities.Contracted ? Type.GetType("Y4NGZCompany.Contracts._Shared.ContractPerformanceReportUi, Y4NGZCompany", throwOnError: false) : null)?.GetProperty("IsRoundEndPresentationActive", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } try { bool flag = default(bool); int num; if (_reportActiveProperty != null) { object value = _reportActiveProperty.GetValue(null); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } catch { return false; } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { PublishCurrentState(force: true); } } internal static class GameplayHudMotion { private static bool _initialized; internal static Vector2 CurrentOffset { get; private set; } internal static event Action MotionSampled; internal static void Initialize() { //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { _initialized = true; SceneManager.sceneLoaded += OnSceneLoaded; Publish(Vector2.zero); } } internal static void Shutdown() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (_initialized) { SceneManager.sceneLoaded -= OnSceneLoaded; CurrentOffset = Vector2.zero; GameplayHudMotion.MotionSampled = null; _initialized = false; } } private static void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) Publish(Vector2.zero); } private static void Publish(Vector2 offset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) CurrentOffset = offset; Action motionSampled = GameplayHudMotion.MotionSampled; if (motionSampled == null) { return; } Delegate[] invocationList = motionSampled.GetInvocationList(); foreach (Delegate obj in invocationList) { try { ((Action)obj)(offset); } catch { } } } } internal static class ContractHudLayoutBridge { private const string ExternalTypeName = "Y4NGZCompany.Contracts._Shared.ContractHudLayoutBridge, Y4NGZCompany"; private static bool _resolved; private static MethodInfo _getStackedPromptTop; internal static float GetStackedPromptTop() { if (!_resolved) { _resolved = true; _getStackedPromptTop = (OptionalPluginCapabilities.Contracted ? Type.GetType("Y4NGZCompany.Contracts._Shared.ContractHudLayoutBridge, Y4NGZCompany", throwOnError: false) : null)?.GetMethod("GetStackedPromptTop", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); } try { return (_getStackedPromptTop?.Invoke(null, null) is float num) ? Mathf.Max(0f, num) : 0f; } catch { return 0f; } } } } namespace Y4NGZUpgrades.Patches { internal static class DamageCauseFilter { internal static bool IsEnemyMeleeCause(CauseOfDeath cause) { //IL_0000: 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_0028: Expected I4, but got Unknown //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Invalid comparison between Unknown and I4 switch (cause - 1) { default: if ((int)cause != 14) { break; } goto case 0; case 0: case 3: case 4: case 5: case 7: return true; case 1: case 2: case 6: break; } return false; } internal static bool IsEnemyOrTrapCause(CauseOfDeath cause, int deathAnimation) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_000f: Invalid comparison between Unknown and I4 //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Expected I4, but got Unknown if (IsEnemyMeleeCause(cause)) { return true; } if ((int)cause != 0 && (int)cause != 3) { switch (cause - 7) { case 0: case 4: case 5: case 6: case 8: case 10: break; default: return deathAnimation == 1; } } return true; } } [HarmonyPatch] internal static class AdrenalineRushPatch { private const float VIGNETTE_ALPHA_BASE = 0.1f; private const float VIGNETTE_ALPHA_AMP = 0.06f; private const float VIGNETTE_PULSE_HZ = 3f; private static readonly Color VIGNETTE_TINT_NORMAL = new Color(0.8f, 0.15f, 0.05f, 0f); private static readonly Color VIGNETTE_TINT_INVULN = new Color(1f, 0.95f, 0.95f, 0f); private static RawImage _vignette; private static float _pulseTime; [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] [HarmonyPriority(800)] private static void PreDamagePlayer(PlayerControllerB __instance, ref int damageNumber) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) && AdrenalineRushUpgrade.IsInvincible) { damageNumber = 0; } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)GameNetworkManager.Instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) && AdrenalineRushUpgrade.IsUnlocked() && !__instance.isPlayerDead && __instance.health > 0 && __instance.health <= 20 && !AdrenalineRushUpgrade.IsAdrenalineActive) { ActivateAdrenaline(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static bool PreKillPlayer(PlayerControllerB __instance, Vector3 bodyVelocity, bool spawnBody, CauseOfDeath causeOfDeath, int deathAnimation) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null) { return true; } if ((Object)(object)GameNetworkManager.Instance == (Object)null) { return true; } if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return true; } if (!AdrenalineRushUpgrade.HasInsurance()) { return true; } if (AdrenalineRushUpgrade.InsuranceUsedThisRound) { return true; } if (!DamageCauseFilter.IsEnemyOrTrapCause(causeOfDeath, deathAnimation)) { return true; } AdrenalineRushUpgrade.InsuranceUsedThisRound = true; TriggerSurvivalSave(__instance, "Survival insurance triggered - 2s of invincibility."); return false; } private static void TriggerSurvivalSave(PlayerControllerB player, string message) { player.health = 1; player.MakeCriticallyInjured(true); HUDManager instance = HUDManager.Instance; if (instance != null) { instance.UpdateHealthUI(player.health, false); } if (!AdrenalineRushUpgrade.IsAdrenalineActive) { ActivateAdrenaline(player); } StartInvincibility(player, 2f); HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("ADRENALINE SURGE", message, true, false, "LC_Tip1"); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)GameNetworkManager.Instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance.localPlayerController) { return; } if (AdrenalineRushUpgrade.IsInvincible && Time.time >= AdrenalineRushUpgrade.InvincibilityEndTime) { AdrenalineRushUpgrade.IsInvincible = false; } if (AdrenalineRushUpgrade.IsAdrenalineActive) { if (__instance.isPlayerDead || __instance.health > 20) { DeactivateAdrenaline(); } else { UpdateVignette(); } } } internal static void OnRoundStarted() { AdrenalineRushUpgrade.InsuranceUsedThisRound = false; AdrenalineRushUpgrade.IsInvincible = false; AdrenalineRushUpgrade.InvincibilityEndTime = 0f; DeactivateAdrenaline(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { Cleanup(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { Cleanup(); } private static void Cleanup() { AdrenalineRushUpgrade.InsuranceUsedThisRound = false; AdrenalineRushUpgrade.IsInvincible = false; AdrenalineRushUpgrade.InvincibilityEndTime = 0f; AdrenalineRushUpgrade.IsAdrenalineActive = false; MergedUpgradePatches.ClearSpeedMultiplier("AdrenalineRush"); DestroyVignette(); } private static void ActivateAdrenaline(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !AdrenalineRushUpgrade.IsAdrenalineActive) { MergedUpgradePatches.SetSpeedMultiplier("AdrenalineRush", 1.3f); AdrenalineRushUpgrade.IsAdrenalineActive = true; } } private static void DeactivateAdrenaline() { if (AdrenalineRushUpgrade.IsAdrenalineActive) { MergedUpgradePatches.ClearSpeedMultiplier("AdrenalineRush"); AdrenalineRushUpgrade.IsAdrenalineActive = false; HideVignette(); } } private static void StartInvincibility(PlayerControllerB player, float seconds) { AdrenalineRushUpgrade.IsInvincible = true; AdrenalineRushUpgrade.InvincibilityEndTime = Time.time + seconds; } private static void UpdateVignette() { //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_0067: 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) EnsureVignette(); if (!((Object)(object)_vignette == (Object)null)) { ((Component)_vignette).gameObject.SetActive(true); _pulseTime += Time.deltaTime * 3f; if (AdrenalineRushUpgrade.IsInvincible) { float a = 0.18f + 0.1f * Mathf.Abs(Mathf.Sin(Time.time * 8f)); Color vIGNETTE_TINT_INVULN = VIGNETTE_TINT_INVULN; vIGNETTE_TINT_INVULN.a = a; ((Graphic)_vignette).color = vIGNETTE_TINT_INVULN; } else { float a2 = 0.1f + 0.06f * Mathf.Sin(_pulseTime); Color vIGNETTE_TINT_NORMAL = VIGNETTE_TINT_NORMAL; vIGNETTE_TINT_NORMAL.a = a2; ((Graphic)_vignette).color = vIGNETTE_TINT_NORMAL; } } } private static void EnsureVignette() { //IL_004d: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0081: 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_00c3: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_vignette != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { GameObject val = new GameObject("AdrenalineVignette"); val.transform.SetParent(((Component)canvas).transform, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _vignette = val.AddComponent(); ((Graphic)_vignette).raycastTarget = false; ((Graphic)_vignette).color = new Color(0f, 0f, 0f, 0f); } } } private static void HideVignette() { if ((Object)(object)_vignette != (Object)null) { ((Component)_vignette).gameObject.SetActive(false); } _pulseTime = 0f; } private static void DestroyVignette() { if ((Object)(object)_vignette != (Object)null) { Object.Destroy((Object)(object)((Component)_vignette).gameObject); } _vignette = null; _pulseTime = 0f; } } internal static class ChameleonCompanyPatch { private static bool _initialized; internal static void Initialize() { if (_initialized) { return; } if (!OptionalPluginCapabilities.LethalCctv) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"Chameleon: LethalCCTV not present; camera-detection integration disabled."); } return; } try { InstallProvider(); _initialized = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"Chameleon: camera-detection multiplier provider installed."); } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("Chameleon: failed to install camera-detection provider: " + ex.Message)); } } } private static void InstallProvider() { if (!OptionalCctvBridge.InstallDetectionTimeMultiplierProvider(GetDetectionTimeMultiplier)) { throw new MissingMemberException("LethalCCTV detection-time provider API was not found."); } } private static float GetDetectionTimeMultiplier(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 1f; } PlayerControllerB val = StartOfRound.Instance?.localPlayerController; return ChameleonUpgrade.GetDetectionTimeMultiplier(((Object)(object)val != (Object)null && val.actualClientId == player.actualClientId) ? ChameleonUpgrade.GetTier() : UpgradeTierSync.GetTier(player.actualClientId, "chameleon")); } } [HarmonyPatch] internal static class CommandNetPatch { private sealed class MinimapTacticalDot { public RectTransform Rect; public Image Fill; } private struct VanillaMapUiState { public bool MapScreenPlayerNameEnabled; public bool MapScreenPlayerNameBgEnabled; public bool HeadMountedCamUiEnabled; public bool LocalPlayerPlaceholderEnabled; public bool CompassRoseEnabled; public bool ShipArrowUiActive; public bool ShipIconActive; public bool LostSignalUiActive; public bool ExitLineEnabled; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveWalkie; public static HandleNamedMessageDelegate <1>__OnReceiveDamageNotice; } private const string MSG_WALKIE = "CommandNet_Walkie"; private const string MSG_DAMAGE_OUTLINE = "CommandNet_DamageOutline"; private const string PROMPT_KEY = "command_net_walkie"; private const float MINIMAP_REFRESH_INTERVAL = 0.1f; private const float MINIMAP_SIZE = 130f; private const float MINIMAP_MARGIN = 18f; private const float MINIMAP_CHAT_GAP = 10f; private const float MINIMAP_INSET = 5f; private const float MINIMAP_BORDER_THICKNESS = 1.5f; private const float MINIMAP_BORDER_ALPHA = 0.84f; private const float MINIMAP_GRID_ALPHA = 0.2f; private const float MINIMAP_CAMERA_HEIGHT = 3.636f; private const float MINIMAP_BOOT_DURATION = 0.42f; private const float MINIMAP_BOOT_LINE_PHASE = 0.16f; private const float MINIMAP_TACTICAL_DOT_SIZE = 7.5f; private const float MINIMAP_TACTICAL_DOT_INSET = 1.35f; private const int MINIMAP_TEXTURE_SIZE = 512; private const int MINIMAP_SCANLINE_COUNT = 11; private static readonly HashSet SeenWalkieMessages = new HashSet(); private static readonly HashSet SeenDamageMessages = new HashSet(); private static readonly HashSet ActiveVirtualSpeakers = new HashSet(); private static readonly Dictionary PriorSpeakerStates = new Dictionary(); private static bool _handlersRegistered; private static int _nextMessageId; private static PlayerControllerB _listeningPlayer; private static bool _priorHoldingWalkieTalkie; private static bool _localSpeaking; private static float _nextMinimapRefresh; private static bool _presentationVisible; private static bool _hangarStateKnown; private static bool _wasInHangarShipRoom; private static Vector2 _hudMotionOffset; private static EntranceTeleport[] _cachedEntrances = Array.Empty(); private static bool _entrancesCached; private static bool _cameraMarkerFailureLogged; private static GameObject _minimapRoot; private static RectTransform _minimapRect; private static CanvasGroup _minimapCanvasGroup; private static RawImage _radarImage; private static RectTransform _tacticalMarkerLayer; private static RectTransform _markerLayer; private static Image _bootLine; private static RenderTexture _minimapTexture; private static Camera _minimapCamera; private static Camera _minimapSourceCamera; private static Sprite _pixelSprite; private static Sprite _circleSprite; private static Sprite _vignetteSprite; private static RectTransform _chatRect; private static Vector2 _chatOriginalAnchoredPosition; private static bool _chatLayoutCaptured; private static float _minimapBootStartTime; private static bool _minimapBootActive; private static readonly List MinimapMarkers = new List(); private static readonly List MinimapTacticalDots = new List(); private static readonly List MinimapAccentImages = new List(); private static readonly List MinimapGridImages = new List(); private static readonly List MinimapScanlineImages = new List(); private static VanillaMapUiState _vanillaMapUiState; private static string _cachedPromptText; private static string _cachedPromptPath; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } internal static void OnRoundStarted() { RegisterNetworkHandlers(); SeenWalkieMessages.Clear(); SeenDamageMessages.Clear(); SetVirtualSpeakerState(speaking: false); ActiveVirtualSpeakers.Clear(); PriorSpeakerStates.Clear(); _nextMinimapRefresh = 0f; _hangarStateKnown = false; _wasInHangarShipRoom = true; _cachedEntrances = Array.Empty(); _entrancesCached = false; _cameraMarkerFailureLogged = false; SetMinimapPresentationActive(active: false); SetLocalSpeaking(speaking: false); } internal static void SetPresentationVisible(bool visible) { _presentationVisible = visible; if (!visible) { SetMinimapPresentationActive(active: false); } } internal static void SetHudMotionOffset(Vector2 offset) { //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) //IL_0006: 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_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) Vector2 val = _hudMotionOffset - offset; if (!(((Vector2)(ref val)).sqrMagnitude <= 0.0001f)) { _hudMotionOffset = offset; ApplyMinimapLayout(); if ((Object)(object)_minimapRoot != (Object)null && _minimapRoot.activeSelf) { ApplyChatLayoutForMinimap(); } } } internal static void RefreshPresentationTheme() { RefreshMinimapStyle(); } internal static void ShutdownPresentation() { //IL_0006: 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) _presentationVisible = false; _hudMotionOffset = Vector2.zero; _hangarStateKnown = false; _cachedEntrances = Array.Empty(); _entrancesCached = false; DestroyMinimap(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { SetLocalSpeaking(speaking: false); ExitVirtualRadio(); DestroyMinimap(); Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("command_net_walkie"); SeenWalkieMessages.Clear(); SeenDamageMessages.Clear(); SetVirtualSpeakerState(speaking: false); ActiveVirtualSpeakers.Clear(); PriorSpeakerStates.Clear(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { RegisterNetworkHandlers(); UpdateVirtualRadioState(__instance); PollTransmitKey(__instance); UpdateCommandPrompt(__instance); UpdateMinimap(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber) { if (IsLocalPlayer(__instance) && damageNumber > 0 && !__instance.isPlayerDead) { int playerId = (int)__instance.playerClientId; int messageId = NextMessageId(); HandleDamageNotice(messageId, playerId); SendDamageNotice(messageId, playerId); } } private static void UpdateVirtualRadioState(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || !CommandNetUpgrade.HasVirtualWalkie()) { SetLocalSpeaking(speaking: false); ExitVirtualRadio(); } else { EnterVirtualRadio(player); } } private static void PollTransmitKey(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && CommandNetUpgrade.HasVirtualWalkie()) { SetLocalSpeaking(!player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu && !player.inSpecialInteractAnimation && ((Object)(object)player.quickMenuManager == (Object)null || !player.quickMenuManager.isMenuOpen) && UpgradeInput.IsPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CommandNetTransmit)); } } private static void EnterVirtualRadio(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { if ((Object)(object)_listeningPlayer != (Object)(object)player) { ExitVirtualRadio(); _listeningPlayer = player; _priorHoldingWalkieTalkie = player.holdingWalkieTalkie; } player.holdingWalkieTalkie = true; UpdateVoiceEffects(); } } private static void ExitVirtualRadio() { if ((Object)(object)_listeningPlayer != (Object)null) { _listeningPlayer.holdingWalkieTalkie = _priorHoldingWalkieTalkie; _listeningPlayer = null; } _priorHoldingWalkieTalkie = false; UpdateVoiceEffects(); } private static void SetLocalSpeaking(bool speaking) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null) { _localSpeaking = false; } else if ((speaking || _localSpeaking) && (!speaking || !_localSpeaking || !val.speakingToWalkieTalkie)) { if (speaking && (Object)(object)_listeningPlayer == (Object)null) { EnterVirtualRadio(val); } _localSpeaking = speaking; int messageId = NextMessageId(); int playerId = (int)val.playerClientId; ApplyWalkieMessage(messageId, playerId, speaking, localSender: true); SendWalkieMessage(messageId, playerId, speaking); } } private static void ApplyWalkieMessage(int messageId, int playerId, bool speaking, bool localSender) { if (!SeenWalkieMessages.Add(messageId)) { return; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null || playerId < 0 || playerId >= instance.allPlayerScripts.Length) { return; } PlayerControllerB val = instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null) { return; } val.speakingToWalkieTalkie = speaking; if (localSender) { val.activatingItem = speaking; if ((Object)(object)val.playerBodyAnimator != (Object)null) { val.playerBodyAnimator.SetBool("walkieTalkie", speaking); } } if (speaking) { ActiveVirtualSpeakers.Add(playerId); } else { ActiveVirtualSpeakers.Remove(playerId); } SetVirtualSpeakerState(ActiveVirtualSpeakers.Count > 0); PlayTransmissionSfx(playerId, speaking); UpdateVoiceEffects(); } private static void SetVirtualSpeakerState(bool speaking) { if (WalkieTalkie.allWalkieTalkies == null) { return; } if (!speaking) { foreach (KeyValuePair priorSpeakerState in PriorSpeakerStates) { if ((Object)(object)priorSpeakerState.Key != (Object)null) { priorSpeakerState.Key.clientIsHoldingAndSpeakingIntoThis = priorSpeakerState.Value; } } PriorSpeakerStates.Clear(); return; } for (int i = 0; i < WalkieTalkie.allWalkieTalkies.Count; i++) { WalkieTalkie val = WalkieTalkie.allWalkieTalkies[i]; if (!((Object)(object)val == (Object)null) && ((GrabbableObject)val).isBeingUsed) { if (!PriorSpeakerStates.ContainsKey(val)) { PriorSpeakerStates[val] = val.clientIsHoldingAndSpeakingIntoThis; } val.clientIsHoldingAndSpeakingIntoThis = true; } } } private static void PlayTransmissionSfx(int playerId, bool speaking) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || WalkieTalkie.allWalkieTalkies == null) { return; } PlayerControllerB val = ((playerId >= 0 && playerId < instance.allPlayerScripts.Length) ? instance.allPlayerScripts[playerId] : null); for (int i = 0; i < WalkieTalkie.allWalkieTalkies.Count; i++) { WalkieTalkie val2 = WalkieTalkie.allWalkieTalkies[i]; if (!((Object)(object)val2 == (Object)null) && ((GrabbableObject)val2).isBeingUsed && !((Object)(object)val2.thisAudio == (Object)null) && (!((Object)(object)val != (Object)null) || !((Object)(object)((GrabbableObject)val2).playerHeldBy == (Object)(object)val)) && !IsPocketedHeldWalkie(val2)) { AudioClip[] array = (speaking ? val2.startTransmissionSFX : val2.stopTransmissionSFX); if (array != null && array.Length != 0) { RoundManager.PlayRandomClip(val2.thisAudio, array, true, 1f, 0, 1000); } } } } private static bool IsPocketedHeldWalkie(WalkieTalkie walkie) { if ((Object)(object)walkie == (Object)null || (Object)(object)((GrabbableObject)walkie).playerHeldBy == (Object)null) { return false; } GrabbableObject currentlyHeldObjectServer = ((GrabbableObject)walkie).playerHeldBy.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer != (Object)null && (Object)(object)((Component)currentlyHeldObjectServer).GetComponent() != (Object)null) { return ((GrabbableObject)walkie).isPocketed; } return false; } private static void UpdateVoiceEffects() { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } try { StartOfRound.Instance.UpdatePlayerVoiceEffects(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Command Net] Voice update skipped: " + ex.Message)); } } } private static void HandleDamageNotice(int messageId, int playerId) { if (!SeenDamageMessages.Add(messageId) || !CommandNetUpgrade.HasDamageOutline()) { return; } StartOfRound instance = StartOfRound.Instance; if (!((Object)(object)instance == (Object)null) && instance.allPlayerScripts != null && playerId >= 0 && playerId < instance.allPlayerScripts.Length) { PlayerControllerB val = instance.allPlayerScripts[playerId]; if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && val.isPlayerControlled) { ForemanPingPatch.MarkTeammateFromCommandNet(val); } } } private static void UpdateCommandPrompt(PlayerControllerB player) { if (!CommandNetUpgrade.HasVirtualWalkie() || (Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat || player.inTerminalMenu || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("command_net_walkie"); return; } string text = UpgradeInput.EffectivePath(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CommandNetTransmit); if (_cachedPromptText == null || !string.Equals(_cachedPromptPath, text, StringComparison.Ordinal)) { _cachedPromptPath = text; string text2 = UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CommandNetTransmit, "J"); _cachedPromptText = "Walkie-talkie: [" + text2 + "]"; } Y4ngzPromptOverlay.SetPostPlayerMenuPrompt("command_net_walkie", _cachedPromptText); } private static void UpdateMinimap(PlayerControllerB player) { if (!CommandNetUpgrade.HasMinimap() || (Object)(object)player == (Object)null || player.isPlayerDead || !IsLandedOnPlanet()) { _hangarStateKnown = false; DestroyMinimap(); return; } bool isInHangarShipRoom = player.isInHangarShipRoom; bool flag = ((!_hangarStateKnown) ? (!isInHangarShipRoom) : (_wasInHangarShipRoom && !isInHangarShipRoom)); _hangarStateKnown = true; _wasInHangarShipRoom = isInHangarShipRoom; if (isInHangarShipRoom || !_presentationVisible) { SetMinimapPresentationActive(active: false); return; } bool flag2 = (Object)(object)_minimapRoot != (Object)null; EnsureMinimap(); if ((Object)(object)_minimapRoot == (Object)null) { return; } SetMinimapPresentationActive(active: true); if (flag2 && flag) { RestartMinimapBootAnimation(); } ApplyChatLayoutForMinimap(); UpdateMinimapBootAnimation(); if (Time.unscaledTime < _nextMinimapRefresh) { return; } _nextMinimapRefresh = Time.unscaledTime + 0.1f; if (!RenderMinimap(player)) { if ((Object)(object)_radarImage != (Object)null) { ((Behaviour)_radarImage).enabled = false; } HideAllMinimapMarkers(); } else { if ((Object)(object)_radarImage != (Object)null) { ((Behaviour)_radarImage).enabled = true; } UpdateMinimapMarkers(player); } } private static bool IsLandedOnPlanet() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && !instance.inShipPhase) { return instance.shipDoorsEnabled; } return false; } private static void SetMinimapPresentationActive(bool active) { if ((Object)(object)_minimapRoot == (Object)null) { if (!active) { RestoreChatLayout(); } return; } if (_minimapRoot.activeSelf != active) { _minimapRoot.SetActive(active); } if (active) { ApplyMinimapLayout(); } else { RestoreChatLayout(); } } private static void RestartMinimapBootAnimation() { //IL_003f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_minimapRect == (Object)null) && !((Object)(object)_minimapCanvasGroup == (Object)null)) { _minimapBootStartTime = Time.unscaledTime; _minimapBootActive = true; ((Transform)_minimapRect).localScale = new Vector3(1f, 0.02f, 1f); _minimapCanvasGroup.alpha = 0f; SetBootLineVisible(visible: false, 0f); } } private static void ApplyMinimapLayout() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_minimapRect == (Object)null)) { Canvas componentInParent = ((Component)_minimapRect).GetComponentInParent(); float num = (((Object)(object)componentInParent != (Object)null && componentInParent.scaleFactor > 0.01f) ? componentInParent.scaleFactor : 1f); Rect safeArea = Screen.safeArea; float num2 = ((Rect)(ref safeArea)).xMin / num; float num3 = ((Rect)(ref safeArea)).yMin / num; _minimapRect.anchoredPosition = new Vector2(18f + num2 + _hudMotionOffset.x, 83f + num3 + _hudMotionOffset.y); } } private static void UpdateMinimapBootAnimation() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_minimapRect == (Object)null || (Object)(object)_minimapCanvasGroup == (Object)null) { return; } if (!_minimapBootActive) { ((Transform)_minimapRect).localScale = Vector3.one; _minimapCanvasGroup.alpha = 1f; if ((Object)(object)_bootLine != (Object)null) { ((Component)_bootLine).gameObject.SetActive(false); } return; } float num = Time.unscaledTime - _minimapBootStartTime; float num2 = Mathf.Clamp01(num / 0.16f); float num3 = Mathf.Clamp01((num - 0.16f) / 0.26f); float num4 = Mathf.SmoothStep(0f, 1f, num2); float num5 = Mathf.SmoothStep(0f, 1f, num3); if (num < 0.16f) { ((Transform)_minimapRect).localScale = new Vector3(1f, Mathf.Lerp(0.012f, 0.035f, num4), 1f); _minimapCanvasGroup.alpha = Mathf.Lerp(0.2f, 1f, num4); SetBootLineVisible(visible: true, Mathf.Lerp(0.35f, 0.96f, num4)); return; } ((Transform)_minimapRect).localScale = new Vector3(1f, Mathf.Lerp(0.05f, 1f, num5), 1f); _minimapCanvasGroup.alpha = 1f; SetBootLineVisible(num3 < 0.78f, Mathf.Lerp(0.9f, 0f, num3)); if (num >= 0.42f) { _minimapBootActive = false; ((Transform)_minimapRect).localScale = Vector3.one; _minimapCanvasGroup.alpha = 1f; SetBootLineVisible(visible: false, 0f); } } private static void SetBootLineVisible(bool visible, float alpha) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_bootLine == (Object)null)) { ((Component)_bootLine).gameObject.SetActive(visible); ((Graphic)_bootLine).color = GetMinimapAccentColor(alpha); } } private static void ApplyChatLayoutForMinimap() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) RectTransform val = ResolveChatRect(); if (!((Object)(object)val == (Object)null)) { if ((Object)(object)_chatRect != (Object)(object)val) { RestoreChatLayout(); _chatRect = val; _chatOriginalAnchoredPosition = val.anchoredPosition; _chatLayoutCaptured = true; } float num = (((Object)(object)_minimapRect != (Object)null) ? (_minimapRect.anchoredPosition.y - 65f) : 18f); float num2 = 130f + num + 10f; val.anchoredPosition = _chatOriginalAnchoredPosition + new Vector2(0f, num2); } } private static RectTransform ResolveChatRect() { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance == (Object)null || instance.Chat == null || (Object)(object)instance.Chat.canvasGroup == (Object)null) { return null; } return ((Component)instance.Chat.canvasGroup).GetComponent(); } private static void RestoreChatLayout() { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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 (_chatLayoutCaptured && (Object)(object)_chatRect != (Object)null) { _chatRect.anchoredPosition = _chatOriginalAnchoredPosition; } _chatRect = null; _chatOriginalAnchoredPosition = Vector2.zero; _chatLayoutCaptured = false; } private static void EnsureMinimap() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_0105: 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_0148: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018b: 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) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_0210: 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_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0287: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02d0: Unknown result type (might be due to invalid IL or missing references) //IL_02e0: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_0355: Unknown result type (might be due to invalid IL or missing references) //IL_0364: Unknown result type (might be due to invalid IL or missing references) //IL_0369: Unknown result type (might be due to invalid IL or missing references) //IL_0389: Unknown result type (might be due to invalid IL or missing references) //IL_0398: Unknown result type (might be due to invalid IL or missing references) //IL_03a7: Unknown result type (might be due to invalid IL or missing references) //IL_03b6: Unknown result type (might be due to invalid IL or missing references) //IL_03bb: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Unknown result type (might be due to invalid IL or missing references) //IL_03f9: Unknown result type (might be due to invalid IL or missing references) //IL_0408: Unknown result type (might be due to invalid IL or missing references) //IL_040d: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_044b: Unknown result type (might be due to invalid IL or missing references) //IL_045a: Unknown result type (might be due to invalid IL or missing references) //IL_045f: Unknown result type (might be due to invalid IL or missing references) //IL_047f: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_049d: Unknown result type (might be due to invalid IL or missing references) //IL_04ac: Unknown result type (might be due to invalid IL or missing references) //IL_04b1: Unknown result type (might be due to invalid IL or missing references) //IL_04d1: Unknown result type (might be due to invalid IL or missing references) //IL_04e0: Unknown result type (might be due to invalid IL or missing references) //IL_04ef: Unknown result type (might be due to invalid IL or missing references) //IL_04fe: Unknown result type (might be due to invalid IL or missing references) //IL_0503: Unknown result type (might be due to invalid IL or missing references) //IL_0523: Unknown result type (might be due to invalid IL or missing references) //IL_0532: Unknown result type (might be due to invalid IL or missing references) //IL_0541: Unknown result type (might be due to invalid IL or missing references) //IL_0550: Unknown result type (might be due to invalid IL or missing references) //IL_0555: Unknown result type (might be due to invalid IL or missing references) //IL_0575: Unknown result type (might be due to invalid IL or missing references) //IL_0584: Unknown result type (might be due to invalid IL or missing references) //IL_0593: Unknown result type (might be due to invalid IL or missing references) //IL_05a2: Unknown result type (might be due to invalid IL or missing references) //IL_05a7: Unknown result type (might be due to invalid IL or missing references) //IL_05b8: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_minimapRoot != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { _minimapRoot = new GameObject("Y4NGZ_CommandNetMinimap"); _minimapRoot.transform.SetParent(((Component)canvas).transform, false); _minimapRoot.transform.SetAsLastSibling(); _minimapCanvasGroup = _minimapRoot.AddComponent(); _minimapCanvasGroup.alpha = 0f; _minimapCanvasGroup.interactable = false; _minimapCanvasGroup.blocksRaycasts = false; _minimapRect = _minimapRoot.AddComponent(); _minimapRect.anchorMin = Vector2.zero; _minimapRect.anchorMax = Vector2.zero; _minimapRect.pivot = new Vector2(0f, 0.5f); _minimapRect.sizeDelta = new Vector2(130f, 130f); ((Transform)_minimapRect).localScale = new Vector3(1f, 0.02f, 1f); Image obj = _minimapRoot.AddComponent(); obj.sprite = GetPixelSprite(); ((Graphic)obj).color = GetMinimapPanelColor(0.76f); ((Graphic)obj).raycastTarget = false; GameObject val = new GameObject("VanillaRadarTexture"); val.transform.SetParent(_minimapRoot.transform, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = new Vector2(5f, 5f); val2.offsetMax = new Vector2(-5f, -5f); _radarImage = val.AddComponent(); ((Graphic)_radarImage).color = new Color(0.86f, 0.95f, 0.78f, 0.9f); ((Graphic)_radarImage).raycastTarget = false; _radarImage.uvRect = new Rect(0f, 0f, 1f, 1f); GameObject val3 = new GameObject("TacticalMarkers"); val3.transform.SetParent(_minimapRoot.transform, false); _tacticalMarkerLayer = val3.AddComponent(); _tacticalMarkerLayer.anchorMin = Vector2.zero; _tacticalMarkerLayer.anchorMax = Vector2.one; _tacticalMarkerLayer.offsetMin = val2.offsetMin; _tacticalMarkerLayer.offsetMax = val2.offsetMax; GameObject val4 = new GameObject("NavigationMarkers"); val4.transform.SetParent(_minimapRoot.transform, false); _markerLayer = val4.AddComponent(); _markerLayer.anchorMin = Vector2.zero; _markerLayer.anchorMax = Vector2.one; _markerLayer.offsetMin = val2.offsetMin; _markerLayer.offsetMax = val2.offsetMax; Color minimapAccentColor = GetMinimapAccentColor(0.84f); Color minimapAccentColor2 = GetMinimapAccentColor(0.2f); CreateCrtScanlines(_minimapRoot.transform); CreateCrtVignette(_minimapRoot.transform); CreateLine("GridV1", _minimapRoot.transform, new Vector2(0.333f, 0f), new Vector2(0.333f, 1f), new Vector2(-0.5f, 7f), new Vector2(0.5f, -7f), minimapAccentColor2, registerAccent: false); CreateLine("GridV2", _minimapRoot.transform, new Vector2(0.666f, 0f), new Vector2(0.666f, 1f), new Vector2(-0.5f, 7f), new Vector2(0.5f, -7f), minimapAccentColor2, registerAccent: false); CreateLine("GridH1", _minimapRoot.transform, new Vector2(0f, 0.333f), new Vector2(1f, 0.333f), new Vector2(7f, -0.5f), new Vector2(-7f, 0.5f), minimapAccentColor2, registerAccent: false); CreateLine("GridH2", _minimapRoot.transform, new Vector2(0f, 0.666f), new Vector2(1f, 0.666f), new Vector2(7f, -0.5f), new Vector2(-7f, 0.5f), minimapAccentColor2, registerAccent: false); CreateLine("Top", _minimapRoot.transform, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -1.5f), new Vector2(0f, 0f), minimapAccentColor, registerAccent: true); CreateLine("Bottom", _minimapRoot.transform, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(0f, 1.5f), minimapAccentColor, registerAccent: true); CreateLine("Left", _minimapRoot.transform, new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(1.5f, 0f), minimapAccentColor, registerAccent: true); CreateLine("Right", _minimapRoot.transform, new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(-1.5f, 0f), new Vector2(0f, 0f), minimapAccentColor, registerAccent: true); CreateBootLine(_minimapRoot.transform, minimapAccentColor); EnsureMinimapTexture(); ApplyMinimapLayout(); RefreshMinimapStyle(); RestartMinimapBootAnimation(); } } } private static void CreateLine(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color, bool registerAccent) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = anchorMin; obj.anchorMax = anchorMax; obj.offsetMin = offsetMin; obj.offsetMax = offsetMax; Image val2 = val.AddComponent(); val2.sprite = GetPixelSprite(); ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; if (registerAccent) { MinimapAccentImages.Add(val2); } else { MinimapGridImages.Add(val2); } } private static Color GetMinimapAccentColor(float alpha) { //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) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Color accent = UiTheme.Accent; accent.a = alpha; return accent; } private static Color GetMinimapPanelColor(float alpha) { //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) //IL_000e: Unknown result type (might be due to invalid IL or missing references) Color panel = UiTheme.Panel; panel.a = alpha; return panel; } private static void CreateCrtScanlines(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0079: 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) for (int i = 1; i < 11; i++) { float num = (float)i / 11f; GameObject val = new GameObject($"Scanline{i}"); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(0f, num); obj.anchorMax = new Vector2(1f, num); obj.offsetMin = new Vector2(6f, -0.4f); obj.offsetMax = new Vector2(-6f, 0.4f); Image val2 = val.AddComponent(); val2.sprite = GetPixelSprite(); ((Graphic)val2).color = new Color(0f, 0f, 0f, 0.2f); ((Graphic)val2).raycastTarget = false; MinimapScanlineImages.Add(val2); } } private static void CreateCrtVignette(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0081: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("CrtVignette"); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = new Vector2(5f, 5f); obj.offsetMax = new Vector2(-5f, -5f); Image obj2 = val.AddComponent(); obj2.sprite = GetVignetteSprite(); ((Graphic)obj2).color = new Color(1f, 1f, 1f, 0.9f); ((Graphic)obj2).raycastTarget = false; } private static void CreateBootLine(Transform parent, Color accent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("BootLine"); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(0f, 0.5f); obj.anchorMax = new Vector2(1f, 0.5f); obj.offsetMin = new Vector2(6f, -0.8f); obj.offsetMax = new Vector2(-6f, 0.8f); _bootLine = val.AddComponent(); _bootLine.sprite = GetPixelSprite(); ((Graphic)_bootLine).color = accent; ((Graphic)_bootLine).raycastTarget = false; ((Component)_bootLine).gameObject.SetActive(false); } private static bool RenderMinimap(PlayerControllerB player) { //IL_0168: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_00c3: 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_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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) ManualCameraRenderer val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.mapScreen : null); Camera val2 = (((Object)(object)val != (Object)null) ? val.mapCamera : null); if ((Object)(object)player == (Object)null || (Object)(object)val2 == (Object)null) { return false; } EnsureMinimapTexture(); EnsureMinimapCamera(val2); if ((Object)(object)_minimapCamera == (Object)null || (Object)(object)_minimapTexture == (Object)null) { return false; } Vector3 val3 = ResolveMinimapFocus(player); ConfigureMinimapCamera(player, val, val2, val3.x, val3.y, val3.z); _vanillaMapUiState = HideVanillaMapUi(val); GameObject val4 = ResolveContourMap(val); bool flag = false; bool active = false; Vector3 position = Vector3.zero; if ((Object)(object)val4 != (Object)null) { flag = true; active = val4.activeSelf; position = val4.transform.position; bool flag2 = !player.isInsideFactory; val4.SetActive(flag2); if (flag2) { Vector3 position2 = val4.transform.position; val4.transform.position = new Vector3(position2.x, val3.y - 1.5f, position2.z); } } try { _minimapCamera.Render(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Command Net] Minimap render skipped: " + ex.Message)); } return false; } finally { if (flag && (Object)(object)val4 != (Object)null) { val4.SetActive(active); val4.transform.position = position; } RestoreVanillaMapUi(val); } return true; } private static VanillaMapUiState HideVanillaMapUi(ManualCameraRenderer mapScreen) { VanillaMapUiState result = default(VanillaMapUiState); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.mapScreenPlayerName != (Object)null) { result.MapScreenPlayerNameEnabled = ((Behaviour)instance.mapScreenPlayerName).enabled; ((Behaviour)instance.mapScreenPlayerName).enabled = false; } if ((Object)(object)instance.mapScreenPlayerNameBG != (Object)null) { result.MapScreenPlayerNameBgEnabled = ((Behaviour)instance.mapScreenPlayerNameBG).enabled; ((Behaviour)instance.mapScreenPlayerNameBG).enabled = false; } } if ((Object)(object)mapScreen == (Object)null) { return result; } if ((Object)(object)mapScreen.headMountedCamUI != (Object)null) { result.HeadMountedCamUiEnabled = ((Behaviour)mapScreen.headMountedCamUI).enabled; ((Behaviour)mapScreen.headMountedCamUI).enabled = false; } if ((Object)(object)mapScreen.localPlayerPlaceholder != (Object)null) { result.LocalPlayerPlaceholderEnabled = ((Behaviour)mapScreen.localPlayerPlaceholder).enabled; ((Behaviour)mapScreen.localPlayerPlaceholder).enabled = false; } if ((Object)(object)mapScreen.compassRose != (Object)null) { result.CompassRoseEnabled = ((Behaviour)mapScreen.compassRose).enabled; ((Behaviour)mapScreen.compassRose).enabled = false; } if ((Object)(object)mapScreen.shipArrowUI != (Object)null) { result.ShipArrowUiActive = mapScreen.shipArrowUI.activeSelf; mapScreen.shipArrowUI.SetActive(false); } if ((Object)(object)mapScreen.shipIcon != (Object)null) { result.ShipIconActive = mapScreen.shipIcon.activeSelf; mapScreen.shipIcon.SetActive(false); } if ((Object)(object)mapScreen.LostSignalUI != (Object)null) { result.LostSignalUiActive = mapScreen.LostSignalUI.activeSelf; mapScreen.LostSignalUI.SetActive(false); } if ((Object)(object)mapScreen.lineFromRadarTargetToExit != (Object)null) { result.ExitLineEnabled = ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled; ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled = false; } return result; } private static void RestoreVanillaMapUi(ManualCameraRenderer mapScreen) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.mapScreenPlayerName != (Object)null) { ((Behaviour)instance.mapScreenPlayerName).enabled = _vanillaMapUiState.MapScreenPlayerNameEnabled; } if ((Object)(object)instance.mapScreenPlayerNameBG != (Object)null) { ((Behaviour)instance.mapScreenPlayerNameBG).enabled = _vanillaMapUiState.MapScreenPlayerNameBgEnabled; } } if (!((Object)(object)mapScreen == (Object)null)) { if ((Object)(object)mapScreen.headMountedCamUI != (Object)null) { ((Behaviour)mapScreen.headMountedCamUI).enabled = _vanillaMapUiState.HeadMountedCamUiEnabled; } if ((Object)(object)mapScreen.localPlayerPlaceholder != (Object)null) { ((Behaviour)mapScreen.localPlayerPlaceholder).enabled = _vanillaMapUiState.LocalPlayerPlaceholderEnabled; } if ((Object)(object)mapScreen.compassRose != (Object)null) { ((Behaviour)mapScreen.compassRose).enabled = _vanillaMapUiState.CompassRoseEnabled; } if ((Object)(object)mapScreen.shipArrowUI != (Object)null) { mapScreen.shipArrowUI.SetActive(_vanillaMapUiState.ShipArrowUiActive); } if ((Object)(object)mapScreen.shipIcon != (Object)null) { mapScreen.shipIcon.SetActive(_vanillaMapUiState.ShipIconActive); } if ((Object)(object)mapScreen.LostSignalUI != (Object)null) { mapScreen.LostSignalUI.SetActive(_vanillaMapUiState.LostSignalUiActive); } if ((Object)(object)mapScreen.lineFromRadarTargetToExit != (Object)null) { ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled = _vanillaMapUiState.ExitLineEnabled; } } } private static void EnsureMinimapTexture() { //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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Expected O, but got Unknown if ((Object)(object)_minimapTexture != (Object)null && _minimapTexture.IsCreated()) { if ((Object)(object)_radarImage != (Object)null && (Object)(object)_radarImage.texture != (Object)(object)_minimapTexture) { _radarImage.texture = (Texture)(object)_minimapTexture; } return; } if ((Object)(object)_minimapTexture != (Object)null) { _minimapTexture.Release(); } _minimapTexture = new RenderTexture(512, 512, 16, (RenderTextureFormat)0) { name = "Y4NGZ_CommandNetMinimapTexture", hideFlags = (HideFlags)61, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, useMipMap = false, autoGenerateMips = false }; _minimapTexture.Create(); if ((Object)(object)_radarImage != (Object)null) { _radarImage.texture = (Texture)(object)_minimapTexture; } } private static void EnsureMinimapCamera(Camera sourceCamera) { //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_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sourceCamera == (Object)null)) { if ((Object)(object)_minimapCamera == (Object)null) { _minimapCamera = new GameObject("Y4NGZ_CommandNetMinimapCamera") { hideFlags = (HideFlags)61 }.AddComponent(); } if ((Object)(object)_minimapSourceCamera != (Object)(object)sourceCamera) { _minimapCamera.CopyFrom(sourceCamera); _minimapSourceCamera = sourceCamera; } ((Behaviour)_minimapCamera).enabled = false; _minimapCamera.targetTexture = _minimapTexture; _minimapCamera.rect = new Rect(0f, 0f, 1f, 1f); _minimapCamera.aspect = 1f; } } private static void ConfigureMinimapCamera(PlayerControllerB player, ManualCameraRenderer mapScreen, Camera sourceCamera, float focusX, float focusY, float focusZ) { //IL_0015: 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_0040: 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) ((Component)_minimapCamera).transform.SetPositionAndRotation(new Vector3(focusX, focusY + 3.636f, focusZ), ((Component)sourceCamera).transform.rotation); _minimapCamera.cullingMask = sourceCamera.cullingMask; _minimapCamera.clearFlags = sourceCamera.clearFlags; _minimapCamera.backgroundColor = sourceCamera.backgroundColor; _minimapCamera.orthographic = sourceCamera.orthographic; _minimapCamera.orthographicSize = sourceCamera.orthographicSize; _minimapCamera.fieldOfView = sourceCamera.fieldOfView; if (player.isInHangarShipRoom) { _minimapCamera.nearClipPlane = -0.96f; _minimapCamera.farClipPlane = 7.52f; } else if (!player.isInsideFactory) { float num = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraNearPlane : sourceCamera.nearClipPlane); float num2 = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraFarPlane : sourceCamera.farClipPlane); _minimapCamera.nearClipPlane = num - 18f; _minimapCamera.farClipPlane = num2 + 18f; } else { _minimapCamera.nearClipPlane = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraNearPlane : sourceCamera.nearClipPlane); _minimapCamera.farClipPlane = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraFarPlane : sourceCamera.farClipPlane); } } private static Vector3 ResolveMinimapFocus(PlayerControllerB player) { //IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) Vector3 result = ((Component)player).transform.position; RaycastHit val = default(RaycastHit); if (Physics.Raycast(((Component)player).transform.position + Vector3.up * 0.1f, Vector3.down, ref val, 5f, ((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMask : (-1), (QueryTriggerInteraction)1)) { result = ((RaycastHit)(ref val)).point + Vector3.up * 0.06f; } return result; } private static GameObject ResolveContourMap(ManualCameraRenderer mapScreen) { if ((Object)(object)mapScreen == (Object)null) { return null; } if ((Object)(object)mapScreen.contourMap != (Object)null) { return mapScreen.contourMap; } GameObject val = null; try { val = GameObject.FindGameObjectWithTag("TerrainContourMap"); } catch { return null; } if ((Object)(object)val != (Object)null) { mapScreen.contourMap = val; } return val; } private static void RefreshMinimapStyle() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_002d: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) Color minimapAccentColor = GetMinimapAccentColor(0.84f); for (int i = 0; i < MinimapAccentImages.Count; i++) { if ((Object)(object)MinimapAccentImages[i] != (Object)null) { ((Graphic)MinimapAccentImages[i]).color = minimapAccentColor; } } Color minimapAccentColor2 = GetMinimapAccentColor(0.2f); for (int j = 0; j < MinimapGridImages.Count; j++) { if ((Object)(object)MinimapGridImages[j] != (Object)null) { ((Graphic)MinimapGridImages[j]).color = minimapAccentColor2; } } for (int k = 0; k < MinimapScanlineImages.Count; k++) { if ((Object)(object)MinimapScanlineImages[k] != (Object)null) { ((Graphic)MinimapScanlineImages[k]).color = new Color(0f, 0f, 0f, 0.2f); } } if ((Object)(object)_bootLine != (Object)null && !_minimapBootActive) { ((Graphic)_bootLine).color = minimapAccentColor; } } private static void UpdateMinimapMarkers(PlayerControllerB player) { //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_tacticalMarkerLayer == (Object)null || (Object)(object)_markerLayer == (Object)null || (Object)(object)_minimapCamera == (Object)null || (Object)(object)player == (Object)null) { return; } int used = 0; if (OptionalPluginCapabilities.LethalCctv) { try { AddCameraMarkers(ref used); } catch (Exception ex) { if (!_cameraMarkerFailureLogged) { _cameraMarkerFailureLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Command Net] CCTV marker integration unavailable: " + ex.Message)); } } } } AddObjectiveMarkers(ref used); AddEnemyMarkers(ref used, player); for (int i = used; i < MinimapTacticalDots.Count; i++) { MinimapTacticalDot minimapTacticalDot = MinimapTacticalDots[i]; if ((Object)(object)minimapTacticalDot?.Rect != (Object)null) { ((Component)minimapTacticalDot.Rect).gameObject.SetActive(false); } } int used2 = 0; Color minimapAccentColor = GetMinimapAccentColor(0.92f); AddMinimapMarker(ref used2, ((Component)player).transform.position, minimapAccentColor, 7f, ((Component)player).transform.eulerAngles.y); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && instance.allPlayerScripts != null) { for (int j = 0; j < instance.allPlayerScripts.Length; j++) { PlayerControllerB val = instance.allPlayerScripts[j]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)player) && !val.isPlayerDead && val.isPlayerControlled && val.isInsideFactory == player.isInsideFactory) { AddMinimapMarker(ref used2, ((Component)val).transform.position, new Color(0.96f, 0.86f, 0.62f, 0.92f), 5.5f, float.NaN); } } } AddEntranceMarkers(ref used2, player.isInsideFactory, minimapAccentColor.r, minimapAccentColor.g, minimapAccentColor.b); if (!player.isInsideFactory && (Object)(object)instance != (Object)null && (Object)(object)instance.elevatorTransform != (Object)null) { AddMinimapMarker(ref used2, instance.elevatorTransform.position, new Color(0.62f, 0.88f, 1f, 0.78f), 6f, float.NaN); } for (int k = used2; k < MinimapMarkers.Count; k++) { if ((Object)(object)MinimapMarkers[k] != (Object)null) { ((Component)MinimapMarkers[k]).gameObject.SetActive(false); } } } private static void AddCameraMarkers(ref int used) { //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_0035: 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) List list = new List(); OptionalCctvBridge.CollectCameraTransforms(list); Color accent = UiTheme.Accent; accent.a = 0.98f; for (int i = 0; i < list.Count; i++) { Transform val = list[i]; if (!((Object)(object)val == (Object)null)) { AddMinimapTacticalDot(ref used, val.position, accent); } } } private static void AddObjectiveMarkers(ref int used) { //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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) List list = new List(); OptionalCctvBridge.CollectActiveObjectivePositions(list); Color warning = UiTheme.Warning; warning.a = 0.98f; for (int i = 0; i < list.Count; i++) { AddMinimapTacticalDot(ref used, list[i], warning); } } private static void AddEnemyMarkers(ref int used, PlayerControllerB player) { //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_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) List list = (((Object)(object)RoundManager.Instance != (Object)null) ? RoundManager.Instance.SpawnedEnemies : null); if (list == null || (Object)(object)player == (Object)null) { return; } bool flag = !player.isInsideFactory; Color danger = UiTheme.Danger; danger.a = 0.98f; for (int i = 0; i < list.Count; i++) { EnemyAI val = list[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && val.isOutside == flag) { AddMinimapTacticalDot(ref used, ((Component)val).transform.position, danger); } } } private static void AddEntranceMarkers(ref int used, bool playerIsInside, float accentR, float accentG, float accentB) { //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) if (!_entrancesCached) { _cachedEntrances = Object.FindObjectsOfType(); _entrancesCached = true; } bool flag = !playerIsInside; for (int i = 0; i < _cachedEntrances.Length; i++) { EntranceTeleport val = _cachedEntrances[i]; if (!((Object)(object)val == (Object)null) && val.isEntranceToBuilding == flag) { bool flag2 = val.entranceId == 0; Color color = (flag2 ? new Color(accentR, accentG, accentB, 0.86f) : new Color(1f, 0.68f, 0.34f, 0.78f)); AddMinimapMarker(ref used, ResolveEntrancePosition(val), color, flag2 ? 6f : 4.5f, float.NaN); } } } private static Vector3 ResolveEntrancePosition(EntranceTeleport entrance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)entrance == (Object)null) { return Vector3.zero; } if (!((Object)(object)entrance.entrancePoint != (Object)null)) { return ((Component)entrance).transform.position; } return entrance.entrancePoint.position; } private static void AddMinimapMarker(ref int used, Vector3 worldPosition, Color color, float size, float headingDegrees) { //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_0033: 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_0072: 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_007d: Unknown result type (might be due to invalid IL or missing references) if (TryWorldToMinimapPosition(worldPosition + Vector3.up * 0.25f, out var anchoredPosition)) { Image minimapMarker = GetMinimapMarker(used); used++; RectTransform component = ((Component)minimapMarker).GetComponent(); component.anchoredPosition = anchoredPosition; component.sizeDelta = new Vector2(size, size); ((Transform)component).localEulerAngles = (float.IsNaN(headingDegrees) ? new Vector3(0f, 0f, 45f) : new Vector3(0f, 0f, 0f - headingDegrees)); ((Graphic)minimapMarker).color = color; ((Component)minimapMarker).gameObject.SetActive(true); } } private static void AddMinimapTacticalDot(ref int used, Vector3 worldPosition, Color color) { //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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (TryWorldToMinimapPosition(worldPosition + Vector3.up * 0.25f, out var anchoredPosition)) { MinimapTacticalDot minimapTacticalDot = GetMinimapTacticalDot(used); used++; minimapTacticalDot.Rect.anchoredPosition = anchoredPosition; minimapTacticalDot.Rect.sizeDelta = new Vector2(7.5f, 7.5f); ((Transform)minimapTacticalDot.Rect).localEulerAngles = Vector3.zero; ((Graphic)minimapTacticalDot.Fill).color = color; ((Component)minimapTacticalDot.Rect).gameObject.SetActive(true); } } private static bool TryWorldToMinimapPosition(Vector3 worldPosition, out Vector2 anchoredPosition) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0079: 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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) anchoredPosition = Vector2.zero; if ((Object)(object)_minimapCamera == (Object)null || (Object)(object)_markerLayer == (Object)null) { return false; } Vector3 val = _minimapCamera.WorldToViewportPoint(worldPosition); float num = Mathf.Min(_minimapCamera.nearClipPlane, _minimapCamera.farClipPlane); float num2 = Mathf.Max(_minimapCamera.nearClipPlane, _minimapCamera.farClipPlane); if (val.z < num || val.z > num2 || val.x < 0f || val.x > 1f || val.y < 0f || val.y > 1f) { return false; } Rect rect = _markerLayer.rect; anchoredPosition = new Vector2((val.x - 0.5f) * ((Rect)(ref rect)).width, (val.y - 0.5f) * ((Rect)(ref rect)).height); return true; } private static Image GetMinimapMarker(int index) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: 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_0046: 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_0064: Unknown result type (might be due to invalid IL or missing references) while (MinimapMarkers.Count <= index) { GameObject val = new GameObject("Marker"); val.transform.SetParent((Transform)(object)_markerLayer, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(0.5f, 0.5f); obj.anchorMax = new Vector2(0.5f, 0.5f); obj.pivot = new Vector2(0.5f, 0.5f); Image val2 = val.AddComponent(); val2.sprite = GetPixelSprite(); ((Graphic)val2).raycastTarget = false; val.SetActive(false); MinimapMarkers.Add(val2); } return MinimapMarkers[index]; } private static MinimapTacticalDot GetMinimapTacticalDot(int index) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0047: 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_0066: 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_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_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) while (MinimapTacticalDots.Count <= index) { GameObject val = new GameObject("TacticalDot"); val.transform.SetParent((Transform)(object)_tacticalMarkerLayer, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0.5f, 0.5f); val2.anchorMax = new Vector2(0.5f, 0.5f); val2.pivot = new Vector2(0.5f, 0.5f); Image obj = val.AddComponent(); obj.sprite = GetCircleSprite(); ((Graphic)obj).color = new Color(0.01f, 0.015f, 0.02f, 0.94f); ((Graphic)obj).raycastTarget = false; GameObject val3 = new GameObject("Fill"); val3.transform.SetParent((Transform)(object)val2, false); RectTransform obj2 = val3.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = new Vector2(1.35f, 1.35f); obj2.offsetMax = new Vector2(-1.35f, -1.35f); Image val4 = val3.AddComponent(); val4.sprite = GetCircleSprite(); ((Graphic)val4).raycastTarget = false; val.SetActive(false); MinimapTacticalDots.Add(new MinimapTacticalDot { Rect = val2, Fill = val4 }); } return MinimapTacticalDots[index]; } private static void HideAllMinimapMarkers() { for (int i = 0; i < MinimapTacticalDots.Count; i++) { MinimapTacticalDot minimapTacticalDot = MinimapTacticalDots[i]; if ((Object)(object)minimapTacticalDot?.Rect != (Object)null) { ((Component)minimapTacticalDot.Rect).gameObject.SetActive(false); } } for (int j = 0; j < MinimapMarkers.Count; j++) { if ((Object)(object)MinimapMarkers[j] != (Object)null) { ((Component)MinimapMarkers[j]).gameObject.SetActive(false); } } } private static void DestroyMinimap() { RestoreChatLayout(); if ((Object)(object)_minimapRoot != (Object)null) { Object.Destroy((Object)(object)_minimapRoot); } if ((Object)(object)_minimapCamera != (Object)null) { Object.Destroy((Object)(object)((Component)_minimapCamera).gameObject); } if ((Object)(object)_minimapTexture != (Object)null) { _minimapTexture.Release(); Object.Destroy((Object)(object)_minimapTexture); } _minimapRoot = null; _minimapRect = null; _minimapCanvasGroup = null; _radarImage = null; _tacticalMarkerLayer = null; _markerLayer = null; _bootLine = null; _minimapCamera = null; _minimapSourceCamera = null; _minimapTexture = null; _minimapBootStartTime = 0f; _minimapBootActive = false; MinimapMarkers.Clear(); MinimapTacticalDots.Clear(); MinimapAccentImages.Clear(); MinimapGridImages.Clear(); MinimapScanlineImages.Clear(); } private static Sprite GetPixelSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_004d: 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_0066: Expected O, but got Unknown if ((Object)(object)_pixelSprite != (Object)null) { return _pixelSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, Color.white); val.Apply(false, true); _pixelSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); ((Object)_pixelSprite).hideFlags = (HideFlags)61; return _pixelSprite; } private static Sprite GetCircleSprite() { //IL_0019: 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_0026: 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_0035: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_circleSprite != (Object)null) { return _circleSprite; } Texture2D val = new Texture2D(32, 32, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; for (int i = 0; i < 32; i++) { for (int j = 0; j < 32; j++) { float num = ((float)j + 0.5f) / 32f * 2f - 1f; float num2 = ((float)i + 0.5f) / 32f * 2f - 1f; float num3 = Mathf.Sqrt(num * num + num2 * num2); float num4 = 1f - Mathf.SmoothStep(0.78f, 1f, num3); val.SetPixel(j, i, new Color(1f, 1f, 1f, num4)); } } val.Apply(false, true); _circleSprite = Sprite.Create(val, new Rect(0f, 0f, 32f, 32f), new Vector2(0.5f, 0.5f)); ((Object)_circleSprite).hideFlags = (HideFlags)61; return _circleSprite; } private static Sprite GetVignetteSprite() { //IL_0019: 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_0026: 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_0035: Expected O, but got Unknown //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0109: 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) if ((Object)(object)_vignetteSprite != (Object)null) { return _vignetteSprite; } Texture2D val = new Texture2D(48, 48, (TextureFormat)4, false) { hideFlags = (HideFlags)61, wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1 }; for (int i = 0; i < 48; i++) { for (int j = 0; j < 48; j++) { float num = ((float)j + 0.5f) / 48f * 2f - 1f; float num2 = ((float)i + 0.5f) / 48f * 2f - 1f; float num3 = Mathf.Sqrt(num * num + num2 * num2); float num4 = Mathf.SmoothStep(0f, 0.42f, Mathf.InverseLerp(0.62f, 1.25f, num3)); val.SetPixel(j, i, new Color(0f, 0f, 0f, num4)); } } val.Apply(false, true); _vignetteSprite = Sprite.Create(val, new Rect(0f, 0f, 48f, 48f), new Vector2(0.5f, 0.5f)); ((Object)_vignetteSprite).hideFlags = (HideFlags)61; return _vignetteSprite; } private static int NextMessageId() { int num = (int)(((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null) ? GameNetworkManager.Instance.localPlayerController.playerClientId : 0); _nextMessageId++; return (num << 20) ^ _nextMessageId ^ Mathf.RoundToInt(Time.realtimeSinceStartup * 1000f); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveWalkie; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveWalkie; <>O.<0>__OnReceiveWalkie = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("CommandNet_Walkie", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceiveDamageNotice; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveDamageNotice; <>O.<1>__OnReceiveDamageNotice = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("CommandNet_DamageOutline", (HandleNamedMessageDelegate)obj2); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CommandNetPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void SendWalkieMessage(int messageId, int playerId, bool speaking) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendWalkieMessage(messageId, playerId, speaking, null); } else { SendWalkieMessage(messageId, playerId, speaking, 0uL); } } } private static void SendWalkieMessage(int messageId, int playerId, bool speaking, ulong? clientId) { //IL_002b: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(9, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref messageId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref speaking, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("CommandNet_Walkie", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("CommandNet_Walkie", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveWalkie(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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) try { int messageId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageId, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); bool speaking = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref speaking, default(ForPrimitives)); bool localSender = (Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null && (int)GameNetworkManager.Instance.localPlayerController.playerClientId == num; ApplyWalkieMessage(messageId, num, speaking, localSender); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendWalkieMessage(messageId, num, speaking, null); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("CommandNetPatch: malformed walkie message: " + ex.Message)); } } } private static void SendDamageNotice(int messageId, int playerId) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendDamageNotice(messageId, playerId, null); } else { SendDamageNotice(messageId, playerId, 0uL); } } } private static void SendDamageNotice(int messageId, int playerId, ulong? clientId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref messageId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("CommandNet_DamageOutline", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("CommandNet_DamageOutline", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveDamageNotice(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) try { int messageId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref messageId, default(ForPrimitives)); int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); HandleDamageNotice(messageId, playerId); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendDamageNotice(messageId, playerId, null); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("CommandNetPatch: malformed damage notice: " + ex.Message)); } } } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } [HarmonyPatch] internal static class CourierDronePatch { private enum DroneMode { NotSpawned, IdleAtPlayer, GuardingPlayer, FlyingToEntrance, AtEntrance, ReturningToShip, FlyingToPlayer, ManualControl, PointerAttack, PointerFetch } internal enum CourierCommandType { None, Spawn, Dismiss, Guard, FlyToEntrance, ReturnToShip, Flashlight, Pilot, PointerAttack, PointerFetch } private enum ManualFireKind { Flame = 1, Grenade } private struct PointerTarget { internal CourierCommandType CommandType; internal NetworkObjectReference TargetReference; internal Color ReticleColor; internal bool IsValid { get { if (CommandType != CourierCommandType.PointerAttack) { return CommandType == CourierCommandType.PointerFetch; } return true; } } } internal readonly struct TabletCommandEntry { internal readonly CourierCommandType Type; internal readonly string Label; internal readonly bool Available; internal readonly string Reason; internal TabletCommandEntry(CourierCommandType type, string label, bool available, string reason) { Type = type; Label = label; Available = available; Reason = reason; } } private sealed class CourierCommand { internal CourierCommandType Type; internal int CourierTier; internal int PlayerId = -1; internal bool PlayerWasInside; internal bool DropIsInShip; internal bool DropIsInFactory; internal bool FlashlightEnabled; internal Vector3 DroneStartPosition; internal Vector3 EntrancePosition; internal Vector3 OutsideEntrancePosition; internal Vector3 InsideEntrancePosition; internal Vector3 DropPosition; internal readonly List Items = new List(); } private sealed class MainEntranceRoute { internal Vector3 OutsidePosition; internal Vector3 InsidePosition; } private struct CourierItemMove { internal readonly ulong NetworkObjectId; internal readonly Vector3 PickupPosition; internal readonly Vector3 DropPosition; internal readonly bool PickupIsInFactory; internal CourierItemMove(ulong networkObjectId, Vector3 pickupPosition, Vector3 dropPosition, bool pickupIsInFactory) { //IL_0008: 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_000f: 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) NetworkObjectId = networkObjectId; PickupPosition = pickupPosition; DropPosition = dropPosition; PickupIsInFactory = pickupIsInFactory; } } private struct RendererPresentationState { internal readonly Renderer Renderer; internal readonly bool Enabled; internal readonly ShadowCastingMode ShadowCastingMode; internal readonly int Layer; internal RendererPresentationState(Renderer renderer, bool enabled, ShadowCastingMode shadowCastingMode, int layer) { //IL_000f: 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) Renderer = renderer; Enabled = enabled; ShadowCastingMode = shadowCastingMode; Layer = layer; } } private struct CarriedCourierItem { internal readonly CourierItemMove Move; internal readonly GrabbableObject Item; internal readonly Vector3 WorldScale; internal readonly Vector3 CarryOffset; internal readonly Quaternion CarryLocalRotation; internal readonly bool BodyWasKinematic; internal readonly bool BodyUsedGravity; internal CarriedCourierItem(CourierItemMove move, GrabbableObject item, Vector3 worldScale, Vector3 carryOffset, Quaternion carryLocalRotation, bool bodyWasKinematic, bool bodyUsedGravity) { //IL_000f: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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) Move = move; Item = item; WorldScale = worldScale; CarryOffset = carryOffset; CarryLocalRotation = carryLocalRotation; BodyWasKinematic = bodyWasKinematic; BodyUsedGravity = bodyUsedGravity; } } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveRequest; public static HandleNamedMessageDelegate <1>__OnReceiveCommand; public static HandleNamedMessageDelegate <2>__OnReceiveState; public static HandleNamedMessageDelegate <3>__OnReceiveDeath; public static HandleNamedMessageDelegate <4>__OnReceiveHit; public static HandleNamedMessageDelegate <5>__OnReceiveFlame; public static HandleNamedMessageDelegate <6>__OnReceiveGrenadeLaunch; public static HandleNamedMessageDelegate <7>__OnReceiveGrenadeExplosion; public static HandleNamedMessageDelegate <8>__OnReceiveManualPose; public static HandleNamedMessageDelegate <9>__OnReceiveManualPickup; public static HandleNamedMessageDelegate <10>__OnReceiveManualFire; public static HandleNamedMessageDelegate <11>__OnReceivePointerCommand; } private const string MSG_COURIER_REQUEST = "TechnicianCourier_Request"; private const string MSG_COURIER_COMMAND = "TechnicianCourier_Command"; private const string MSG_COURIER_STATE = "TechnicianCourier_State"; private const string MSG_COURIER_DEATH = "TechnicianCourier_Death"; private const string MSG_COURIER_HIT = "TechnicianCourier_Hit"; private const string MSG_COURIER_FLAME = "TechnicianCourier_Flame"; private const string MSG_COURIER_GRENADE_LAUNCH = "TechnicianCourier_GrenadeLaunch"; private const string MSG_COURIER_GRENADE_EXPLODE = "TechnicianCourier_GrenadeExplode"; private const string MSG_COURIER_MANUAL_POSE = "TechnicianCourier_ManualPose"; private const string MSG_COURIER_MANUAL_PICKUP = "TechnicianCourier_ManualPickup"; private const string MSG_COURIER_MANUAL_FIRE = "TechnicianCourier_ManualFire"; private const string MSG_COURIER_POINTER_COMMAND = "TechnicianCourier_PointerCommand"; private const int DRONE_FLAME_HIT_ID = 74043; private const int DRONE_MAX_HEALTH = 30; private const int DRONE_ENEMY_CONTACT_DAMAGE = 10; private const float DRONE_PROXIMITY_AGGRO_RADIUS = 5f; private const float DRONE_ENEMY_ATTACK_RANGE = 2.1f; private const float DRONE_ENEMY_ATTACK_COOLDOWN = 1.1f; private const float DRONE_ENEMY_FACE_RANGE_MULTIPLIER = 1.5f; private const float DRONE_ENEMY_FACE_TURN_DEGREES_PER_SECOND = 360f; private const float DRONE_PROXIMITY_THREAT_SECONDS = 2.5f; private const float DRONE_ATTACK_THREAT_SECONDS = 8f; private const float DRONE_DEATH_VISUAL_SECONDS = 5f; private const float DRONE_HIT_JOLT_DISTANCE = 0.12f; private const float DRONE_HIT_JOLT_SECONDS = 0.25f; private const float DRONE_ATTACK_WARNING_INTERVAL = 5f; private const float ENEMY_SCAN_INTERVAL = 0.25f; private const float FLAME_TRIGGER_RANGE = 3.5f; private const float FLAME_GUARD_RANGE = 4.5f; private const float FLAME_DAMAGE_RADIUS = 3.2f; private const int FLAME_DAMAGE = 1; private const int FLAME_TICKS = 3; private const float FLAME_COOLDOWN = 5f; private const float FLAME_DAMAGE_WINDOW_SECONDS = 1.2f; private const float GRENADE_MIN_RANGE = 8f; private const float GRENADE_MAX_RANGE = 18f; private const float GRENADE_COOLDOWN = 8f; private const float GRENADE_KILL_RANGE = 3f; private const float GRENADE_DAMAGE_RANGE = 5.5f; private const float GRENADE_SAFETY_MARGIN = 2f; private const float GRENADE_FUSE_SECONDS = 2.5f; private const float GRENADE_LOB_SPEED = 15.5f; private const float GRENADE_PROJECTILE_RADIUS = 0.18f; private const float MANUAL_DRONE_BOOT_SCREEN_SECONDS = 1f; private const float MANUAL_MOVE_SPEED = 6.2f; private const float MANUAL_VERTICAL_SPEED = 3.8f; private const float MANUAL_MOUSE_SENSITIVITY = 0.075f; private const float MANUAL_COLLISION_RADIUS = 0.34f; private const float MANUAL_CAMERA_CLEARANCE = 0.28f; private const float MANUAL_MIN_GROUND_HEIGHT = 0.88f; private const float MANUAL_MAX_GROUND_HEIGHT = 5.25f; private const float MANUAL_PICKUP_RADIUS = 4.2f; private const float MANUAL_POSE_SYNC_INTERVAL = 0.08f; private const float MANUAL_PICKUP_LOCK_SECONDS = 1.25f; private const float POINTER_COMMAND_RANGE = 45f; private const float POINTER_COMMAND_COOLDOWN_SECONDS = 1.5f; private const float POINTER_PRIORITY_SECONDS = 20f; private const float PRIORITY_TARGET_UNREACHABLE_SECONDS = 8f; private const float POINTER_FETCH_TIMEOUT_SECONDS = 25f; private const float VISUAL_FLIGHT_HEIGHT = 0.95f; private const float VISUAL_SPEED = 10.5f; private const float VISUAL_TURN_SPEED = 7.5f; private const float VISUAL_FORWARD_TILT = 10f; private const float VISUAL_MAX_BANK = 13f; private const float ENTRANCE_SCAN_SECONDS = 0.75f; private const float ENTRANCE_WAIT_SCAN_INTERVAL = 0.8f; private const float GUARD_PICKUP_RADIUS = 6f; private const float GUARD_PICKUP_SCAN_INTERVAL = 0.8f; private const float MAGNET_PICKUP_LOWER_HEIGHT = 0.78f; private const float MAGNET_PICKUP_LIFT_SECONDS = 0.55f; private const float NAVMESH_SAMPLE_RADIUS = 8f; private const float FOLLOW_SPEED = 6.8f; private const float FOLLOW_CATCHUP_DISTANCE = 8.5f; private const float FOLLOW_WARP_DISTANCE = 28f; private const float FOLLOW_SETTLE_DISTANCE = 1.35f; private const float FOLLOW_RECHASE_DISTANCE = 3.4f; private const float FOLLOW_RING_RADIUS = 2.3f; private const float FOLLOW_DIRECT_MAX_DISTANCE = 4f; private const float FOLLOW_COLLISION_RADIUS = 0.3f; private const float FOLLOW_WALL_STOP_SHORT = 0.35f; private const float FOLLOW_MOVE_SMOOTH_TIME = 0.28f; private const float FOLLOW_LOOKAHEAD_DISTANCE = 8f; private const float COLLISION_REPATH_INTERVAL = 0.6f; private const float HOVER_CLEARANCE_PROBE_INTERVAL = 0.2f; private const float HOVER_PROBE_TOP_HEIGHT = 2.2f; private const float HOVER_MAX_CLEARANCE_HEIGHT = 1.9f; private const float HOVER_MIN_CLEARANCE_HEIGHT = 0.55f; private const float HOVER_OBSTACLE_CLEARANCE = 0.22f; private const float STUCK_RESCUE_WINDOW_SECONDS = 3f; private const float STUCK_RESCUE_MIN_PROGRESS = 0.3f; private const float STUCK_RESCUE_OWNER_DISTANCE = 6f; private const float NAVMESH_REPATH_INTERVAL = 0.5f; private const float NAVMESH_REPATH_TARGET_MOVE_DISTANCE = 2f; private const float GROUND_VERTICAL_SMOOTH_SPEED = 3f; private const float CARRY_DANGLE_HEIGHT = 0.55f; private const float CARRY_FLOOR_CLEARANCE = 0.15f; private const float IDLE_SWAY_BOB_AMPLITUDE = 0.05f; private const float IDLE_SWAY_BOB_FREQUENCY = 1.2f; private const float IDLE_SWAY_DRIFT_AMPLITUDE = 0.08f; private const float IDLE_SWAY_DRIFT_FREQUENCY = 0.4f; private const float IDLE_SWAY_YAW_SPEED = 1.8f; private const float SHIP_DRONE_EDGE_MARGIN = 0.75f; private static readonly Color PointerEnemyColor = new Color(1f, 0.18f, 0.16f, 0.95f); private static readonly Color PointerItemColor = new Color(1f, 0.7f, 0.26f, 0.95f); private static readonly List PlannedItems = new List(); private static readonly List CarriedItems = new List(); private static readonly Dictionary DroneThreats = new Dictionary(); private static readonly Dictionary NextDroneHitByEnemy = new Dictionary(); private static readonly Dictionary KnownGrabbableItems = new Dictionary(); private static readonly Dictionary ActiveGrenadeVisuals = new Dictionary(); private static readonly List CachedFollowPath = new List(); private static bool _handlersRegistered; private static float _commandCooldownEnd; private static DroneMode _mode = DroneMode.NotSpawned; private static GameObject _droneVisual; private static Vector3 _droneGroundPosition; private static bool _droneIsInside; private static bool _isFollowingPlayer; private static bool _reportedNoEntranceScrap; private static int _ownerPlayerId = -1; private static int _routeVersion; private static int _droneHealth = 30; private static bool _droneDestroyedThisRound; private static int _ownerCourierTier; private static float _nextEnemyScanAt; private static int _lastEnemyScanFrame = -1; private static int _lastEnemyFacingFrame = -1; private static float _nextFlameAt; private static float _nextGrenadeAt; private static float _combatLandedUntil; private static int _nextGrenadeId = 1; private static float _nextEntranceScrapScanAt; private static float _nextGuardScrapScanAt; private static bool _flashlightEnabled; private static bool _followSettled; private static Vector3 _cachedFollowPathTarget; private static float _nextFollowRepathAt; private static bool _lastRouteMoveBlocked; private static float _nextCollisionRepathAt; private static Vector3 _followSmoothVelocity; private static float _nextHoverProbeAt; private static float _dynamicHoverHeight = 0.95f; private static Vector3 _stuckWindowStartGround; private static float _stuckWindowStartAt; private static bool _stuckRepathIssued; private static bool _stuckRescueActive; private static GameObject _manualPlayerRendererCacheRoot; private static Renderer[] _manualPlayerRendererCache; private static GameObject _droneRendererCacheRoot; private static Renderer[] _droneRendererCache; private static bool _manualControlActive; private static bool _manualControlCameraActivated; private static int _manualControlPlayerId = -1; private static DroneMode _manualPreviousMode = DroneMode.NotSpawned; private static GameObject _manualCameraObject; private static Camera _manualCamera; private static GameObject _manualHudRoot; private static Text _manualHudStatusText; private static Text _manualHudCargoText; private static Text _manualHudTelemetryText; private static Text _manualHudControlsText; private static GameObject _manualHudStartupRoot; private static Text _manualHudStartupText; private static Image _manualHudStartupProgressImage; private static bool _restoreMoveInput; private static bool _restoreLookInput; private static bool _restoreInteractInput; private static bool _restoreGameplayCameraEnabled; private static bool _manualSavedInputState; private static bool _manualSavedPresentationState; private static readonly List ManualRendererStates = new List(); private static bool _restoreBodyModelEnabled; private static bool _restoreBodyModelLod1Enabled; private static bool _restoreBodyModelLod2Enabled; private static bool _restoreBodyModelArmsEnabled; private static ShadowCastingMode _restoreBodyShadowMode; private static ShadowCastingMode _restoreBodyLod1ShadowMode; private static ShadowCastingMode _restoreBodyLod2ShadowMode; private static bool _restoreLocalArmsMatchCamera; private static bool _restoreAnimatorGrab; private static bool _restoreAnimatorGrabValidated; private static bool _manualSavedAnimatorFlags; private static float _manualDroneStartupUntil; private static float _manualYaw; private static float _manualPitch; private static float _manualNextPoseSyncAt; private static float _manualPickupLockedUntil; private static bool _magnetPickupActive; private static float _nextPointerCommandAt; private static float _nextDroneAttackWarningAt; private static ulong _priorityTargetId; private static float _priorityTargetExpiresAt; private static float _priorityTargetUnreachableSince; private static DroneMode _pointerPreviousMode = DroneMode.NotSpawned; private const int MANUAL_POSE_BYTES = 28; private const int MANUAL_PICKUP_BYTES = 40; internal static bool IsLocalPilotModeActive => _manualControlActive; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } internal static void OnRoundStarted() { _commandCooldownEnd = 0f; StopManualControl(resumeDrone: false, notifyOwner: false); ResetDroneHealthForRound(); ResetDroneState(destroyVisual: true); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { StopManualControl(resumeDrone: false, notifyOwner: false); ResetDroneState(destroyVisual: true); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { StopManualControl(resumeDrone: false, notifyOwner: false); _handlersRegistered = false; } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { UpdateEnemyDroneFacingOncePerFrame(); UpdateEnemyDroneAggroScanOncePerFrame(); if (IsLocalPlayer(__instance)) { UpdatePointerTargeting(__instance); if (_manualControlActive) { TickManualControl(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "Crouch", new Type[] { typeof(bool) })] [HarmonyPrefix] private static bool PrePlayerCrouch(PlayerControllerB __instance, bool crouch) { if (!_manualControlActive || !crouch || !IsLocalPlayer(__instance)) { return true; } return false; } [HarmonyPatch(typeof(EnemyAI), "DoAIInterval")] [HarmonyPostfix] private static void PostEnemyDoAIInterval(EnemyAI __instance) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) try { if (IsServerAuthority() && !((Object)(object)__instance == (Object)null) && !__instance.isEnemyDead && CanDroneBeDamaged() && EnemySharesDroneSpace(__instance) && IsDroneThreat(__instance)) { Vector3 droneTargetPosition = GetDroneTargetPosition(); if (!(droneTargetPosition == Vector3.zero) && !PlayerHasPriorityOverDrone(__instance, droneTargetPosition)) { __instance.movingTowardsTargetPlayer = false; __instance.targetPlayer = null; SteerEnemyTowardDrone(__instance); } } } catch (Exception ex) { string text = (((Object)(object)__instance != (Object)null) ? ((object)__instance).GetType().Name : ""); ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("Courier Drone enemy DoAIInterval postfix skipped for " + text + ": " + ex.Message)); } } } private static bool PlayerHasPriorityOverDrone(EnemyAI enemy, Vector3 dronePosition) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) PlayerControllerB val = (((Object)(object)enemy != (Object)null) ? enemy.targetPlayer : null); if ((Object)(object)val == (Object)null || val.isPlayerDead || (Object)(object)((Component)val).transform == (Object)null || (Object)(object)((Component)enemy).transform == (Object)null) { return false; } Vector3 val2 = ((Component)val).transform.position - ((Component)enemy).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; val2 = dronePosition - ((Component)enemy).transform.position; float sqrMagnitude2 = ((Vector3)(ref val2)).sqrMagnitude; return sqrMagnitude < sqrMagnitude2; } private static void UpdatePointerTargeting(PlayerControllerB player) { //IL_0009: 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_002b: 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_00a3: Unknown result type (might be due to invalid IL or missing references) if (!CanPointerCommandBeActive(player)) { FieldTabletScreenRuntime.SetDronePointerReticle(show: false, Color.clear); return; } PointerTarget pointerTarget = FindPointerTarget(player); if (!pointerTarget.IsValid) { FieldTabletScreenRuntime.SetDronePointerReticle(show: false, Color.clear); return; } string label = BuildPointerReticleLabel(pointerTarget.CommandType); FieldTabletScreenRuntime.SetDronePointerReticle(show: true, pointerTarget.ReticleColor, 0f, label); if (!(Time.time < _nextPointerCommandAt) && WasPointerCommandPressedThisFrame()) { _nextPointerCommandAt = Time.time + 1.5f; FieldTabletScreenRuntime.SetDronePointerReticle(show: true, pointerTarget.ReticleColor, 0.18f, label); SendPointerCommand((int)player.playerClientId, CourierDroneUpgrade.GetTier(), pointerTarget.CommandType, pointerTarget.TargetReference); } } private static string BuildPointerReticleLabel(CourierCommandType commandType) { string text = ((commandType == CourierCommandType.PointerAttack) ? "ATTACK" : "FETCH"); return "[" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CourierDroneCommand, "MMB") + "] " + text; } private static bool CanPointerCommandBeActive(PlayerControllerB player) { if (CourierDroneUpgrade.IsUnlocked() && (Object)(object)_droneVisual != (Object)null && !_droneDestroyedThisRound && _mode != DroneMode.NotSpawned && _mode != DroneMode.ManualControl && !_manualControlActive) { return CanUsePointer(player); } return false; } private static bool CanUsePointer(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu) { if (!((Object)(object)player.quickMenuManager == (Object)null)) { return !player.quickMenuManager.isMenuOpen; } return true; } return false; } private static PointerTarget FindPointerTarget(PlayerControllerB player) { //IL_003b: 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_004b: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val == (Object)null) { return default(PointerTarget); } RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), 45f, GetPointerRaycastMask(), (QueryTriggerInteraction)2); if (array == null || array.Length == 0) { return default(PointerTarget); } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num = 0; num < array.Length; num++) { Collider collider = ((RaycastHit)(ref array[num])).collider; if ((Object)(object)collider == (Object)null) { continue; } Transform transform = ((Component)collider).transform; if ((!((Object)(object)transform != (Object)null) || !((Object)(object)player != (Object)null) || !transform.IsChildOf(((Component)player).transform)) && (!((Object)(object)transform != (Object)null) || !((Object)(object)_droneVisual != (Object)null) || !transform.IsChildOf(_droneVisual.transform)) && (!((Object)(object)transform != (Object)null) || ((Object)transform).name.IndexOf("FieldTablet", StringComparison.OrdinalIgnoreCase) < 0)) { if (TryBuildPointerEnemyTarget(collider, out var target)) { return target; } if (TryBuildPointerItemTarget(collider, out target)) { return target; } if (!collider.isTrigger) { break; } } } return default(PointerTarget); } private static int GetPointerRaycastMask() { return (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-5)) | 0x40 | 0x200 | 0x80000 | 0x800000; } private static bool TryBuildPointerEnemyTarget(Collider collider, out PointerTarget target) { //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) //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) target = default(PointerTarget); EnemyAI val = ResolveEnemyFromCollider(collider); if ((Object)(object)val == (Object)null || val.isEnemyDead || !EnemySharesDroneSpace(val)) { return false; } NetworkObject val2 = (((Object)(object)((NetworkBehaviour)val).NetworkObject != (Object)null) ? ((NetworkBehaviour)val).NetworkObject : ((Component)val).GetComponentInParent()); if ((Object)(object)val2 == (Object)null) { return false; } target = new PointerTarget { CommandType = CourierCommandType.PointerAttack, TargetReference = new NetworkObjectReference(val2), ReticleColor = PointerEnemyColor }; return true; } private static bool TryBuildPointerItemTarget(Collider collider, out PointerTarget target) { //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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) target = default(PointerTarget); GrabbableObject componentInParent = ((Component)collider).GetComponentInParent(); if (!IsPointerFetchEligible(componentInParent)) { return false; } NetworkObject val = (((Object)(object)((NetworkBehaviour)componentInParent).NetworkObject != (Object)null) ? ((NetworkBehaviour)componentInParent).NetworkObject : ((Component)componentInParent).GetComponentInParent()); if ((Object)(object)val == (Object)null) { return false; } target = new PointerTarget { CommandType = CourierCommandType.PointerFetch, TargetReference = new NetworkObjectReference(val), ReticleColor = PointerItemColor }; return true; } private static EnemyAI ResolveEnemyFromCollider(Collider collider) { if ((Object)(object)collider == (Object)null) { return null; } EnemyAICollisionDetect componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && (Object)(object)componentInParent.mainScript != (Object)null) { return componentInParent.mainScript; } return ((Component)collider).GetComponentInParent(); } private static bool WasPointerCommandPressedThisFrame() { return UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CourierDroneCommand); } internal static bool TryGetTabletTelemetry(out Vector3 position, out float healthNormalized, out float cargoNormalized, out int cargoCount, out string status, out bool droneInside) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) bool result = (Object)(object)_droneVisual != (Object)null && !_droneDestroyedThisRound; position = (((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform.position : Vector3.zero); healthNormalized = (_droneDestroyedThisRound ? 0f : Mathf.Clamp01((float)_droneHealth / 30f)); cargoNormalized = Mathf.Clamp01(GetCarriedCargoWeightPounds() / 150f); cargoCount = CarriedItems.Count; status = GetDroneStatusText(); droneInside = _droneIsInside; return result; } internal static string GetTabletActiveModeName() { if (_droneDestroyedThisRound) { return "DESTROYED"; } return ((!((Object)(object)_droneVisual == (Object)null)) ? _mode : DroneMode.NotSpawned) switch { DroneMode.NotSpawned => "OFFLINE", DroneMode.IdleAtPlayer => "IDLE", DroneMode.GuardingPlayer => "GUARDING PLAYER", DroneMode.FlyingToEntrance => "ENTRANCE SWEEP", DroneMode.AtEntrance => "AT ENTRANCE", DroneMode.ReturningToShip => "RETURNING TO SHIP", DroneMode.FlyingToPlayer => "DISMISSING", DroneMode.ManualControl => "PILOT LINK", DroneMode.PointerAttack => "POINTER ATTACK", DroneMode.PointerFetch => "POINTER FETCH", _ => "READY", }; } private static string FormatCargoWeight(float pounds) { return $"{Mathf.RoundToInt(pounds)}/{Mathf.RoundToInt(150f)} lb"; } private static float GetItemWeightPounds(GrabbableObject item) { if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null) { return 0f; } return Mathf.Max(0f, item.itemProperties.weight - 1f) * 105f; } private static float GetCarriedCargoWeightPounds() { float num = 0f; for (int i = 0; i < CarriedItems.Count; i++) { num += GetItemWeightPounds(CarriedItems[i].Item); } return num; } private static float GetPlannedCargoWeightPounds() { float num = 0f; for (int i = 0; i < PlannedItems.Count; i++) { num += GetItemWeightPounds(ResolveItem(PlannedItems[i].NetworkObjectId)); } return num; } private static float GetReservedCargoWeightPounds() { return GetCarriedCargoWeightPounds() + GetPlannedCargoWeightPounds(); } private static bool WouldExceedCargoWeight(GrabbableObject item, float existingWeightLb) { return existingWeightLb + GetItemWeightPounds(item) > 150.01f; } private static bool IsCargoWeightFull() { return GetCarriedCargoWeightPounds() >= 149.99f; } private static string GetDroneStatusText() { if (_droneDestroyedThisRound) { return "DESTROYED"; } switch ((!((Object)(object)_droneVisual == (Object)null)) ? _mode : DroneMode.NotSpawned) { case DroneMode.NotSpawned: return "OFFLINE"; case DroneMode.IdleAtPlayer: if (CarriedItems.Count > 0) { return "HOLDING"; } if (!_isFollowingPlayer) { return "WAITING"; } return "FOLLOWING"; case DroneMode.GuardingPlayer: return "GUARDING"; case DroneMode.FlyingToEntrance: return "OUTBOUND"; case DroneMode.AtEntrance: if (CarriedItems.Count <= 0) { return "SCANNING"; } return "CARGO READY"; case DroneMode.ReturningToShip: return "RETURNING TO SHIP"; case DroneMode.FlyingToPlayer: return "RETURNING"; case DroneMode.ManualControl: if (!_manualControlCameraActivated) { return "LINKING"; } return "MANUAL"; case DroneMode.PointerAttack: return "ENGAGING"; case DroneMode.PointerFetch: return "FETCHING"; default: return "READY"; } } private static string GetNextDroneActionText() { if (_droneDestroyedThisRound) { return "NEXT ROUND"; } switch ((!((Object)(object)_droneVisual == (Object)null)) ? _mode : DroneMode.NotSpawned) { case DroneMode.NotSpawned: return "DEPLOY"; case DroneMode.IdleAtPlayer: case DroneMode.GuardingPlayer: return "SEND TO ENTRANCE"; case DroneMode.AtEntrance: return "RETURN TO SHIP"; case DroneMode.FlyingToEntrance: case DroneMode.ReturningToShip: case DroneMode.FlyingToPlayer: case DroneMode.ManualControl: case DroneMode.PointerAttack: case DroneMode.PointerFetch: return "BUSY"; default: return "READY"; } } private static bool IsBusyMode(DroneMode mode) { if (mode != DroneMode.FlyingToEntrance && mode != DroneMode.ReturningToShip && mode != DroneMode.FlyingToPlayer && mode != DroneMode.ManualControl && mode != DroneMode.PointerAttack) { return mode == DroneMode.PointerFetch; } return true; } internal static bool TryCommandFromFieldTablet(PlayerControllerB player) { return TryExecuteTabletCommand(player, ResolveContextualSummonDismissType()); } internal static void StopLocalPilotMode(bool notifyOwner) { StopManualControl(resumeDrone: true, notifyOwner); } internal static int GetTabletCommandEntries(PlayerControllerB player, TabletCommandEntry[] entries) { if (entries == null || entries.Length == 0) { return 0; } int count = 0; AddTabletCommandEntry(player, entries, ref count, ResolveContextualSummonDismissType()); AddTabletCommandEntry(player, entries, ref count, CourierCommandType.Guard); AddTabletCommandEntry(player, entries, ref count, CourierCommandType.FlyToEntrance); AddTabletCommandEntry(player, entries, ref count, CourierCommandType.ReturnToShip); AddTabletCommandEntry(player, entries, ref count, CourierCommandType.Flashlight); if (CourierDroneUpgrade.GetTier() >= 3) { AddTabletCommandEntry(player, entries, ref count, CourierCommandType.Pilot); } return count; } internal static bool TryExecuteTabletCommand(PlayerControllerB player, CourierCommandType commandType) { if (!IsTabletCommandAvailable(commandType, player, out var reason)) { if ((Object)(object)player != (Object)null) { DisplayOwnerTip((int)player.playerClientId, reason, isWarning: true); } return false; } if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient) { CourierCommand courierCommand = BuildCommand(player, commandType); ApplyCommand(courierCommand); if (courierCommand != null) { return courierCommand.Type != CourierCommandType.None; } return false; } if (NetworkManager.Singleton.IsServer) { CourierCommand courierCommand2 = BuildCommand(player, commandType); ApplyCommand(courierCommand2); BroadcastCommand(courierCommand2); if (courierCommand2 != null) { return courierCommand2.Type != CourierCommandType.None; } return false; } SendRequest((int)player.playerClientId, commandType); return true; } private static void AddTabletCommandEntry(PlayerControllerB player, TabletCommandEntry[] entries, ref int count, CourierCommandType commandType) { if (count < entries.Length) { string reason; bool flag = IsTabletCommandAvailable(commandType, player, out reason); entries[count++] = new TabletCommandEntry(commandType, GetTabletCommandLabel(commandType), flag, flag ? string.Empty : reason); } } private static CourierCommandType ResolveContextualSummonDismissType() { if (!((Object)(object)_droneVisual == (Object)null) && _mode != DroneMode.NotSpawned) { return CourierCommandType.Dismiss; } return CourierCommandType.Spawn; } private static string GetTabletCommandLabel(CourierCommandType commandType) { switch (commandType) { case CourierCommandType.Spawn: return "SUMMON"; case CourierCommandType.Dismiss: return "DISMISS"; case CourierCommandType.Guard: return "GUARD ME"; case CourierCommandType.FlyToEntrance: return "ENTRANCE SWEEP"; case CourierCommandType.ReturnToShip: return "RETURN TO SHIP"; case CourierCommandType.Flashlight: if (!_flashlightEnabled) { return "FLASHLIGHT ON"; } return "FLASHLIGHT OFF"; case CourierCommandType.Pilot: return "PILOT"; default: return "COMMAND"; } } private static bool IsTabletCommandAvailable(CourierCommandType commandType, PlayerControllerB player, out string reason) { reason = string.Empty; switch (commandType) { case CourierCommandType.None: reason = "NO COMMAND"; return false; case CourierCommandType.Pilot: if (CourierDroneUpgrade.GetTier() < 3) { reason = "PILOT LOCKED"; return false; } break; } if (!CourierDroneUpgrade.IsUnlocked()) { reason = "DRONE LOCKED"; return false; } if ((Object)(object)player == (Object)null || !CanUse(player)) { reason = "PLAYER BUSY"; return false; } if (_droneDestroyedThisRound) { reason = "NEXT ROUND"; return false; } if (Time.time < _commandCooldownEnd) { reason = $"LOCK {Mathf.CeilToInt(_commandCooldownEnd - Time.time)}S"; return false; } DroneMode droneMode = ((!((Object)(object)_droneVisual == (Object)null)) ? _mode : DroneMode.NotSpawned); bool flag = (Object)(object)_droneVisual != (Object)null && droneMode != DroneMode.NotSpawned; switch (commandType) { case CourierCommandType.Spawn: if (flag) { reason = "DEPLOYED"; return false; } return true; case CourierCommandType.Dismiss: if (!flag) { reason = "NO DRONE"; return false; } return true; case CourierCommandType.Guard: if (!flag) { reason = "NO DRONE"; return false; } if (droneMode == DroneMode.GuardingPlayer) { reason = "ACTIVE"; return false; } if (IsBusyMode(droneMode)) { reason = "BUSY"; return false; } return true; case CourierCommandType.FlyToEntrance: if (!flag) { reason = "NO DRONE"; return false; } if (droneMode == DroneMode.AtEntrance) { reason = "AT ENTRANCE"; return false; } if (IsBusyMode(droneMode)) { reason = "BUSY"; return false; } return true; case CourierCommandType.ReturnToShip: if (!flag) { reason = "NO DRONE"; return false; } if (IsBusyMode(droneMode)) { reason = "BUSY"; return false; } return true; case CourierCommandType.Flashlight: if (!flag) { reason = "NO DRONE"; return false; } return true; case CourierCommandType.Pilot: if (!flag) { reason = "NO DRONE"; return false; } if (droneMode == DroneMode.ManualControl) { reason = "ACTIVE"; return false; } if (IsBusyMode(droneMode)) { reason = "BUSY"; return false; } if (_magnetPickupActive || Time.time < _manualPickupLockedUntil) { reason = "MAGNET BUSY"; return false; } return true; default: reason = "UNAVAILABLE"; return false; } } private static void TryStartManualControl(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { if ((Object)(object)_droneVisual == (Object)null || _droneDestroyedThisRound || _mode != DroneMode.ManualControl) { DisplayOwnerTip((int)player.playerClientId, "Drone link unavailable.", isWarning: true); } else if (!_manualControlActive) { _manualControlActive = true; _manualControlCameraActivated = false; _manualControlPlayerId = (int)player.playerClientId; _manualDroneStartupUntil = 0f; _manualNextPoseSyncAt = 0f; InitializeManualAngles(player); SaveAndLockPlayerInput(player); SuppressManualPlayerPhysicalControls(player); FieldOperationsTabletPatch.TrySetPilotActionReadyHold(hold: true); CreateManualCamera(player); ActivateManualCamera(player); DisplayOwnerTip((int)player.playerClientId, "Remote drone link active.", isWarning: false); } } } private static void TickManualControl(PlayerControllerB player) { if (UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.DronePilotExit)) { StopManualControl(resumeDrone: true, notifyOwner: false); return; } if (!CanContinueManualControl(player)) { StopManualControl(resumeDrone: true, notifyOwner: false); return; } SaveAndLockPlayerInput(player); SuppressManualPlayerPhysicalControls(player); FieldOperationsTabletPatch.TrySetPilotActionReadyHold(hold: true); if (!_manualControlCameraActivated) { ActivateManualCamera(player); } ApplyManualPlayerPresentation(player); SuppressManualPlayerPhysicalControls(player); UpdateManualLook(); UpdateManualDroneMovement(player); UpdateManualCameraTransform(); UpdateManualHud(); HandleManualDroneActions(player); if (Time.time >= _manualNextPoseSyncAt) { _manualNextPoseSyncAt = Time.time + 0.08f; BroadcastManualPose(active: true); } } private static bool CanContinueManualControl(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu && (!player.inSpecialInteractAnimation || FieldOperationsTabletPatch.IsTabletActive) && ((Object)(object)player.quickMenuManager == (Object)null || !player.quickMenuManager.isMenuOpen) && !_droneDestroyedThisRound && (Object)(object)_droneVisual != (Object)null) { return _mode == DroneMode.ManualControl; } return false; } private static void InitializeManualAngles(PlayerControllerB player) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform : ((player != null) ? ((Component)player).transform : null)); Vector3 val2 = (((Object)(object)val != (Object)null) ? val.forward : Vector3.forward); Vector3 forward = default(Vector3); ((Vector3)(ref forward))..ctor(val2.x, 0f, val2.z); if (((Vector3)(ref forward)).sqrMagnitude <= 0.001f && (Object)(object)player != (Object)null) { ((Vector3)(ref forward))..ctor(((Component)player).transform.forward.x, 0f, ((Component)player).transform.forward.z); } if (((Vector3)(ref forward)).sqrMagnitude <= 0.001f) { forward = Vector3.forward; } Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref forward)).normalized, Vector3.up); _manualYaw = ((Quaternion)(ref val3)).eulerAngles.y; _manualPitch = 0f; } private static void SaveAndLockPlayerInput(PlayerControllerB player) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { if (!_manualSavedInputState) { _restoreMoveInput = player.disableMoveInput; _restoreLookInput = player.disableLookInput; _restoreInteractInput = player.disableInteract; _restoreGameplayCameraEnabled = (Object)(object)player.gameplayCamera == (Object)null || ((Behaviour)player.gameplayCamera).enabled; _manualSavedInputState = true; } player.disableMoveInput = true; player.disableLookInput = true; player.disableInteract = true; player.externalForceAutoFade = Vector3.zero; } } private static void CreateManualCamera(PlayerControllerB player) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_00ac: 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) if ((Object)(object)_manualCameraObject != (Object)null) { Object.Destroy((Object)(object)_manualCameraObject); } Camera val = (((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); _manualCameraObject = new GameObject("Y4NGZ_CourierDroneManualCamera"); _manualCamera = _manualCameraObject.AddComponent(); if ((Object)(object)val != (Object)null) { _manualCamera.fieldOfView = val.fieldOfView; _manualCamera.nearClipPlane = val.nearClipPlane; _manualCamera.farClipPlane = val.farClipPlane; _manualCamera.cullingMask = val.cullingMask; _manualCamera.clearFlags = val.clearFlags; _manualCamera.backgroundColor = val.backgroundColor; _manualCamera.allowHDR = val.allowHDR; _manualCamera.allowMSAA = val.allowMSAA; _manualCamera.depth = val.depth + 1f; } else { _manualCamera.fieldOfView = 66f; _manualCamera.nearClipPlane = 0.03f; _manualCamera.farClipPlane = 1000f; } ((Behaviour)_manualCamera).enabled = false; _manualCamera.targetTexture = null; UpdateManualCameraTransform(); } private static void ActivateManualCamera(PlayerControllerB player) { if ((Object)(object)_manualCamera == (Object)null) { CreateManualCamera(player); } ApplyManualPlayerPresentation(player); _manualDroneStartupUntil = Time.unscaledTime + 1f; CreateManualHud(); UpdateManualCameraTransform(); if ((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) { ((Behaviour)player.gameplayCamera).enabled = false; } if ((Object)(object)_manualCamera != (Object)null) { _manualCamera.targetTexture = null; ((Behaviour)_manualCamera).enabled = true; } _manualControlCameraActivated = true; BroadcastManualPose(active: true); } private static void SuppressManualPlayerPhysicalControls(PlayerControllerB player) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } player.disableMoveInput = true; player.disableLookInput = true; player.disableInteract = true; player.externalForceAutoFade = Vector3.zero; try { if (player.isCrouching) { player.Crouch(false); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("Courier Drone manual crouch suppression skipped: " + ex.Message)); } } if ((Object)(object)player.playerBodyAnimator != (Object)null) { player.playerBodyAnimator.SetBool("crouching", false); player.playerBodyAnimator.SetBool("Walking", false); player.playerBodyAnimator.SetBool("Sprinting", false); player.playerBodyAnimator.SetBool("Sideways", false); } } private static void ApplyManualPlayerPresentation(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { FieldOperationsTabletPatch.ReleaseLocalThirdPersonPresentationForDrone(); SaveManualPlayerPresentation(player); SetOriginalPlayerRenderersForDroneView(player); player.localArmsMatchCamera = false; if ((Object)(object)player.playerBodyAnimator != (Object)null) { player.playerBodyAnimator.SetBool("Walking", false); player.playerBodyAnimator.SetBool("Sprinting", false); player.playerBodyAnimator.SetBool("Sideways", false); player.playerBodyAnimator.SetBool("Grab", true); player.playerBodyAnimator.SetBool("GrabValidated", true); } } } private static void SaveManualPlayerPresentation(PlayerControllerB player) { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) if (_manualSavedPresentationState || (Object)(object)player == (Object)null) { return; } _manualSavedPresentationState = true; _restoreBodyModelEnabled = (Object)(object)player.thisPlayerModel != (Object)null && ((Renderer)player.thisPlayerModel).enabled; _restoreBodyModelLod1Enabled = (Object)(object)player.thisPlayerModelLOD1 != (Object)null && ((Renderer)player.thisPlayerModelLOD1).enabled; _restoreBodyModelLod2Enabled = (Object)(object)player.thisPlayerModelLOD2 != (Object)null && ((Renderer)player.thisPlayerModelLOD2).enabled; _restoreBodyModelArmsEnabled = (Object)(object)player.thisPlayerModelArms != (Object)null && ((Renderer)player.thisPlayerModelArms).enabled; _restoreBodyShadowMode = (ShadowCastingMode)((!((Object)(object)player.thisPlayerModel != (Object)null)) ? 3 : ((int)((Renderer)player.thisPlayerModel).shadowCastingMode)); _restoreBodyLod1ShadowMode = (ShadowCastingMode)(((Object)(object)player.thisPlayerModelLOD1 != (Object)null) ? ((int)((Renderer)player.thisPlayerModelLOD1).shadowCastingMode) : 0); _restoreBodyLod2ShadowMode = (ShadowCastingMode)(((Object)(object)player.thisPlayerModelLOD2 != (Object)null) ? ((int)((Renderer)player.thisPlayerModelLOD2).shadowCastingMode) : 0); _restoreLocalArmsMatchCamera = player.localArmsMatchCamera; ManualRendererStates.Clear(); Renderer[] cachedRenderers = GetCachedRenderers(((Component)player).gameObject, ref _manualPlayerRendererCacheRoot, ref _manualPlayerRendererCache); foreach (Renderer val in cachedRenderers) { if (!((Object)(object)val == (Object)null)) { ManualRendererStates.Add(new RendererPresentationState(val, val.enabled, val.shadowCastingMode, ((Component)val).gameObject.layer)); } } if ((Object)(object)player.playerBodyAnimator != (Object)null) { _restoreAnimatorGrab = player.playerBodyAnimator.GetBool("Grab"); _restoreAnimatorGrabValidated = player.playerBodyAnimator.GetBool("GrabValidated"); _manualSavedAnimatorFlags = true; } } private static void RestoreManualPlayerPresentation() { //IL_00d2: 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_00fc: 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) PlayerControllerB val = ResolvePlayer(_manualControlPlayerId) ?? GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || !_manualSavedPresentationState) { ManualRendererStates.Clear(); _manualSavedPresentationState = false; return; } for (int i = 0; i < ManualRendererStates.Count; i++) { RendererPresentationState rendererPresentationState = ManualRendererStates[i]; if (!((Object)(object)rendererPresentationState.Renderer == (Object)null)) { rendererPresentationState.Renderer.enabled = rendererPresentationState.Enabled; rendererPresentationState.Renderer.shadowCastingMode = rendererPresentationState.ShadowCastingMode; ((Component)rendererPresentationState.Renderer).gameObject.layer = rendererPresentationState.Layer; } } ManualRendererStates.Clear(); SetSkinnedRenderer(val.thisPlayerModel, _restoreBodyModelEnabled, _restoreBodyShadowMode); SetSkinnedRenderer(val.thisPlayerModelLOD1, _restoreBodyModelLod1Enabled, _restoreBodyLod1ShadowMode); SetSkinnedRenderer(val.thisPlayerModelLOD2, _restoreBodyModelLod2Enabled, _restoreBodyLod2ShadowMode); SetSkinnedRenderer(val.thisPlayerModelArms, _restoreBodyModelArmsEnabled, (ShadowCastingMode)0); val.localArmsMatchCamera = _restoreLocalArmsMatchCamera; if ((Object)(object)val.playerBodyAnimator != (Object)null) { if (_manualSavedAnimatorFlags) { val.playerBodyAnimator.SetBool("Grab", _restoreAnimatorGrab); val.playerBodyAnimator.SetBool("GrabValidated", _restoreAnimatorGrabValidated); } val.playerBodyAnimator.SetBool("cancelHolding", false); } _manualSavedPresentationState = false; _manualSavedAnimatorFlags = false; } private static void SetSkinnedRenderer(SkinnedMeshRenderer renderer, bool enabled, ShadowCastingMode shadowMode) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)renderer == (Object)null)) { ((Renderer)renderer).enabled = enabled; ((Renderer)renderer).shadowCastingMode = shadowMode; } } private static void SetOriginalPlayerRenderersForDroneView(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } int num = LayerMask.NameToLayer("Default"); if (num < 0) { num = 0; } for (int i = 0; i < ManualRendererStates.Count; i++) { Renderer renderer = ManualRendererStates[i].Renderer; if (!((Object)(object)renderer == (Object)null)) { bool flag = IsFirstPersonArmsRenderer(player, renderer); bool flag2 = (Object)(object)player.thisPlayerModel != (Object)null && (Object)(object)renderer == (Object)(object)player.thisPlayerModel; bool flag3 = ((Object)(object)player.thisPlayerModelLOD1 != (Object)null && (Object)(object)renderer == (Object)(object)player.thisPlayerModelLOD1) || ((Object)(object)player.thisPlayerModelLOD2 != (Object)null && (Object)(object)renderer == (Object)(object)player.thisPlayerModelLOD2); if (IsDroneTabletRenderer(renderer)) { renderer.enabled = true; renderer.shadowCastingMode = (ShadowCastingMode)1; ((Component)renderer).gameObject.layer = num; } else if (flag) { renderer.enabled = false; renderer.shadowCastingMode = (ShadowCastingMode)0; } else if (flag2) { renderer.enabled = true; renderer.shadowCastingMode = (ShadowCastingMode)1; ((Component)renderer).gameObject.layer = num; } else if (flag3) { renderer.enabled = false; renderer.shadowCastingMode = (ShadowCastingMode)0; } else { renderer.enabled = false; renderer.shadowCastingMode = (ShadowCastingMode)0; } } } SetSkinnedRenderer(player.thisPlayerModel, enabled: true, (ShadowCastingMode)1); SetSkinnedRenderer(player.thisPlayerModelLOD1, enabled: false, (ShadowCastingMode)0); SetSkinnedRenderer(player.thisPlayerModelLOD2, enabled: false, (ShadowCastingMode)0); SetSkinnedRenderer(player.thisPlayerModelArms, enabled: false, (ShadowCastingMode)0); SetFirstPersonArmsRenderersVisible(player, visible: false); } private static bool IsFirstPersonArmsRenderer(PlayerControllerB player, Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } if ((Object)(object)player != (Object)null && (Object)(object)player.thisPlayerModelArms != (Object)null && (Object)(object)renderer == (Object)(object)player.thisPlayerModelArms) { return true; } Transform val = ((Component)renderer).transform; Transform val2 = (((Object)(object)player != (Object)null) ? ((Component)player).transform : null); while ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)val2) { string name = ((Object)val).name; if (!string.IsNullOrEmpty(name) && (name.IndexOf("ScavengerModelArmsOnly", StringComparison.OrdinalIgnoreCase) >= 0 || name.IndexOf("ArmsOnly", StringComparison.OrdinalIgnoreCase) >= 0)) { return true; } val = val.parent; } return false; } private static void SetFirstPersonArmsRenderersVisible(PlayerControllerB player, bool visible) { if ((Object)(object)player == (Object)null) { return; } for (int i = 0; i < ManualRendererStates.Count; i++) { Renderer renderer = ManualRendererStates[i].Renderer; if (IsFirstPersonArmsRenderer(player, renderer)) { renderer.enabled = visible; renderer.shadowCastingMode = (ShadowCastingMode)0; } } } private static bool IsDroneTabletRenderer(Renderer renderer) { if ((Object)(object)renderer == (Object)null) { return false; } Transform val = ((Component)renderer).transform; while ((Object)(object)val != (Object)null) { string text = ((Object)val).name ?? string.Empty; if (text.IndexOf("Y4NGZ_DroneTablet", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Y4NGZ_FPSTabletProp", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Tablet_01", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } val = val.parent; } return false; } private static Renderer[] GetCachedDroneRenderers() { return GetCachedRenderers(_droneVisual, ref _droneRendererCacheRoot, ref _droneRendererCache); } private static Renderer[] GetCachedRenderers(GameObject root, ref GameObject cacheRoot, ref Renderer[] cache) { if ((Object)(object)root == (Object)null) { return Array.Empty(); } if ((Object)(object)cacheRoot != (Object)(object)root || cache == null) { cacheRoot = root; cache = root.GetComponentsInChildren(true); } return cache; } private static void ClearDroneRendererCache() { _droneRendererCacheRoot = null; _droneRendererCache = null; } private static void UpdateManualLook() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0027: Unknown result type (might be due to invalid IL or missing references) Vector2 val = UpgradeInput.ReadVanillaVector2("Look"); _manualYaw += val.x * 0.075f; _manualPitch = Mathf.Clamp(_manualPitch - val.y * 0.075f, -38f, 42f); } private static void UpdateManualDroneMovement(PlayerControllerB player) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_droneVisual == (Object)null) && !(Time.time < _manualPickupLockedUntil)) { Vector2 val = UpgradeInput.ReadVanillaVector2("Move"); float x = val.x; float y = val.y; float num = 0f; if (UpgradeInput.IsPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.DronePilotAscend)) { num += 1f; } if (UpgradeInput.IsPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.DronePilotDescend)) { num -= 1f; } Vector3 val2 = Quaternion.Euler(0f, _manualYaw, 0f) * new Vector3(x, 0f, y); if (((Vector3)(ref val2)).sqrMagnitude > 1f) { ((Vector3)(ref val2)).Normalize(); } Vector3 position = _droneVisual.transform.position; Vector3 requested = position + val2 * (6.2f * Time.deltaTime) + Vector3.up * (num * 3.8f * Time.deltaTime); requested = ClampManualDronePosition(position, requested, player); _droneVisual.transform.position = requested; _droneGroundPosition = ResolveManualGroundPosition(requested); if ((Object)(object)player != (Object)null) { _droneIsInside = player.isInsideFactory; } Quaternion val3 = Quaternion.Euler(0f, _manualYaw, 0f); _droneVisual.transform.rotation = Quaternion.Slerp(_droneVisual.transform.rotation, val3, Mathf.Clamp01(Time.deltaTime * 7.5f)); UpdateCarriedItemTransforms(); } } private static Vector3 ClampManualDronePosition(Vector3 current, Vector3 requested, PlayerControllerB player) { //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_001d: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0035: 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_0054: 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_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_007d: 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_00cd: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_0205: Unknown result type (might be due to invalid IL or missing references) //IL_016a: 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_0173: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: 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) Vector3 val = requested; int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); Vector3 val2 = val - current; float magnitude = ((Vector3)(ref val2)).magnitude; RaycastHit val3 = default(RaycastHit); if (magnitude > 0.001f && Physics.SphereCast(current, 0.34f, ((Vector3)(ref val2)).normalized, ref val3, magnitude + 0.05f, num, (QueryTriggerInteraction)1)) { val = current + ((Vector3)(ref val2)).normalized * Mathf.Max(0f, ((RaycastHit)(ref val3)).distance - 0.08f); } float num2 = ((_droneGroundPosition != Vector3.zero) ? _droneGroundPosition.y : (((Object)(object)player != (Object)null && (Object)(object)((Component)player).transform != (Object)null) ? ((Component)player).transform.position.y : val.y)); RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val + Vector3.up * 2.25f, Vector3.down, ref val4, 9f, num, (QueryTriggerInteraction)1)) { num2 = ((RaycastHit)(ref val4)).point.y; } val.y = Mathf.Clamp(val.y, num2 + 0.88f, num2 + 5.25f); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)player != (Object)null && IsPlayerInShip(player) && (Object)(object)instance != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; val.x = ClampInsideBounds(val.x, ((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, 0.75f); val.z = ClampInsideBounds(val.z, ((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, 0.75f); val.y = Mathf.Clamp(val.y, ((Bounds)(ref bounds)).min.y + 0.88f, ((Bounds)(ref bounds)).max.y - 0.35f); } return val; } private static Vector3 ResolveManualGroundPosition(Vector3 dronePosition) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); RaycastHit val = default(RaycastHit); if (Physics.Raycast(dronePosition + Vector3.up * 0.8f, Vector3.down, ref val, 8f, num, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val)).point + Vector3.up * 0.05f; } if (!(_droneGroundPosition != Vector3.zero)) { return Vector3.zero; } return _droneGroundPosition; } private static void UpdateManualCameraTransform() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_manualCamera == (Object)null) && !((Object)(object)_droneVisual == (Object)null)) { Quaternion rotation = Quaternion.Euler(_manualPitch, _manualYaw, 0f); Vector3 yawForwardInput = Quaternion.Euler(0f, _manualYaw, 0f) * Vector3.forward; Vector3 position = CalculateManualCameraPosition(_droneVisual.transform.position, yawForwardInput); _manualCamera.nearClipPlane = 0.045f; ((Component)_manualCamera).transform.position = position; ((Component)_manualCamera).transform.rotation = rotation; } } private static Vector3 CalculateManualCameraPosition(Vector3 dronePosition, Vector3 yawForwardInput) { //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_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0228: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: 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) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0095: 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_00a3: 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_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: 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) //IL_00df: 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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0106: 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_010f: 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) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0141: 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_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019c: 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_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = yawForwardInput; if (((Vector3)(ref val)).sqrMagnitude <= 0.001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); float num = 0.62f; Renderer[] cachedDroneRenderers = GetCachedDroneRenderers(); if (cachedDroneRenderers != null && cachedDroneRenderers.Length != 0) { float num2 = 0f; foreach (Renderer val2 in cachedDroneRenderers) { if (!((Object)(object)val2 == (Object)null) && val2.enabled) { Bounds bounds = val2.bounds; Vector3 extents = ((Bounds)(ref bounds)).extents; Vector3 val3 = ((Bounds)(ref bounds)).center - dronePosition; Vector3[] array = (Vector3[])(object)new Vector3[8] { val3 + new Vector3(extents.x, extents.y, extents.z), val3 + new Vector3(extents.x, extents.y, 0f - extents.z), val3 + new Vector3(extents.x, 0f - extents.y, extents.z), val3 + new Vector3(extents.x, 0f - extents.y, 0f - extents.z), val3 + new Vector3(0f - extents.x, extents.y, extents.z), val3 + new Vector3(0f - extents.x, extents.y, 0f - extents.z), val3 + new Vector3(0f - extents.x, 0f - extents.y, extents.z), val3 + new Vector3(0f - extents.x, 0f - extents.y, 0f - extents.z) }; for (int j = 0; j < array.Length; j++) { num2 = Mathf.Max(num2, Vector3.Dot(array[j], val)); } } } num = Mathf.Clamp(num2 + 0.28f, 0.68f, 1.75f); } return dronePosition + val * num + Vector3.up * 0.11f; } private static void CreateManualHud() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009e: 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_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_020b: 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_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_027f: Unknown result type (might be due to invalid IL or missing references) //IL_02a3: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_030d: Unknown result type (might be due to invalid IL or missing references) //IL_031c: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0368: Unknown result type (might be due to invalid IL or missing references) //IL_0377: Unknown result type (might be due to invalid IL or missing references) //IL_0390: Unknown result type (might be due to invalid IL or missing references) //IL_03b4: Unknown result type (might be due to invalid IL or missing references) //IL_03c3: Unknown result type (might be due to invalid IL or missing references) //IL_03d2: Unknown result type (might be due to invalid IL or missing references) //IL_03eb: Unknown result type (might be due to invalid IL or missing references) //IL_040f: Unknown result type (might be due to invalid IL or missing references) //IL_041e: Unknown result type (might be due to invalid IL or missing references) //IL_042d: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) DestroyManualHud(); _manualHudRoot = new GameObject("Y4NGZ_CourierDroneManualHUD"); Canvas obj = _manualHudRoot.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 32000; CanvasScaler obj2 = _manualHudRoot.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; _manualHudRoot.AddComponent(); Font builtinResource = Resources.GetBuiltinResource("Arial.ttf"); _manualHudStatusText = CreateManualHudText("Status", _manualHudRoot.transform, builtinResource, new Vector2(24f, -24f), new Vector2(0f, 1f), (TextAnchor)0, 24, new Color(0.73f, 1f, 0.96f, 0.96f)); _manualHudCargoText = CreateManualHudText("Cargo", _manualHudRoot.transform, builtinResource, new Vector2(-24f, -24f), new Vector2(1f, 1f), (TextAnchor)2, 22, new Color(0.92f, 0.98f, 1f, 0.94f)); _manualHudTelemetryText = CreateManualHudText("Telemetry", _manualHudRoot.transform, builtinResource, new Vector2(24f, 24f), new Vector2(0f, 0f), (TextAnchor)6, 20, new Color(0.72f, 0.95f, 1f, 0.88f)); _manualHudControlsText = CreateManualHudText("Controls", _manualHudRoot.transform, builtinResource, new Vector2(0f, 30f), new Vector2(0.5f, 0f), (TextAnchor)7, 19, new Color(0.92f, 0.98f, 1f, 0.78f)); _manualHudControlsText.text = BuildManualControlLegend(); CreateManualHudImage("ReticleH", _manualHudRoot.transform, new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(74f, 2f), new Color(0.2f, 1f, 0.92f, 0.72f)); CreateManualHudImage("ReticleV", _manualHudRoot.transform, new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(2f, 74f), new Color(0.2f, 1f, 0.92f, 0.72f)); CreateManualHudImage("ReticleCore", _manualHudRoot.transform, new Vector2(0f, 0f), new Vector2(0.5f, 0.5f), new Vector2(8f, 8f), new Color(1f, 1f, 1f, 0.88f)); CreateManualHudImage("TopBand", _manualHudRoot.transform, new Vector2(0f, 0f), new Vector2(0.5f, 1f), new Vector2(1920f, 4f), new Color(0.13f, 0.95f, 0.85f, 0.55f)); CreateManualHudImage("BottomBand", _manualHudRoot.transform, new Vector2(0f, 0f), new Vector2(0.5f, 0f), new Vector2(1920f, 4f), new Color(0.13f, 0.95f, 0.85f, 0.55f)); CreateManualHudImage("LeftTick", _manualHudRoot.transform, new Vector2(42f, 0f), new Vector2(0f, 0.5f), new Vector2(3f, 220f), new Color(0.13f, 0.95f, 0.85f, 0.35f)); CreateManualHudImage("RightTick", _manualHudRoot.transform, new Vector2(-42f, 0f), new Vector2(1f, 0.5f), new Vector2(3f, 220f), new Color(0.13f, 0.95f, 0.85f, 0.35f)); CreateManualStartupOverlay(builtinResource); UpdateManualHud(); } private static Text CreateManualHudText(string name, Transform parent, Font font, Vector2 anchoredPosition, Vector2 anchor, TextAnchor alignment, int size, Color color) { //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_0032: 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_005d: 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_006d: 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_0085: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DroneHUD_" + name); val.transform.SetParent(parent, false); Text obj = val.AddComponent(); obj.font = font; obj.fontSize = size; obj.alignment = alignment; ((Graphic)obj).color = color; obj.horizontalOverflow = (HorizontalWrapMode)1; obj.verticalOverflow = (VerticalWrapMode)1; ((Graphic)obj).raycastTarget = false; RectTransform component = ((Component)obj).GetComponent(); component.anchorMin = anchor; component.anchorMax = anchor; component.pivot = anchor; component.anchoredPosition = anchoredPosition; component.sizeDelta = new Vector2(680f, 128f); return obj; } private static Image CreateManualHudImage(string name, Transform parent, Vector2 anchoredPosition, Vector2 anchor, Vector2 size, Color color) { //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_0023: 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_003f: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DroneHUD_" + name); val.transform.SetParent(parent, false); Image obj = val.AddComponent(); ((Graphic)obj).color = color; ((Graphic)obj).raycastTarget = false; RectTransform component = ((Component)obj).GetComponent(); component.anchorMin = anchor; component.anchorMax = anchor; component.pivot = new Vector2(0.5f, 0.5f); component.anchoredPosition = anchoredPosition; component.sizeDelta = size; return obj; } private static void CreateManualStartupOverlay(Font font) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_008b: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0188: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d4: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: 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_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_manualHudRoot == (Object)null)) { _manualHudStartupRoot = new GameObject("DroneHUD_StartupOverlay"); _manualHudStartupRoot.transform.SetParent(_manualHudRoot.transform, false); RectTransform obj = _manualHudStartupRoot.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; Image obj2 = _manualHudStartupRoot.AddComponent(); ((Graphic)obj2).color = new Color(0.005f, 0.035f, 0.04f, 0.94f); ((Graphic)obj2).raycastTarget = false; CreateManualHudImage("StartupFrameTop", _manualHudStartupRoot.transform, new Vector2(0f, 92f), new Vector2(0.5f, 0.5f), new Vector2(700f, 3f), new Color(0.12f, 1f, 0.92f, 0.62f)); CreateManualHudImage("StartupFrameBottom", _manualHudStartupRoot.transform, new Vector2(0f, -92f), new Vector2(0.5f, 0.5f), new Vector2(700f, 3f), new Color(0.12f, 1f, 0.92f, 0.62f)); CreateManualHudImage("StartupBarBack", _manualHudStartupRoot.transform, new Vector2(0f, -54f), new Vector2(0.5f, 0.5f), new Vector2(620f, 12f), new Color(0.06f, 0.28f, 0.29f, 0.9f)); _manualHudStartupProgressImage = CreateManualHudImage("StartupBarFill", _manualHudStartupRoot.transform, new Vector2(-310f, -54f), new Vector2(0.5f, 0.5f), new Vector2(0f, 8f), new Color(0.16f, 1f, 0.88f, 0.96f)); ((Component)_manualHudStartupProgressImage).GetComponent().pivot = new Vector2(0f, 0.5f); _manualHudStartupText = CreateManualHudText("StartupText", _manualHudStartupRoot.transform, font, new Vector2(0f, 18f), new Vector2(0.5f, 0.5f), (TextAnchor)4, 40, new Color(0.76f, 1f, 0.96f, 0.98f)); ((Component)_manualHudStartupText).GetComponent().sizeDelta = new Vector2(900f, 150f); _manualHudStartupRoot.SetActive(false); } } private static void UpdateManualHud() { //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_manualHudRoot == (Object)null)) { string arg = $"{FormatCargoWeight(GetCarriedCargoWeightPounds())} ({CarriedItems.Count})"; float num = (((Object)(object)_droneVisual != (Object)null) ? Mathf.Max(0f, _droneVisual.transform.position.y - _droneGroundPosition.y) : 0f); if ((Object)(object)_manualHudStatusText != (Object)null) { _manualHudStatusText.text = "COURIER DRONE LINK\nREMOTE LINK ACTIVE"; } if ((Object)(object)_manualHudCargoText != (Object)null) { _manualHudCargoText.text = $"CARGO {arg}\nHP {Mathf.Clamp(_droneHealth, 0, 30)}/{30}"; } if ((Object)(object)_manualHudTelemetryText != (Object)null) { _manualHudTelemetryText.text = string.Format("ALT {0:0.0}m\nMODE {1}", num, _droneIsInside ? "INTERIOR" : "EXTERIOR"); } UpdateManualStartupOverlay(); } } private static string BuildManualControlLegend() { IngameKeybinds keybinds = Y4NGZUpgrades.Gui.Plugin.Keybinds; string text = UpgradeInput.DisplayPair(keybinds?.DronePilotAscend, "SPACE", keybinds?.DronePilotDescend, "CTRL"); string text2 = UpgradeInput.DisplayLabel(keybinds?.DronePilotFlame, "LMB"); string text3 = UpgradeInput.DisplayLabel(keybinds?.DronePilotGrenade, "RMB"); string text4 = UpgradeInput.DisplayLabel(keybinds?.DronePilotLift, "E"); string text5 = UpgradeInput.DisplayLabel(keybinds?.DronePilotLight, "F"); string text6 = UpgradeInput.DisplayLabel(keybinds?.DronePilotExit, "ESC"); return "VANILLA MOVE/LOOK [" + text + "] ALT [" + text2 + "] FLAME [" + text3 + "] GRENADE [" + text4 + "] LIFT [" + text5 + "] LIGHT [" + text6 + "] EXIT"; } private static void UpdateManualStartupOverlay() { //IL_0096: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_manualHudStartupRoot == (Object)null) { return; } bool flag = _manualControlCameraActivated && Time.unscaledTime < _manualDroneStartupUntil; if (_manualHudStartupRoot.activeSelf != flag) { _manualHudStartupRoot.SetActive(flag); } if (flag) { float num = Mathf.Max(0f, _manualDroneStartupUntil - Time.unscaledTime); float num2 = Mathf.Clamp01(1f - num / 1f); if ((Object)(object)_manualHudStartupProgressImage != (Object)null) { ((Component)_manualHudStartupProgressImage).GetComponent().sizeDelta = new Vector2(Mathf.Lerp(96f, 620f, num2), 8f); } if ((Object)(object)_manualHudStartupText != (Object)null) { _manualHudStartupText.text = ((num2 < 0.58f) ? "COURIER DRONE\nLINK INITIALIZING" : "COURIER DRONE\nFEED SYNCING"); } } } private static void DestroyManualHud() { if (!((Object)(object)_manualHudRoot == (Object)null)) { Object.Destroy((Object)(object)_manualHudRoot); _manualHudRoot = null; _manualHudStatusText = null; _manualHudCargoText = null; _manualHudTelemetryText = null; _manualHudControlsText = null; _manualHudStartupRoot = null; _manualHudStartupText = null; _manualHudStartupProgressImage = null; } } private static void HandleManualDroneActions(PlayerControllerB player) { //IL_001b: 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) IngameKeybinds keybinds = Y4NGZUpgrades.Gui.Plugin.Keybinds; if (UpgradeInput.WasPressed(keybinds?.DronePilotFlame)) { TryRequestManualFire(player, ManualFireKind.Flame, GetDroneCombatPosition()); } if (UpgradeInput.WasPressed(keybinds?.DronePilotGrenade)) { TryRequestManualFire(player, ManualFireKind.Grenade, ResolveManualGrenadeTarget()); } if (UpgradeInput.WasPressed(keybinds?.DronePilotLift)) { TryManualPickup(player); } if (UpgradeInput.WasPressed(keybinds?.DronePilotLight)) { TryExecuteTabletCommand(player, CourierCommandType.Flashlight); } } private static void TryRequestManualFire(PlayerControllerB player, ManualFireKind fireKind, Vector3 targetPosition) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && _manualControlActive) { int playerId = (int)player.playerClientId; if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient) { HandleManualFireRequest(playerId, fireKind, targetPosition); } else if (NetworkManager.Singleton.IsServer) { HandleManualFireRequest(playerId, fireKind, targetPosition); } else { SendManualFireRequest(playerId, fireKind, targetPosition); } } } private static Vector3 ResolveManualGrenadeTarget() { //IL_0019: 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_001e: 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_0020: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0071: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)ResolveGrenadeMuzzle() != (Object)null) ? ResolveGrenadeMuzzle().position : GetDroneCombatOrigin()); if (val == Vector3.zero) { return Vector3.zero; } Camera val2 = (((Object)(object)_manualCamera != (Object)null) ? _manualCamera : Camera.main); Vector3 val3 = (((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform.forward : Vector3.forward); Vector3 val4 = val; if ((Object)(object)val2 != (Object)null) { val4 = ((Component)val2).transform.position; val3 = ((Component)val2).transform.forward; } int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); Vector3 target = val4 + ((Vector3)(ref val3)).normalized * 18f; RaycastHit val5 = default(RaycastHit); if (Physics.Raycast(val4, val3, ref val5, 18f, num, (QueryTriggerInteraction)1)) { target = ((RaycastHit)(ref val5)).point; } return ClampManualGrenadeTarget(val, target); } private static Vector3 ClampManualGrenadeTarget(Vector3 start, Vector3 target) { //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_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_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_0034: 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_0039: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - start; if (((Vector3)(ref val)).sqrMagnitude <= 0.001f) { val = (((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform.forward : Vector3.forward); } float num = Mathf.Clamp(((Vector3)(ref val)).magnitude, 8f, 18f); return start + ((Vector3)(ref val)).normalized * num; } private static void TryManualPickup(PlayerControllerB player) { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null || Time.time < _manualPickupLockedUntil) { return; } if (IsCargoWeightFull()) { DisplayOwnerTip(_manualControlPlayerId, "Cargo weight full.", isWarning: true); return; } GrabbableObject val = FindManualPickupTarget(); if ((Object)(object)val == (Object)null) { DisplayOwnerTip(_manualControlPlayerId, "No scrap close enough to lift.", isWarning: true); return; } if (WouldExceedCargoWeight(val, GetCarriedCargoWeightPounds())) { DisplayOwnerTip(_manualControlPlayerId, "That scrap would exceed 150 lb cargo.", isWarning: true); return; } CourierItemMove courierItemMove = new CourierItemMove(((NetworkBehaviour)val).NetworkObjectId, ((Component)val).transform.position, FindShipDropPosition(player), val.isInFactory); _manualPickupLockedUntil = Time.time + 1.25f; CourierItemMove itemMove = courierItemMove; StartCoroutineOnAvailableHost(MagnetPickUpScrap(itemMove, itemMove.PickupIsInFactory, val, _routeVersion)); BroadcastManualPickup(courierItemMove); } private static GrabbableObject FindManualPickupTarget() { //IL_0019: 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_0039: 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_003e: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: 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) if ((Object)(object)_droneVisual == (Object)null) { return null; } Vector3 position = _droneVisual.transform.position; Vector3 val = (((Object)(object)_manualCamera != (Object)null) ? ((Component)_manualCamera).transform.position : position); Vector3 val2 = (((Object)(object)_manualCamera != (Object)null) ? ((Component)_manualCamera).transform.forward : _droneVisual.transform.forward); float radiusSqr = 17.639997f; GrabbableObject[] array = ScanGrabbableObjectsForCommandOrSweep(); GrabbableObject result = null; float num = float.MaxValue; foreach (GrabbableObject val3 in array) { if (IsManualPickupEligible(val3, position, radiusSqr)) { Vector3 val4 = ((Component)val3).transform.position + Vector3.up * 0.2f - val; float num2 = Vector3.Angle(val2, val4); float num3 = Vector3.Distance(position, ((Component)val3).transform.position) + num2 * 0.035f; if (num2 > 82f) { num3 += 8f; } if (!(num3 >= num)) { num = num3; result = val3; } } } return result; } private static bool IsManualPickupEligible(GrabbableObject item, Vector3 dronePosition, float radiusSqr) { //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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item != (Object)null && (Object)(object)item.itemProperties != (Object)null && item.itemProperties.isScrap && item.isInFactory == _droneIsInside && !item.isHeld && !item.isPocketed && !item.isHeldByEnemy && !item.isInShipRoom && item.grabbable && !IsAlreadyCarried(((NetworkBehaviour)item).NetworkObjectId) && !IsAlreadyPlanned(((NetworkBehaviour)item).NetworkObjectId)) { Vector3 val = ((Component)item).transform.position - dronePosition; return ((Vector3)(ref val)).sqrMagnitude <= radiusSqr; } return false; } private static void StopManualControl(bool resumeDrone, bool notifyOwner) { bool manualControlActive = _manualControlActive; int manualControlPlayerId = _manualControlPlayerId; if (!manualControlActive && (Object)(object)_manualCameraObject == (Object)null) { return; } FieldOperationsTabletPatch.TrySetPilotActionReadyHold(hold: false); DestroyManualHud(); RestoreManualPlayerPresentation(); RestorePlayerInputAndCamera(); if ((Object)(object)_manualCameraObject != (Object)null) { Object.Destroy((Object)(object)_manualCameraObject); _manualCameraObject = null; _manualCamera = null; } _manualControlActive = false; _manualControlCameraActivated = false; _manualControlPlayerId = -1; _manualDroneStartupUntil = 0f; _manualNextPoseSyncAt = 0f; _manualPickupLockedUntil = 0f; _manualSavedInputState = false; _manualSavedPresentationState = false; if (manualControlActive) { BroadcastManualPose(active: false); } if (resumeDrone && (Object)(object)_droneVisual != (Object)null && !_droneDestroyedThisRound && _mode == DroneMode.ManualControl) { _mode = ((_manualPreviousMode == DroneMode.NotSpawned || IsBusyMode(_manualPreviousMode)) ? DroneMode.IdleAtPlayer : _manualPreviousMode); if (_mode == DroneMode.ManualControl) { _mode = DroneMode.IdleAtPlayer; } int version = ++_routeVersion; if (_mode == DroneMode.IdleAtPlayer) { StartIdleFollow(version); } } if (notifyOwner && manualControlActive) { DisplayOwnerTip(manualControlPlayerId, "Tablet control closed.", isWarning: false); } } private static void RestorePlayerInputAndCamera() { PlayerControllerB val = ResolvePlayer(_manualControlPlayerId) ?? GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { val.disableMoveInput = _restoreMoveInput; val.disableLookInput = _restoreLookInput; val.disableInteract = _restoreInteractInput; if ((Object)(object)val.gameplayCamera != (Object)null) { ((Behaviour)val.gameplayCamera).enabled = _restoreGameplayCameraEnabled; } } } private static CourierCommand BuildCommand(PlayerControllerB player, CourierCommandType commandType, int courierTierOverride = -1) { //IL_0064: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0171: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_0191: 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_019b: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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) if (_droneDestroyedThisRound) { return null; } CourierCommand courierCommand = BuildCommandContext(player, courierTierOverride); if (courierCommand == null) { return null; } DroneMode droneMode = ((!((Object)(object)_droneVisual == (Object)null)) ? _mode : DroneMode.NotSpawned); switch (commandType) { case CourierCommandType.Spawn: courierCommand.Type = ((droneMode == DroneMode.NotSpawned) ? CourierCommandType.Spawn : CourierCommandType.None); courierCommand.DroneStartPosition = FindDroneStartPosition(player); if (courierCommand.DroneStartPosition == Vector3.zero) { courierCommand.Type = CourierCommandType.None; } break; case CourierCommandType.Dismiss: courierCommand.Type = ((droneMode != DroneMode.NotSpawned) ? CourierCommandType.Dismiss : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(FindDroneStartPosition(player)); courierCommand.DropIsInShip = IsPlayerInShip(player); courierCommand.DropIsInFactory = (Object)(object)player != (Object)null && player.isInsideFactory; courierCommand.DropPosition = FindPlayerDropPosition(player); break; case CourierCommandType.Guard: courierCommand.Type = ((droneMode != DroneMode.NotSpawned && !IsBusyMode(droneMode)) ? CourierCommandType.Guard : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(FindDroneStartPosition(player)); break; case CourierCommandType.FlyToEntrance: courierCommand.Type = ((droneMode != DroneMode.NotSpawned && !IsBusyMode(droneMode) && droneMode != DroneMode.AtEntrance) ? CourierCommandType.FlyToEntrance : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(FindDroneStartPosition(player)); if (courierCommand.Type == CourierCommandType.FlyToEntrance) { courierCommand.Items.AddRange(FindEntranceScrap(courierCommand)); } break; case CourierCommandType.ReturnToShip: courierCommand.Type = ((droneMode != DroneMode.NotSpawned && !IsBusyMode(droneMode)) ? CourierCommandType.ReturnToShip : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(courierCommand.EntrancePosition); break; case CourierCommandType.Flashlight: courierCommand.Type = ((droneMode != DroneMode.NotSpawned) ? CourierCommandType.Flashlight : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(FindDroneStartPosition(player)); courierCommand.FlashlightEnabled = !_flashlightEnabled; break; case CourierCommandType.Pilot: courierCommand.Type = ((courierCommand.CourierTier >= 3 && droneMode != DroneMode.NotSpawned && droneMode != DroneMode.ManualControl && !IsBusyMode(droneMode) && !_magnetPickupActive && Time.time >= _manualPickupLockedUntil) ? CourierCommandType.Pilot : CourierCommandType.None); courierCommand.DroneStartPosition = CurrentDroneGroundPositionOr(FindDroneStartPosition(player)); break; default: courierCommand.Type = CourierCommandType.None; break; } return courierCommand; } private static CourierCommand BuildCommandContext(PlayerControllerB player, int courierTierOverride = -1) { //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_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_0098: 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) //IL_00a3: 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_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_00a8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return null; } MainEntranceRoute mainEntranceRoute = FindMainEntranceRoute(); CourierCommand courierCommand = new CourierCommand { CourierTier = ((courierTierOverride >= 0) ? Mathf.Clamp(courierTierOverride, 0, 3) : CourierDroneUpgrade.GetTier()), PlayerId = (int)player.playerClientId, PlayerWasInside = player.isInsideFactory, DropIsInShip = true, DropIsInFactory = false, DropPosition = FindShipDropPosition(player), OutsideEntrancePosition = mainEntranceRoute.OutsidePosition, InsideEntrancePosition = mainEntranceRoute.InsidePosition }; courierCommand.EntrancePosition = (courierCommand.PlayerWasInside ? FirstNonZero(courierCommand.InsideEntrancePosition, courierCommand.OutsideEntrancePosition) : FirstNonZero(courierCommand.OutsideEntrancePosition, courierCommand.InsideEntrancePosition)); return courierCommand; } private static List FindEntranceScrap(CourierCommand command, List searchPositions = null) { //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) List list = new List(); List positions = searchPositions ?? FindMainEntranceSearchPositions(command); if (positions.Count == 0) { return list; } GrabbableObject[] array = ScanGrabbableObjectsForCommandOrSweep(); Array.Sort(array, delegate(GrabbableObject a, GrabbableObject b) { //IL_000f: 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) float num3 = (((Object)(object)a == (Object)null) ? float.MaxValue : DistanceToClosestPointSqr(((Component)a).transform.position, positions)); float value = (((Object)(object)b == (Object)null) ? float.MaxValue : DistanceToClosestPointSqr(((Component)b).transform.position, positions)); return num3.CompareTo(value); }); float radiusSqr = 100f; float num = GetReservedCargoWeightPounds(); for (int num2 = 0; num2 < array.Length; num2++) { if (list.Count >= 12) { break; } GrabbableObject val = array[num2]; if (IsCourierEligibleEntranceScrap(val, positions, radiusSqr) && !IsAlreadyCarried(((NetworkBehaviour)val).NetworkObjectId) && !IsAlreadyPlanned(((NetworkBehaviour)val).NetworkObjectId) && !WouldExceedCargoWeight(val, num)) { Vector3 dropPosition = command.DropPosition + new Vector3(Random.Range(-1.4f, 1.4f), 0.15f, Random.Range(-1f, 1f)); list.Add(new CourierItemMove(((NetworkBehaviour)val).NetworkObjectId, ((Component)val).transform.position, dropPosition, val.isInFactory)); num += GetItemWeightPounds(val); } } return list; } private static GrabbableObject[] ScanGrabbableObjectsForCommandOrSweep() { GrabbableObject[] array = Object.FindObjectsOfType(); CacheKnownGrabbableItems(array); return array; } private static void CacheKnownGrabbableItems(GrabbableObject[] items) { if (items == null) { return; } foreach (GrabbableObject val in items) { if ((Object)(object)val != (Object)null) { KnownGrabbableItems[((NetworkBehaviour)val).NetworkObjectId] = val; } } } private static void ApplyCommand(CourierCommand command) { if (command != null && command.Type != CourierCommandType.None && !_droneDestroyedThisRound) { if (command.CourierTier > 0) { _ownerCourierTier = command.CourierTier; } if (command.Type != CourierCommandType.Flashlight) { ClearPointerTargetState(); } switch (command.Type) { case CourierCommandType.Spawn: SpawnDroneAt(command); break; case CourierCommandType.Dismiss: StartDismiss(command); break; case CourierCommandType.Guard: StartGuardingPlayer(command); break; case CourierCommandType.FlyToEntrance: StartFlyToEntrance(command); break; case CourierCommandType.ReturnToShip: StartReturnToShip(command); break; case CourierCommandType.Flashlight: ApplyFlashlightState(command.FlashlightEnabled); _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); BroadcastDroneState(); break; case CourierCommandType.Pilot: StartPilotControl(command); break; } } } private static float GetCommandCooldownSeconds(CourierCommandType commandType) { if (commandType != CourierCommandType.Guard && commandType != CourierCommandType.Flashlight && commandType != CourierCommandType.Pilot) { return 3f; } return 1f; } private static void StartPilotControl(CourierCommand command) { if (command != null && !((Object)(object)_droneVisual == (Object)null) && !_droneDestroyedThisRound) { if (_mode != DroneMode.ManualControl) { _manualPreviousMode = _mode; } _ownerPlayerId = command.PlayerId; _ownerCourierTier = Mathf.Max(_ownerCourierTier, command.CourierTier); _mode = DroneMode.ManualControl; _isFollowingPlayer = false; _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); _routeVersion++; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (int)val.playerClientId == command.PlayerId) { TryStartManualControl(val); } if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { BroadcastDroneState(); } } } private static void ApplyFlashlightState(bool enabled) { _flashlightEnabled = enabled; if ((Object)(object)_droneVisual != (Object)null) { CourierDroneRuntimeAssets.SetFlashlight(_droneVisual, enabled); } } private static void SpawnDroneAt(CourierCommand command) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if (!_droneDestroyedThisRound) { _routeVersion++; PlannedItems.Clear(); CarriedItems.Clear(); _reportedNoEntranceScrap = false; _ownerPlayerId = command.PlayerId; _ownerCourierTier = Mathf.Max(command.CourierTier, 1); _droneIsInside = command.PlayerWasInside; _droneGroundPosition = command.DroneStartPosition; if (_droneHealth <= 0) { _droneHealth = 30; } _mode = DroneMode.IdleAtPlayer; _nextDroneAttackWarningAt = 0f; EnsureDroneVisualAt(command.DroneStartPosition); CourierDroneRuntimeAssets.PlayMaterializeIn(_droneVisual); CourierDroneRuntimeAssets.PlayLiftOff(_droneVisual); ApplyFlashlightState(_flashlightEnabled); _combatLandedUntil = 0f; CourierDroneRuntimeAssets.PlayWakeupSound(_droneVisual); _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); DisplayOwnerTip(command.PlayerId, "Drone deployed. It will stay with you.", isWarning: false); StartIdleFollow(_routeVersion); } } private static void StartDismiss(CourierCommand command) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_droneVisual == (Object)null)) { StopManualControl(resumeDrone: false, notifyOwner: false); EnsureDroneVisualAt(command.DroneStartPosition); CourierDroneRuntimeAssets.PlayRecallSound(_droneVisual); _combatLandedUntil = 0f; _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); _ownerPlayerId = command.PlayerId; _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); DisplayOwnerTip(command.PlayerId, "Drone dismissing.", isWarning: false); StartCoroutineOnAvailableHost(DismissRoutine(command, ++_routeVersion)); } } private static void StartGuardingPlayer(CourierCommand command) { if (!((Object)(object)_droneVisual == (Object)null)) { StopManualControl(resumeDrone: true, notifyOwner: false); _routeVersion++; _mode = DroneMode.GuardingPlayer; _ownerPlayerId = command.PlayerId; if (command.CourierTier > 0) { _ownerCourierTier = command.CourierTier; } _combatLandedUntil = 0f; _nextGuardScrapScanAt = 0f; _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); DisplayOwnerTip(command.PlayerId, "Guard mode active.", isWarning: false); StartCoroutineOnAvailableHost(GuardFollowRoutine(_routeVersion)); } } private static void StartFlyToEntrance(CourierCommand command) { //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_0025: Unknown result type (might be due to invalid IL or missing references) if (command.EntrancePosition == Vector3.zero) { DisplayOwnerTip(command.PlayerId, "Main entrance route not found.", isWarning: true); return; } EnsureDroneVisualAt(command.DroneStartPosition); CourierDroneRuntimeAssets.PlaySendToEntranceSound(_droneVisual); _combatLandedUntil = 0f; _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); PlannedItems.Clear(); PlannedItems.AddRange(command.Items); _reportedNoEntranceScrap = false; _nextEntranceScrapScanAt = 0f; _ownerPlayerId = command.PlayerId; _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); DisplayOwnerTip(command.PlayerId, (PlannedItems.Count > 0) ? $"Scanning entrance. {PlannedItems.Count} scrap queued, {FormatCargoWeight(GetPlannedCargoWeightPounds())} planned." : "Scanning entrance for scrap.", isWarning: false); StartCoroutineOnAvailableHost(FlyToEntranceRoutine(command, ++_routeVersion)); } private static void StartReturnToShip(CourierCommand command) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) EnsureDroneVisualAt(command.DroneStartPosition); CourierDroneRuntimeAssets.PlayRecallSound(_droneVisual); _combatLandedUntil = 0f; _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); command.Items.Clear(); command.Items.AddRange(PlannedItems); _ownerPlayerId = command.PlayerId; _commandCooldownEnd = Time.time + GetCommandCooldownSeconds(command.Type); DisplayOwnerTip(command.PlayerId, (CarriedItems.Count > 0) ? $"Returning cargo {FormatCargoWeight(GetCarriedCargoWeightPounds())} ({CarriedItems.Count} items)." : "Returning to ship.", isWarning: false); StartCoroutineOnAvailableHost(ReturnToShipRoutine(command, ++_routeVersion)); } private static bool HandlePointerCommand(int playerId, int courierTier, CourierCommandType commandType, NetworkObjectReference targetReference) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!IsServerAuthority()) { return false; } PlayerControllerB player = ResolvePlayer(playerId); if (!CanServerAcceptPointerCommand(player)) { return false; } switch (commandType) { case CourierCommandType.PointerAttack: { if (!TryResolvePointerAttackTarget(targetReference, out var enemy)) { return false; } StartPointerAttack(player, enemy, courierTier); return true; } case CourierCommandType.PointerFetch: { if (!TryResolvePointerFetchTarget(targetReference, out var item)) { return false; } StartPointerFetch(player, item, courierTier); return true; } default: return false; } } private static bool CanServerAcceptPointerCommand(PlayerControllerB player) { if (CourierDroneUpgrade.IsUnlocked() && (Object)(object)_droneVisual != (Object)null && !_droneDestroyedThisRound && _mode != DroneMode.NotSpawned && _mode != DroneMode.ManualControl && !_manualControlActive) { return CanUsePointer(player); } return false; } private static bool TryResolvePointerAttackTarget(NetworkObjectReference targetReference, out EnemyAI enemy) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) enemy = null; if (!TryResolveNetworkObjectReference(targetReference, out var targetObject)) { return false; } enemy = ((Component)targetObject).GetComponent(); if ((Object)(object)enemy == (Object)null) { enemy = ((Component)targetObject).GetComponentInChildren(); } if ((Object)(object)enemy == (Object)null) { enemy = ((Component)targetObject).GetComponentInParent(); } if ((Object)(object)enemy == (Object)null) { EnemyAICollisionDetect componentInChildren = ((Component)targetObject).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { enemy = componentInChildren.mainScript; } } if ((Object)(object)enemy != (Object)null && !enemy.isEnemyDead) { return EnemySharesDroneSpace(enemy); } return false; } private static bool TryResolvePointerFetchTarget(NetworkObjectReference targetReference, out GrabbableObject item) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) item = null; if (!TryResolveNetworkObjectReference(targetReference, out var targetObject)) { return false; } item = ((Component)targetObject).GetComponent(); if ((Object)(object)item == (Object)null) { item = ((Component)targetObject).GetComponentInChildren(); } if ((Object)(object)item == (Object)null) { item = ((Component)targetObject).GetComponentInParent(); } return IsPointerFetchEligible(item); } private static bool TryResolveNetworkObjectReference(NetworkObjectReference targetReference, out NetworkObject targetObject) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) targetObject = null; NetworkObjectReference val = targetReference; if (((NetworkObjectReference)(ref val)).TryGet(ref targetObject, NetworkManager.Singleton)) { return (Object)(object)targetObject != (Object)null; } return false; } private static void StartPointerAttack(PlayerControllerB player, EnemyAI enemy, int courierTier) { if (!((Object)(object)player == (Object)null) && !((Object)(object)enemy == (Object)null)) { PreparePointerCommandMode(player, courierTier, DroneMode.PointerAttack); _priorityTargetId = (((Object)(object)((NetworkBehaviour)enemy).NetworkObject != (Object)null) ? ((NetworkBehaviour)enemy).NetworkObjectId : GetEnemyKey(enemy)); _priorityTargetExpiresAt = Time.time + 20f; _priorityTargetUnreachableSince = 0f; MarkDroneThreat(enemy, 20f); CourierDroneRuntimeAssets.PlaySendToEntranceSound(_droneVisual); StartCoroutineOnAvailableHost(PointerAttackRoutine(_priorityTargetId, _routeVersion)); BroadcastDroneState(); } } private static void StartPointerFetch(PlayerControllerB player, GrabbableObject item, int courierTier) { if (!((Object)(object)player == (Object)null) && !((Object)(object)item == (Object)null)) { PreparePointerCommandMode(player, courierTier, DroneMode.PointerFetch); CourierDroneRuntimeAssets.PlaySendToEntranceSound(_droneVisual); StartCoroutineOnAvailableHost(PointerFetchRoutine(((NetworkBehaviour)item).NetworkObjectId, (int)player.playerClientId, _routeVersion)); BroadcastDroneState(); } } private static void PreparePointerCommandMode(PlayerControllerB player, int courierTier, DroneMode mode) { StopManualControl(resumeDrone: false, notifyOwner: false); if (_mode != DroneMode.PointerAttack && _mode != DroneMode.PointerFetch) { _pointerPreviousMode = _mode; } if (!CanResumePointerMode(_pointerPreviousMode)) { _pointerPreviousMode = DroneMode.IdleAtPlayer; } _ownerPlayerId = (int)player.playerClientId; if (courierTier > 0) { _ownerCourierTier = Mathf.Max(_ownerCourierTier, courierTier); } _mode = mode; _isFollowingPlayer = false; _followSettled = false; _combatLandedUntil = 0f; _lastRouteMoveBlocked = false; ClearFollowPathCache(); ResetFollowMovementState(); _routeVersion++; } private static IEnumerator PointerAttackRoutine(ulong enemyKey, int version) { while (version == _routeVersion && _mode == DroneMode.PointerAttack) { EnemyAI val = ResolveEnemy(enemyKey); if (!IsValidPriorityTarget(val) || Time.time > _priorityTargetExpiresAt) { break; } MarkDroneThreat(val, 8f); Vector3 val2 = ResolveEnemyCenter(val); Vector3 droneCombatPosition = GetDroneCombatPosition(); float num = 3.1499999f; if (val2 != Vector3.zero && droneCombatPosition != Vector3.zero) { Vector3 val3 = val2 - droneCombatPosition; if (((Vector3)(ref val3)).sqrMagnitude <= num * num) { _priorityTargetUnreachableSince = 0f; HoldPointerAttackPosition(val); yield return null; continue; } } Vector3 val4 = ResampleGroundPoint(((Component)val).transform.position, CurrentDroneGroundPositionOr(_droneGroundPosition)); if (val4 == Vector3.zero) { if (HasPointerBeenUnreachable(blocked: true)) { break; } yield return null; continue; } yield return MovePointerTowardGround(val4, version); if (version != _routeVersion) { yield break; } if (HasPointerBeenUnreachable(_lastRouteMoveBlocked)) { break; } } ResumePointerPreviousMode(version); } private static IEnumerator PointerFetchRoutine(ulong itemId, int ownerPlayerId, int version) { float deadline = Time.time + 25f; bool pickedUp = IsAlreadyCarried(itemId); bool returnedToPlayer = false; while (!pickedUp && version == _routeVersion && _mode == DroneMode.PointerFetch && Time.time < deadline) { GrabbableObject val = ResolveItem(itemId); if (!IsPointerFetchEligible(val)) { break; } if (IsDroneCloseEnoughToItem(val)) { Vector3 dropPosition = FindPlayerDropPosition(ResolvePlayer(ownerPlayerId)); CourierItemMove itemMove = new CourierItemMove(((NetworkBehaviour)val).NetworkObjectId, ((Component)val).transform.position, dropPosition, val.isInFactory); yield return MagnetPickUpScrap(itemMove, itemMove.PickupIsInFactory, val, version); pickedUp = IsAlreadyCarried(itemId); break; } Vector3 val2 = ResampleGroundPoint(((Component)val).transform.position, CurrentDroneGroundPositionOr(_droneGroundPosition)); if (val2 == Vector3.zero) { if (HasPointerBeenUnreachable(blocked: true)) { break; } yield return null; continue; } yield return MovePointerTowardGround(val2, version); if (version != _routeVersion) { yield break; } if (HasPointerBeenUnreachable(_lastRouteMoveBlocked)) { break; } } if (pickedUp && version == _routeVersion && _mode == DroneMode.PointerFetch) { yield return ReturnPointerFetchCargo(ownerPlayerId, version, deadline); returnedToPlayer = IsPointerFetchReturnComplete(ownerPlayerId); } if ((!pickedUp || !returnedToPlayer) && version == _routeVersion && _mode == DroneMode.PointerFetch) { CourierDroneRuntimeAssets.PlayRecallSound(_droneVisual); } ResumePointerPreviousMode(version); } private static IEnumerator ReturnPointerFetchCargo(int ownerPlayerId, int version, float deadline) { while (version == _routeVersion && _mode == DroneMode.PointerFetch && Time.time < deadline) { PlayerControllerB val = ResolvePlayer(ownerPlayerId); if ((Object)(object)val == (Object)null || val.isPlayerDead || (Object)(object)((Component)val).transform == (Object)null || val.isInsideFactory != _droneIsInside) { break; } Vector3 val2 = ResampleGroundPoint(FindPlayerDropPosition(val), CurrentDroneGroundPositionOr(_droneGroundPosition)); if (val2 == Vector3.zero) { break; } Vector3 val3 = CurrentDroneGroundPositionOr(_droneGroundPosition); if (val3 != Vector3.zero) { Vector3 val4 = val3 - val2; if (((Vector3)(ref val4)).sqrMagnitude <= 1.8225001f) { break; } } yield return MovePointerTowardGround(val2, version); if (version != _routeVersion || HasPointerBeenUnreachable(_lastRouteMoveBlocked)) { break; } } } private static bool IsPointerFetchReturnComplete(int ownerPlayerId) { //IL_0035: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = ResolvePlayer(ownerPlayerId); if ((Object)(object)val == (Object)null || val.isPlayerDead || (Object)(object)((Component)val).transform == (Object)null || val.isInsideFactory != _droneIsInside) { return false; } Vector3 val2 = CurrentDroneGroundPositionOr(_droneGroundPosition); Vector3 val3 = ResampleGroundPoint(FindPlayerDropPosition(val), val2); if (val2 != Vector3.zero && val3 != Vector3.zero) { Vector3 val4 = val2 - val3; return ((Vector3)(ref val4)).sqrMagnitude <= 1.8225001f; } return false; } private static IEnumerator MovePointerTowardGround(Vector3 targetGround, int version) { //IL_0007: 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) _lastRouteMoveBlocked = false; if ((Object)(object)_droneVisual == (Object)null || targetGround == Vector3.zero) { _lastRouteMoveBlocked = true; yield break; } Vector3 val = CurrentDroneGroundPositionOr(_droneGroundPosition); if (val == Vector3.zero) { val = ResampleGroundPoint(_droneVisual.transform.position, targetGround); } if (val == Vector3.zero) { _lastRouteMoveBlocked = true; yield break; } List list = BuildNavMeshPath(val, targetGround); if (list == null || list.Count < 2) { _lastRouteMoveBlocked = true; yield break; } Vector3 position = _droneVisual.transform.position; yield return MoveDroneSegment(list[0], list[1], position.x, position.y, position.z, version); } private static void HoldPointerAttackPosition(EnemyAI enemy) { //IL_0018: 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_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_droneVisual == (Object)null) && !((Object)(object)enemy == (Object)null)) { Vector3 val = ResolveEnemyCenter(enemy) - _droneVisual.transform.position; FaceTravelDirection(_droneVisual.transform, val.x, val.y, val.z); UpdateCarriedItemTransforms(); } } private static bool HasPointerBeenUnreachable(bool blocked) { if (!blocked) { _priorityTargetUnreachableSince = 0f; return false; } if (_priorityTargetUnreachableSince <= 0f) { _priorityTargetUnreachableSince = Time.time; } return Time.time - _priorityTargetUnreachableSince >= 8f; } private static bool IsValidPriorityTarget(EnemyAI enemy) { if ((Object)(object)enemy != (Object)null && !enemy.isEnemyDead && EnemySharesDroneSpace(enemy)) { return Time.time <= _priorityTargetExpiresAt; } return false; } private static EnemyAI ResolveEnemy(ulong enemyKey) { if (enemyKey == 0L) { return null; } if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(enemyKey, out var value) && (Object)(object)value != (Object)null) { EnemyAI component = ((Component)value).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } } RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null) { return null; } for (int i = 0; i < instance.SpawnedEnemies.Count; i++) { EnemyAI val = instance.SpawnedEnemies[i]; if ((Object)(object)val != (Object)null && GetEnemyKey(val) == enemyKey) { return val; } } return null; } private static bool IsDroneCloseEnoughToItem(GrabbableObject item) { //IL_0024: 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_003d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null || (Object)(object)_droneVisual == (Object)null) { return false; } float num = 10f; Vector3 val = ((Component)item).transform.position - _droneVisual.transform.position; return ((Vector3)(ref val)).sqrMagnitude <= num * num; } private static bool CanResumePointerMode(DroneMode mode) { if (mode != DroneMode.IdleAtPlayer && mode != DroneMode.GuardingPlayer) { return mode == DroneMode.AtEntrance; } return true; } private static void ResumePointerPreviousMode(int version) { if (version != _routeVersion) { return; } DroneMode droneMode = ((!CanResumePointerMode(_pointerPreviousMode)) ? DroneMode.IdleAtPlayer : _pointerPreviousMode); ClearPointerTargetState(); _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); int version2 = ++_routeVersion; switch (droneMode) { case DroneMode.GuardingPlayer: _mode = DroneMode.GuardingPlayer; StartCoroutineOnAvailableHost(GuardFollowRoutine(version2)); break; case DroneMode.AtEntrance: { CourierCommand courierCommand = BuildCommandContext(ResolvePlayer(_ownerPlayerId)); if (courierCommand != null) { _mode = DroneMode.AtEntrance; StartCoroutineOnAvailableHost(WaitAtEntranceRoutine(courierCommand, version2)); } else { _mode = DroneMode.IdleAtPlayer; StartIdleFollow(version2); } break; } default: _mode = DroneMode.IdleAtPlayer; StartIdleFollow(version2); break; } BroadcastDroneState(); } private static void ClearPriorityTargetOnly() { _priorityTargetId = 0uL; _priorityTargetExpiresAt = 0f; _priorityTargetUnreachableSince = 0f; } private static void ClearPointerTargetState() { ClearPriorityTargetOnly(); _pointerPreviousMode = DroneMode.NotSpawned; } private static IEnumerator FlyToEntranceRoutine(CourierCommand command, int version) { _mode = DroneMode.FlyingToEntrance; List route = BuildRouteToEntrance(command); yield return MoveAlongRoute(command, route, version, pickUpAtEntrance: false); if (version == _routeVersion && !_lastRouteMoveBlocked) { _mode = DroneMode.AtEntrance; if (route.Count > 0) { _droneGroundPosition = route[route.Count - 1]; _droneIsInside = IsSameRoutePoint(_droneGroundPosition, command.InsideEntrancePosition); } yield return WaitAtEntranceRoutine(command, version); } } private static IEnumerator DismissRoutine(CourierCommand command, int version) { _mode = DroneMode.FlyingToPlayer; List route = BuildRouteToDrop(command, includeShipApproach: false); yield return MoveAlongRoute(command, route, version, pickUpAtEntrance: false); if (version != _routeVersion || _lastRouteMoveBlocked) { yield break; } CourierDroneRuntimeAssets.PlayLand(_droneVisual); _combatLandedUntil = Time.time + 0.35f; yield return (object)new WaitForSeconds(0.35f); if (version != _routeVersion) { yield break; } float num = CourierDroneRuntimeAssets.PlayDematerializeOut(_droneVisual); if (num > 0.001f) { yield return (object)new WaitForSeconds(num); if (version != _routeVersion) { yield break; } } int num2 = DropCarriedScrap(command); PlannedItems.Clear(); CarriedItems.Clear(); DroneThreats.Clear(); NextDroneHitByEnemy.Clear(); DestroyActiveGrenadeVisuals(); GameObject droneVisual = _droneVisual; _droneVisual = null; ClearDroneRendererCache(); _mode = DroneMode.NotSpawned; _droneGroundPosition = Vector3.zero; _droneIsInside = false; _isFollowingPlayer = false; _followSettled = false; _flashlightEnabled = false; ClearFollowPathCache(); ResetFollowMovementState(); if ((Object)(object)droneVisual != (Object)null) { Object.Destroy((Object)(object)droneVisual); } DisplayOwnerTip(command.PlayerId, (num2 > 0) ? $"Dropped {num2} scrap." : "Drone dismissed.", isWarning: false); } private static IEnumerator ReturnToShipRoutine(CourierCommand command, int version) { _mode = DroneMode.ReturningToShip; List route = BuildRouteToDrop(command, includeShipApproach: true); yield return MoveAlongRoute(command, route, version, pickUpAtEntrance: false); if (version == _routeVersion && !_lastRouteMoveBlocked) { CourierDroneRuntimeAssets.PlayLand(_droneVisual); _combatLandedUntil = Time.time + 0.35f; yield return (object)new WaitForSeconds(0.35f); if (version == _routeVersion) { int num = DropCarriedScrap(command); PlannedItems.Clear(); _mode = DroneMode.IdleAtPlayer; _droneGroundPosition = command.DropPosition; _droneIsInside = command.DropIsInFactory; _isFollowingPlayer = false; DisplayOwnerTip(command.PlayerId, (num > 0) ? $"Delivered {num} scrap." : "Returned empty.", num <= 0); CourierDroneRuntimeAssets.PlayLiftOff(_droneVisual); ApplyFlashlightState(_flashlightEnabled); _combatLandedUntil = 0f; } } } private static void StartIdleFollow(int version) { _followSettled = false; ClearFollowPathCache(); ResetFollowMovementState(); StartCoroutineOnAvailableHost(IdleFollowRoutine(version)); } private static IEnumerator IdleFollowRoutine(int version) { while (version == _routeVersion && _mode == DroneMode.IdleAtPlayer) { UpdateOwnerFollow(); yield return null; } _isFollowingPlayer = false; } private static IEnumerator GuardFollowRoutine(int version) { while (version == _routeVersion && _mode == DroneMode.GuardingPlayer) { UpdateOwnerFollow(); yield return TryGuardPickUpScrap(version); yield return null; } _isFollowingPlayer = false; } private static void UpdateOwnerFollow() { //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0184: 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_018b: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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) //IL_01a1: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_01e6: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_0201: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_0270: Unknown result type (might be due to invalid IL or missing references) //IL_0272: Unknown result type (might be due to invalid IL or missing references) //IL_0277: Unknown result type (might be due to invalid IL or missing references) //IL_0283: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_028e: Unknown result type (might be due to invalid IL or missing references) //IL_0293: 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_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02bb: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c2: Unknown result type (might be due to invalid IL or missing references) //IL_0222: 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_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_026b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null) { return; } if (_mode != DroneMode.IdleAtPlayer && _mode != DroneMode.GuardingPlayer) { _isFollowingPlayer = false; _followSettled = false; ClearFollowPathCache(); ResetFollowStuckState(); UpdateCarriedItemTransforms(); return; } PlayerControllerB val = ResolvePlayer(_ownerPlayerId); if ((Object)(object)val == (Object)null || val.isPlayerDead || (Object)(object)((Component)val).transform == (Object)null || val.isInsideFactory != _droneIsInside) { _isFollowingPlayer = false; _followSettled = false; ClearFollowPathCache(); ResetFollowStuckState(); UpdateCarriedItemTransforms(); return; } Vector3 val2 = CurrentDroneGroundPositionOr(_droneGroundPosition); Vector3 val3 = FindDroneFollowPosition(val); if (val2 == Vector3.zero || val3 == Vector3.zero) { _isFollowingPlayer = false; ResetFollowStuckState(); ApplyIdleSway(val2, val); UpdateCarriedItemTransforms(); return; } float num = Vector3.Distance(val2, val3); if (num > 28f) { _isFollowingPlayer = false; _followSettled = true; ClearFollowPathCache(); _droneGroundPosition = ResampleGroundPoint(val3, val3); _droneVisual.transform.position = ToFlightPosition(_droneGroundPosition); UpdateCarriedItemTransforms(); return; } if (_followSettled) { if (num <= 3.4f) { _isFollowingPlayer = false; ResetFollowStuckState(); ApplyIdleSway(val2, val); UpdateCarriedItemTransforms(); return; } _followSettled = false; } if (num <= 1.35f) { _isFollowingPlayer = false; _followSettled = true; ClearFollowPathCache(); ResetFollowStuckState(); ApplyIdleSway(val2, val); UpdateCarriedItemTransforms(); return; } _isFollowingPlayer = true; Vector3 val4 = SelectFollowWaypoint(GetFollowPath(val2, val3), val2, val3); if (val4 == Vector3.zero) { _isFollowingPlayer = false; UpdateFollowStuckRescue(val, val2, val2, num); ApplyIdleSway(val2, val); UpdateCarriedItemTransforms(); return; } float num2 = ((num > 8.5f) ? 10.54f : 6.8f); Vector3 candidate = Vector3.SmoothDamp(val2, val4, ref _followSmoothVelocity, 0.28f, num2, Time.deltaTime); candidate = ResampleGroundPoint(candidate, val2); Vector3 position = _droneVisual.transform.position; Vector3 val5 = ToSmoothedFlightPosition(candidate, position.y); if (TryResolveClutterMove(position, val5, candidate, out var adjustedFlight, out var blocked)) { val5 = adjustedFlight; candidate = ResampleGroundPoint(new Vector3(adjustedFlight.x, candidate.y, adjustedFlight.z), val2); if (blocked) { _followSmoothVelocity = Vector3.Lerp(_followSmoothVelocity, Vector3.zero, Mathf.Clamp01(Time.deltaTime * 2.5f)); } } Vector3 position2 = ApplyFlightBob(val5); _droneVisual.transform.position = position2; Vector3 val6 = val5 - position; FaceTravelDirection(_droneVisual.transform, val6.x, val6.y, val6.z); _droneGroundPosition = candidate; UpdateFollowStuckRescue(val, val2, _droneGroundPosition, num); UpdateCarriedItemTransforms(); } private static void UpdateFollowStuckRescue(PlayerControllerB owner, Vector3 previousGround, Vector3 currentGround, float distanceToTarget) { //IL_001f: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) if (_stuckRescueActive) { return; } if ((Object)(object)owner == (Object)null || (Object)(object)((Component)owner).transform == (Object)null || currentGround == Vector3.zero || _followSettled || distanceToTarget <= 1.35f) { ResetFollowStuckState(); } else if (Vector3.Distance(currentGround, ((Component)owner).transform.position) <= 6f) { ResetFollowStuckState(); } else if (_stuckWindowStartGround == Vector3.zero || _stuckWindowStartAt <= 0f) { _stuckWindowStartGround = ((previousGround != Vector3.zero) ? previousGround : currentGround); _stuckWindowStartAt = Time.time; } else { if (Time.time - _stuckWindowStartAt < 3f) { return; } if (Vector3.Distance(currentGround, _stuckWindowStartGround) >= 0.3f) { _stuckWindowStartGround = currentGround; _stuckWindowStartAt = Time.time; _stuckRepathIssued = false; return; } if (!_stuckRepathIssued) { ClearFollowPathCache(); _stuckRepathIssued = true; _stuckWindowStartGround = currentGround; _stuckWindowStartAt = Time.time; return; } Vector3 val = FindDroneFollowPosition(owner); if (val == Vector3.zero) { _stuckWindowStartGround = currentGround; _stuckWindowStartAt = Time.time; } else { StartCoroutineOnAvailableHost(StuckRescueRelocateRoutine(val, _routeVersion)); _stuckWindowStartGround = currentGround; _stuckWindowStartAt = Time.time; } } } private static IEnumerator StuckRescueRelocateRoutine(Vector3 rescueGround, int version) { //IL_0007: 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) if ((Object)(object)_droneVisual == (Object)null || rescueGround == Vector3.zero) { yield break; } _stuckRescueActive = true; float num = CourierDroneRuntimeAssets.PlayDematerializeOut(_droneVisual); if (num > 0.001f) { yield return (object)new WaitForSeconds(num); } if ((Object)(object)_droneVisual == (Object)null || version != _routeVersion) { _stuckRescueActive = false; yield break; } Vector3 val = ResampleGroundPoint(rescueGround, rescueGround); if (val != Vector3.zero) { _droneGroundPosition = val; _droneVisual.transform.position = ToFlightPosition(val); _followSmoothVelocity = Vector3.zero; _dynamicHoverHeight = 0.95f; ClearFollowPathCache(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"Courier Drone stuck-rescue at {val}"); } CourierDroneRuntimeAssets.PlayMaterializeIn(_droneVisual); } ResetFollowStuckState(); _stuckRescueActive = false; } private static IEnumerator TryGuardPickUpScrap(int version) { if (!((Object)(object)_droneVisual == (Object)null) && version == _routeVersion && _mode == DroneMode.GuardingPlayer && !IsCargoWeightFull() && !(Time.time < _nextGuardScrapScanAt)) { _nextGuardScrapScanAt = Time.time + 0.8f; GrabbableObject val = FindGuardPickupTarget(); if (!((Object)(object)val == (Object)null)) { PlayerControllerB player = ResolvePlayer(_ownerPlayerId); Vector3 dropPosition = BuildCommandContext(player)?.DropPosition ?? FindShipDropPosition(player); CourierItemMove itemMove = new CourierItemMove(((NetworkBehaviour)val).NetworkObjectId, ((Component)val).transform.position, dropPosition, val.isInFactory); yield return MagnetPickUpScrap(itemMove, itemMove.PickupIsInFactory, val, version); } } } private static GrabbableObject FindGuardPickupTarget() { //IL_0006: 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_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) Vector3 val = CurrentDroneGroundPositionOr(_droneGroundPosition); if (val == Vector3.zero) { return null; } List searchPositions = new List(); AddRoutePoint(searchPositions, val); PlayerControllerB val2 = ResolvePlayer(_ownerPlayerId); if ((Object)(object)val2 != (Object)null && !val2.isPlayerDead && (Object)(object)((Component)val2).transform != (Object)null) { AddRoutePoint(searchPositions, FindDroneFollowPosition(val2)); } GrabbableObject[] array = ScanGrabbableObjectsForCommandOrSweep(); Array.Sort(array, delegate(GrabbableObject a, GrabbableObject b) { //IL_000f: 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) float num2 = (((Object)(object)a == (Object)null) ? float.MaxValue : DistanceToClosestPointSqr(((Component)a).transform.position, searchPositions)); float value = (((Object)(object)b == (Object)null) ? float.MaxValue : DistanceToClosestPointSqr(((Component)b).transform.position, searchPositions)); return num2.CompareTo(value); }); float radiusSqr = 36f; float carriedCargoWeightPounds = GetCarriedCargoWeightPounds(); foreach (GrabbableObject val3 in array) { if (IsCourierEligibleEntranceScrap(val3, searchPositions, radiusSqr) && val3.isInFactory == _droneIsInside && !IsAlreadyCarried(((NetworkBehaviour)val3).NetworkObjectId) && !IsAlreadyPlanned(((NetworkBehaviour)val3).NetworkObjectId) && !WouldExceedCargoWeight(val3, carriedCargoWeightPounds)) { return val3; } } return null; } private static IEnumerator WaitAtEntranceRoutine(CourierCommand command, int version) { while (version == _routeVersion && _mode == DroneMode.AtEntrance) { ApplyIdleSway(CurrentDroneGroundPositionOr(command.InsideEntrancePosition), ResolvePlayer(_ownerPlayerId)); UpdateCarriedItemTransforms(); Vector3 scanPoint = (_droneIsInside ? CurrentDroneGroundPositionOr(command.InsideEntrancePosition) : command.OutsideEntrancePosition); if (scanPoint == Vector3.zero) { scanPoint = command.EntrancePosition; } AddFreshEntranceScrapPlans(command, scanPoint); yield return TryPickUpScrapAtPoint(command, scanPoint, version); if (!_reportedNoEntranceScrap && CarriedItems.Count == 0 && PlannedItems.Count == 0) { _reportedNoEntranceScrap = true; DisplayOwnerTip(command.PlayerId, "No scrap near entrance yet.", isWarning: false); } if (IsCargoWeightFull()) { DisplayOwnerTip(command.PlayerId, "Cargo weight full. Returning to ship.", isWarning: false); command.Type = CourierCommandType.ReturnToShip; StartReturnToShip(command); break; } float elapsed = 0f; while (elapsed < 0.8f) { if (version != _routeVersion || _mode != DroneMode.AtEntrance) { yield break; } ApplyIdleSway(CurrentDroneGroundPositionOr(scanPoint), ResolvePlayer(_ownerPlayerId)); UpdateCarriedItemTransforms(); elapsed += Time.deltaTime; yield return null; } } } private static void AddFreshEntranceScrapPlans(CourierCommand command, Vector3 scanPoint) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (command == null || IsCargoWeightFull() || Time.time < _nextEntranceScrapScanAt) { return; } _nextEntranceScrapScanAt = Time.time + 0.8f; List list = new List(); AddRoutePoint(list, scanPoint); List list2 = FindEntranceScrap(command, list); for (int i = 0; i < list2.Count; i++) { CourierItemMove item = list2[i]; if (!IsAlreadyCarried(item.NetworkObjectId) && !IsAlreadyPlanned(item.NetworkObjectId)) { PlannedItems.Add(item); } } } private static IEnumerator MoveAlongRoute(CourierCommand command, List route, int version, bool pickUpAtEntrance) { if ((Object)(object)_droneVisual == (Object)null || route.Count == 0) { yield break; } _lastRouteMoveBlocked = false; _droneGroundPosition = route[0]; Vector3 previousPosition = _droneVisual.transform.position; for (int i = 1; i < route.Count; i++) { if (version != _routeVersion) { break; } if (_lastRouteMoveBlocked) { break; } Vector3 val = route[i - 1]; Vector3 to = route[i]; if (IsEntranceTransition(command, val, to)) { _droneVisual.SetActive(false); yield return (object)new WaitForSeconds(0.16f); _droneVisual.transform.position = ToFlightPosition(to); previousPosition = _droneVisual.transform.position; _droneGroundPosition = to; _droneIsInside = IsSameRoutePoint(to, command.InsideEntrancePosition); UpdateCarriedItemTransforms(); _droneVisual.SetActive(true); yield return (object)new WaitForSeconds(0.08f); } else { List path = BuildNavMeshPath(val, to); for (int p = 1; p < path.Count; p++) { if (version != _routeVersion) { yield break; } yield return MoveDroneSegment(path[p - 1], path[p], previousPosition.x, previousPosition.y, previousPosition.z, version); if (_lastRouteMoveBlocked) { yield break; } previousPosition = _droneVisual.transform.position; } previousPosition = _droneVisual.transform.position; Vector3 val2 = _droneGroundPosition - to; if (((Vector3)(ref val2)).sqrMagnitude <= 0.25f) { _droneGroundPosition = ResampleGroundPoint(to, _droneGroundPosition); } } if (pickUpAtEntrance && IsMainEntrancePoint(command, to)) { yield return TryPickUpScrapAtPoint(command, to, version); yield return (object)new WaitForSeconds(0.75f); } } } private static IEnumerator MoveDroneSegment(Vector3 fromGround, Vector3 toGround, float previousX, float previousY, float previousZ, int version) { //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(previousX, previousY, previousZ); Vector3 val2 = ResampleGroundPoint(fromGround, fromGround); Vector3 endGround = ResampleGroundPoint(toGround, toGround); Vector3 val3 = ToFlightPosition(val2); Vector3 end = ToFlightPosition(endGround); float num = Mathf.Max(Vector3.Distance(val3, end) / 10.5f, 0.2f); float maxDuration = Mathf.Max(num * 2.25f, num + 1.2f); float elapsed = 0f; Vector3 previousBasePosition = val; Vector3 routeSmoothVelocity = Vector3.zero; Vector3 currentGround = ((_droneGroundPosition != Vector3.zero) ? _droneGroundPosition : val2); _lastRouteMoveBlocked = false; Vector3 val4; while (elapsed < maxDuration) { if (version != _routeVersion) { yield break; } val4 = currentGround - endGround; if (((Vector3)(ref val4)).sqrMagnitude <= 0.04f) { break; } Vector3 candidate = Vector3.SmoothDamp(currentGround, endGround, ref routeSmoothVelocity, 0.28f, 10.5f, Time.deltaTime); candidate = ResampleGroundPoint(candidate, currentGround); Vector3 val5 = ToSmoothedFlightPosition(candidate, previousBasePosition.y); if (TryResolveClutterMove(previousBasePosition, val5, candidate, out var adjustedFlight, out var blocked)) { val5 = adjustedFlight; candidate = ResampleGroundPoint(new Vector3(adjustedFlight.x, candidate.y, adjustedFlight.z), currentGround); if (blocked) { routeSmoothVelocity = Vector3.Lerp(routeSmoothVelocity, Vector3.zero, Mathf.Clamp01(Time.deltaTime * 2.5f)); } } Vector3 val6 = ApplyFlightBob(val5); _droneVisual.transform.position = val6; Vector3 val7 = val5 - previousBasePosition; FaceTravelDirection(_droneVisual.transform, val7.x, val7.y, val7.z); _droneGroundPosition = candidate; UpdateCarriedItemTransforms(); val = val6; previousBasePosition = val5; currentGround = candidate; elapsed += Time.deltaTime; yield return null; } Vector3 val8 = end; if (TryResolveClutterMove(previousBasePosition, val8, endGround, out var adjustedFlight2, out var blocked2)) { val8 = adjustedFlight2; endGround = ResampleGroundPoint(new Vector3(val8.x, endGround.y, val8.z), (_droneGroundPosition != Vector3.zero) ? _droneGroundPosition : endGround); int lastRouteMoveBlocked; if (!blocked2) { val4 = endGround - toGround; lastRouteMoveBlocked = ((((Vector3)(ref val4)).sqrMagnitude > 0.25f) ? 1 : 0); } else { lastRouteMoveBlocked = 1; } _lastRouteMoveBlocked = (byte)lastRouteMoveBlocked != 0; } _droneVisual.transform.position = val8; _droneGroundPosition = endGround; UpdateCarriedItemTransforms(); yield return (object)new WaitForSeconds(0.05f); } private static List BuildRouteToEntrance(CourierCommand command) { //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_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) List list = new List(); AddRoutePoint(list, CurrentDroneGroundPositionOr(command.DroneStartPosition)); Vector3 point = FirstNonZero(command.InsideEntrancePosition, command.EntrancePosition); Vector3 point2 = FirstNonZero(command.OutsideEntrancePosition, command.EntrancePosition); if (_droneIsInside) { AddRoutePoint(list, point); } else { AddRoutePoint(list, point2); AddRoutePoint(list, point); } return list; } private static List BuildRouteToDrop(CourierCommand command, bool includeShipApproach) { //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_0073: 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_0067: 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_0053: 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_0039: Unknown result type (might be due to invalid IL or missing references) List list = new List(); AddRoutePoint(list, CurrentDroneGroundPositionOr(command.DroneStartPosition)); if (_droneIsInside != command.DropIsInFactory) { if (_droneIsInside) { AddRoutePoint(list, command.InsideEntrancePosition); AddRoutePoint(list, command.OutsideEntrancePosition); } else { AddRoutePoint(list, command.OutsideEntrancePosition); AddRoutePoint(list, command.InsideEntrancePosition); } } if (includeShipApproach) { AddRoutePoint(list, FindShipApproachPosition(command.DropPosition)); } AddRoutePoint(list, command.DropPosition); return list; } private static List BuildNavMeshPath(Vector3 from, Vector3 to) { //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) List list = new List(); AddRoutePoint(list, from); if (TryCalculateNavMeshPath(from, to, out var corners)) { for (int i = 0; i < corners.Length; i++) { AddRoutePoint(list, corners[i]); } } AddRoutePoint(list, to); return list; } private static List GetFollowPath(Vector3 from, Vector3 to) { //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) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_0061: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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_007f: Unknown result type (might be due to invalid IL or missing references) int num; if (!(_cachedFollowPathTarget == Vector3.zero)) { Vector3 val = _cachedFollowPathTarget - to; num = ((((Vector3)(ref val)).sqrMagnitude > 4f) ? 1 : 0); } else { num = 1; } bool flag = (byte)num != 0; bool flag2 = Time.time >= _nextFollowRepathAt; if (CachedFollowPath.Count == 0 || flag || flag2) { CachedFollowPath.Clear(); AddRoutePoint(CachedFollowPath, from); if (TryCalculateNavMeshPath(from, to, out var corners)) { for (int i = 0; i < corners.Length; i++) { AddRoutePoint(CachedFollowPath, corners[i]); } } else if (CanMoveDirectToFollowTarget(from, to)) { AddRoutePoint(CachedFollowPath, to); } _cachedFollowPathTarget = to; _nextFollowRepathAt = Time.time + 0.5f; } TrimFollowPath(from); return CachedFollowPath; } private static Vector3 SelectFollowWaypoint(List path, Vector3 currentGround, Vector3 fallbackTarget) { //IL_000c: 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_001b: 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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_004a: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (path == null || path.Count <= 1) { if (!CanMoveDirectToFollowTarget(currentGround, fallbackTarget)) { return Vector3.zero; } return fallbackTarget; } TrimFollowPath(currentGround); for (int num = path.Count - 1; num >= 1; num--) { Vector3 val = path[num]; if (!(val == Vector3.zero)) { Vector3 val2 = val - currentGround; if (!(((Vector3)(ref val2)).sqrMagnitude > 64f) && CanReachWaypointAtHoverHeight(currentGround, val)) { return val; } } } int num2 = 1; if (path.Count <= num2) { return Vector3.zero; } return path[num2]; } private static void TrimFollowPath(Vector3 currentGround) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) float num = 0.45562503f; while (CachedFollowPath.Count > 2) { Vector3 val = CachedFollowPath[1] - currentGround; if (((Vector3)(ref val)).sqrMagnitude <= num) { CachedFollowPath.RemoveAt(0); continue; } break; } } private static void ClearFollowPathCache() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) CachedFollowPath.Clear(); _cachedFollowPathTarget = Vector3.zero; _nextFollowRepathAt = 0f; } private static void ResetFollowMovementState() { //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) _followSmoothVelocity = Vector3.zero; _nextHoverProbeAt = 0f; _dynamicHoverHeight = 0.95f; _nextCollisionRepathAt = 0f; ResetFollowStuckState(); } private static void ResetFollowStuckState() { //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) _stuckWindowStartGround = Vector3.zero; _stuckWindowStartAt = 0f; _stuckRepathIssued = false; } private static bool TryCalculateNavMeshPath(Vector3 from, Vector3 to, out Vector3[] corners) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_002f: 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_0045: Unknown result type (might be due to invalid IL or missing references) corners = null; NavMeshHit val = default(NavMeshHit); if (!NavMesh.SamplePosition(from, ref val, 8f, -1)) { return false; } NavMeshHit val2 = default(NavMeshHit); if (!NavMesh.SamplePosition(to, ref val2, 8f, -1)) { return false; } NavMeshPath val3 = new NavMeshPath(); if (!NavMesh.CalculatePath(((NavMeshHit)(ref val)).position, ((NavMeshHit)(ref val2)).position, -1, val3) || (int)val3.status != 0 || val3.corners == null || val3.corners.Length < 2) { return false; } corners = val3.corners; return true; } private static IEnumerator TryPickUpScrapAtPoint(CourierCommand command, Vector3 routePoint, int version) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null || IsCargoWeightFull()) { yield break; } List searchPositions = new List(); AddRoutePoint(searchPositions, routePoint); if (searchPositions.Count == 0) { searchPositions = FindMainEntranceSearchPositions(command); } float radiusSqr = 100f; for (int i = 0; i < PlannedItems.Count; i++) { if (version != _routeVersion) { break; } if (_mode == DroneMode.FlyingToPlayer) { break; } if (IsCargoWeightFull()) { break; } CourierItemMove itemMove = PlannedItems[i]; if (IsAlreadyCarried(itemMove.NetworkObjectId) || itemMove.PickupIsInFactory != _droneIsInside) { continue; } GrabbableObject item = ResolveItem(itemMove.NetworkObjectId); if (IsCourierEligibleEntranceScrap(item, searchPositions, radiusSqr)) { if (WouldExceedCargoWeight(item, GetCarriedCargoWeightPounds())) { PlannedItems.RemoveAt(i); i--; } else { yield return MagnetPickUpScrap(itemMove, itemMove.PickupIsInFactory, item, version); } } } } private static IEnumerator MagnetPickUpScrap(CourierItemMove itemMove, bool pickupWasInside, GrabbableObject item, int version) { if ((Object)(object)_droneVisual == (Object)null || (Object)(object)item == (Object)null || version != _routeVersion || WouldExceedCargoWeight(item, GetCarriedCargoWeightPounds())) { yield break; } _magnetPickupActive = true; Vector3 itemGroundPosition = ((Component)item).transform.position; Vector3 end = itemGroundPosition + Vector3.up * 0.78f; yield return MoveDroneVisualPosition(_droneVisual.transform.position, end, 0.35f, version); if (_lastRouteMoveBlocked) { _magnetPickupActive = false; yield break; } if ((Object)(object)_droneVisual == (Object)null || (Object)(object)item == (Object)null || version != _routeVersion) { _magnetPickupActive = false; yield break; } if (WouldExceedCargoWeight(item, GetCarriedCargoWeightPounds())) { _magnetPickupActive = false; yield break; } CourierDroneRuntimeAssets.StartMagnetSound(_droneVisual); item.EnablePhysics(false); bool bodyWasKinematic = (Object)(object)item.propBody != (Object)null && item.propBody.isKinematic; bool bodyUsedGravity = (Object)(object)item.propBody != (Object)null && item.propBody.useGravity; SetItemKinematic(item, isKinematic: true, useGravity: false); Vector3 attachLocal = new Vector3(0.38f * ((CarriedItems.Count % 2 == 0) ? (-0.5f) : 0.5f), -0.55f - 0.22f * (float)(CarriedItems.Count / 2), -0.12f); Vector3 itemStart = ((Component)item).transform.position; Vector3 itemEnd = GetCarryWorldPosition(attachLocal); float elapsed = 0f; while (elapsed < 0.55f) { if (version != _routeVersion) { CourierDroneRuntimeAssets.StopMagnetSound(_droneVisual); _magnetPickupActive = false; yield break; } float num = Mathf.SmoothStep(0f, 1f, elapsed / 0.55f); if ((Object)(object)item != (Object)null) { ((Component)item).transform.position = Vector3.Lerp(itemStart, itemEnd, num); } elapsed += Time.deltaTime; yield return null; } if ((Object)(object)item == (Object)null || (Object)(object)_droneVisual == (Object)null) { CourierDroneRuntimeAssets.StopMagnetSound(_droneVisual); _magnetPickupActive = false; yield break; } Vector3 lossyScale = ((Component)item).transform.lossyScale; Quaternion carryLocalRotation = Quaternion.Inverse(_droneVisual.transform.rotation) * ((Component)item).transform.rotation; ((Component)item).transform.SetParent((Transform)null, true); item.parentObject = null; item.isHeld = false; item.isPocketed = false; item.isHeldByEnemy = false; item.playerHeldBy = null; item.grabbable = false; item.grabbableToEnemies = false; SetWorldScale(((Component)item).transform, lossyScale); CarriedItems.Add(new CarriedCourierItem(itemMove, item, lossyScale, attachLocal, carryLocalRotation, bodyWasKinematic, bodyUsedGravity)); UpdateCarriedItemTransforms(); _droneGroundPosition = itemGroundPosition; _droneIsInside = pickupWasInside; yield return MoveDroneVisualPosition(_droneVisual.transform.position, ToFlightPosition(itemGroundPosition), 0.25f, version); _ = _lastRouteMoveBlocked; CourierDroneRuntimeAssets.StopMagnetSound(_droneVisual); _magnetPickupActive = false; } private static IEnumerator MoveDroneVisualPosition(Vector3 start, Vector3 end, float duration, int version) { //IL_0007: 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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) float elapsed = 0f; Vector3 previous = start; _lastRouteMoveBlocked = false; while (elapsed < duration) { if ((Object)(object)_droneVisual == (Object)null || version != _routeVersion) { yield break; } float num = Mathf.SmoothStep(0f, 1f, elapsed / Mathf.Max(duration, 0.01f)); Vector3 val = Vector3.Lerp(start, end, num); Vector3 nextGround = ResampleGroundPoint(new Vector3(val.x, _droneGroundPosition.y, val.z), _droneGroundPosition); if (TryResolveClutterMove(previous, val, nextGround, out var adjustedFlight, out var blocked)) { val = adjustedFlight; _lastRouteMoveBlocked = blocked; } _droneVisual.transform.position = val; Vector3 val2 = val - previous; FaceTravelDirection(_droneVisual.transform, val2.x, val2.y, val2.z); UpdateCarriedItemTransforms(); previous = val; if (_lastRouteMoveBlocked) { yield break; } elapsed += Time.deltaTime; yield return null; } if ((Object)(object)_droneVisual != (Object)null && version == _routeVersion) { Vector3 val3 = end; Vector3 nextGround2 = ResampleGroundPoint(new Vector3(val3.x, _droneGroundPosition.y, val3.z), _droneGroundPosition); if (TryResolveClutterMove(previous, val3, nextGround2, out var adjustedFlight2, out var blocked2)) { val3 = adjustedFlight2; _lastRouteMoveBlocked = blocked2; } _droneVisual.transform.position = val3; UpdateCarriedItemTransforms(); } } private static int DropCarriedScrap(CourierCommand command) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: 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_0060: Unknown result type (might be due to invalid IL or missing references) int num = 0; for (int i = 0; i < CarriedItems.Count; i++) { CarriedCourierItem carriedCourierItem = CarriedItems[i]; if (!((Object)(object)carriedCourierItem.Item == (Object)null)) { Vector3 dropPosition = command.DropPosition + new Vector3(0.28f * (float)(i % 3 - 1), 1.15f, 0.28f * (float)(i / 3)); MoveScrapToPlayer(carriedCourierItem.Item, dropPosition, command.DropIsInShip, command.DropIsInFactory, carriedCourierItem.WorldScale, carriedCourierItem.BodyWasKinematic, carriedCourierItem.BodyUsedGravity, command.PlayerId); num++; } } CarriedItems.Clear(); return num; } private static int DropCarriedScrapAtDrone() { //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_000c: 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_000e: 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_0040: 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_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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) int num = 0; Vector3 val = CurrentDroneGroundPositionOr(_droneGroundPosition); if (val == Vector3.zero && (Object)(object)_droneVisual != (Object)null) { val = ResampleGroundPoint(_droneVisual.transform.position, Vector3.zero); } for (int i = 0; i < CarriedItems.Count; i++) { CarriedCourierItem carriedCourierItem = CarriedItems[i]; if (!((Object)(object)carriedCourierItem.Item == (Object)null)) { Vector3 dropPosition = val + new Vector3(0.35f * (float)(i % 3 - 1), 1f, 0.35f * (float)(i / 3)); MoveScrapToPlayer(carriedCourierItem.Item, dropPosition, dropIsInShip: false, _droneIsInside, carriedCourierItem.WorldScale, carriedCourierItem.BodyWasKinematic, carriedCourierItem.BodyUsedGravity, _ownerPlayerId); num++; } } CarriedItems.Clear(); return num; } private static void ResetDroneHealthForRound() { _droneHealth = 30; _droneDestroyedThisRound = false; _nextEnemyScanAt = 0f; _lastEnemyScanFrame = -1; _lastEnemyFacingFrame = -1; _nextFlameAt = 0f; _nextGrenadeAt = 0f; _combatLandedUntil = 0f; _nextGuardScrapScanAt = 0f; _magnetPickupActive = false; ClearPointerTargetState(); DroneThreats.Clear(); NextDroneHitByEnemy.Clear(); } private static bool CanDroneBeDamaged() { if (!_droneDestroyedThisRound && _droneHealth > 0 && (Object)(object)_droneVisual != (Object)null && _droneVisual.activeInHierarchy) { return _mode != DroneMode.NotSpawned; } return false; } internal static void NotifyDroneAttackedEnemy(EnemyAI enemy) { if (IsServerAuthority() && !((Object)(object)enemy == (Object)null) && !enemy.isEnemyDead && CanDroneBeDamaged() && EnemySharesDroneSpace(enemy)) { MarkDroneThreat(enemy, 8f); } } private static void UpdateEnemyDroneAggroScanOncePerFrame() { if (_lastEnemyScanFrame == Time.frameCount) { return; } _lastEnemyScanFrame = Time.frameCount; if (Time.time < _nextEnemyScanAt) { return; } _nextEnemyScanAt = Time.time + 0.25f; if (!IsServerAuthority() || !CanDroneBeDamaged()) { return; } RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null) { return; } for (int i = 0; i < instance.SpawnedEnemies.Count; i++) { EnemyAI val = instance.SpawnedEnemies[i]; if ((Object)(object)val != (Object)null) { UpdateEnemyDroneAggro(val); } } UpdateDroneCombat(instance.SpawnedEnemies); } private static void UpdateEnemyDroneFacingOncePerFrame() { if (_lastEnemyFacingFrame == Time.frameCount) { return; } _lastEnemyFacingFrame = Time.frameCount; if (IsServerAuthority() && CanDroneBeDamaged()) { RoundManager instance = RoundManager.Instance; if (!((Object)(object)instance == (Object)null) && instance.SpawnedEnemies != null) { RotateEnemyThreatsTowardDrone(instance.SpawnedEnemies); } } } private static void RotateEnemyThreatsTowardDrone(List enemies) { //IL_0004: 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_000a: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: 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_00da: Unknown result type (might be due to invalid IL or missing references) if (enemies == null) { return; } Vector3 droneCombatPosition = GetDroneCombatPosition(); if (droneCombatPosition == Vector3.zero) { return; } float num = 3.1499999f * 3.1499999f; for (int i = 0; i < enemies.Count; i++) { EnemyAI val = enemies[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !((Object)(object)((Component)val).transform == (Object)null) && EnemySharesDroneSpace(val) && IsDroneThreat(val) && !PlayerHasPriorityOverDrone(val, droneCombatPosition)) { Vector3 val2 = droneCombatPosition - ((Component)val).transform.position; val2.y = 0f; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude <= 0.001f) && !(sqrMagnitude > num)) { Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); ((Component)val).transform.rotation = Quaternion.RotateTowards(((Component)val).transform.rotation, val3, 360f * Time.deltaTime); } } } } private static void UpdateEnemyDroneAggro(EnemyAI enemy) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) if (!IsServerAuthority() || (Object)(object)enemy == (Object)null || enemy.isEnemyDead || !CanDroneBeDamaged() || !EnemySharesDroneSpace(enemy)) { return; } Vector3 droneTargetPosition = GetDroneTargetPosition(); if (!(droneTargetPosition == Vector3.zero)) { Vector3 val = ((Component)enemy).transform.position - droneTargetPosition; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude <= 25f) { MarkDroneThreat(enemy, 2.5f); } if (IsDroneThreat(enemy) && sqrMagnitude <= 4.4099994f) { TryEnemyContactDamageDrone(enemy); } } } private static void UpdateDroneCombat(List enemies) { //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_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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_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_0107: 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_013f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) if (!CanDroneUseCombat() || enemies == null) { return; } int num = ResolveCombatTier(); if (num < 1) { return; } Vector3 droneCombatPosition = GetDroneCombatPosition(); Vector3 droneCombatOrigin = GetDroneCombatOrigin(); if (droneCombatPosition == Vector3.zero || droneCombatOrigin == Vector3.zero) { return; } EnemyAI val = null; float num2 = 12.25f; EnemyAI val2 = null; Vector3 targetPosition = Vector3.zero; float num3 = 324f; bool flag = Time.time >= _nextFlameAt; bool flag2 = num >= 2 && Time.time >= _nextGrenadeAt; Transform val3 = (flag2 ? ResolveGrenadeMuzzle() : null); Vector3 val4 = (((Object)(object)val3 != (Object)null) ? val3.position : droneCombatOrigin); if (TryUsePriorityCombatTarget(num, droneCombatOrigin, droneCombatPosition, val4, flag, flag2)) { return; } for (int i = 0; i < enemies.Count; i++) { EnemyAI val5 = enemies[i]; if (!IsCombatEligibleEnemy(val5)) { continue; } Vector3 val6 = ResolveEnemyCenter(val5); if (val6 == Vector3.zero) { continue; } Vector3 val7 = val6 - droneCombatPosition; float sqrMagnitude = ((Vector3)(ref val7)).sqrMagnitude; if (flag && sqrMagnitude <= num2 && HasDroneLineOfSight(droneCombatOrigin, val6)) { num2 = sqrMagnitude; val = val5; } if (flag2) { val7 = val6 - val4; float sqrMagnitude2 = ((Vector3)(ref val7)).sqrMagnitude; if (!(sqrMagnitude2 < 64f) && !(sqrMagnitude2 > num3) && HasDroneLineOfSight(val4, val6) && !IsPlayerInGrenadeDanger(val6)) { num3 = sqrMagnitude2; val2 = val5; targetPosition = val6; } } } if ((Object)(object)val != (Object)null) { FireDroneFlame(manualMode: false); } else if ((Object)(object)val2 != (Object)null) { FireDroneGrenade(targetPosition); } } private static bool TryUsePriorityCombatTarget(int tier, Vector3 origin, Vector3 dronePosition, Vector3 grenadeOrigin, bool canFlame, bool canGrenade) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0027: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0045: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) EnemyAI val = ResolvePriorityTarget(); if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = ResolveEnemyCenter(val); if (val2 == Vector3.zero) { return true; } Vector3 val3 = val2 - dronePosition; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (canFlame && sqrMagnitude <= 12.25f && HasDroneLineOfSight(origin, val2)) { FireDroneFlame(manualMode: false); return true; } if (!canGrenade || tier < 2) { return true; } val3 = val2 - grenadeOrigin; float sqrMagnitude2 = ((Vector3)(ref val3)).sqrMagnitude; if (sqrMagnitude2 < 64f || sqrMagnitude2 > 324f) { return true; } if (!HasDroneLineOfSight(grenadeOrigin, val2)) { return true; } if (IsPlayerInGrenadeDanger(val2)) { return true; } FireDroneGrenade(val2); return true; } private static EnemyAI ResolvePriorityTarget() { if (_priorityTargetId == 0L) { return null; } if (Time.time > _priorityTargetExpiresAt) { ClearPriorityTargetOnly(); return null; } EnemyAI val = ResolveEnemy(_priorityTargetId); if (!IsCombatEligibleEnemy(val)) { ClearPriorityTargetOnly(); return null; } return val; } private static bool CanDroneUseCombat() { if (IsServerAuthority() && CanDroneBeDamaged() && _mode != DroneMode.ManualControl && Time.time >= _combatLandedUntil && (Object)(object)_droneVisual != (Object)null) { return _droneVisual.activeInHierarchy; } return false; } private static bool CanDroneUseManualCombat() { if (IsServerAuthority() && CanDroneBeDamaged() && _mode == DroneMode.ManualControl && Time.time >= _combatLandedUntil && !_magnetPickupActive && (Object)(object)_droneVisual != (Object)null) { return _droneVisual.activeInHierarchy; } return false; } private static int ResolveCombatTier() { if (_ownerCourierTier <= 0) { return CourierDroneUpgrade.GetTier(); } return _ownerCourierTier; } private static bool IsCombatEligibleEnemy(EnemyAI enemy) { if ((Object)(object)enemy != (Object)null && !enemy.isEnemyDead && (Object)(object)((Component)enemy).transform != (Object)null) { return EnemySharesDroneSpace(enemy); } return false; } private static void FireDroneFlame(bool manualMode) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) _nextFlameAt = Time.time + 5f; Vector3 droneCombatPosition = GetDroneCombatPosition(); PlayDroneFlameLocal(droneCombatPosition); BroadcastDroneFlame(droneCombatPosition); StartCoroutineOnAvailableHost(FlameDamageRoutine(_routeVersion, manualMode)); } private static IEnumerator FlameDamageRoutine(int version, bool manualMode) { float tickDelay = 0.4f; for (int tick = 0; tick < 3; tick++) { if (version != _routeVersion) { break; } if (!(manualMode ? CanDroneUseManualCombat() : CanDroneUseCombat())) { break; } ApplyFlameDamageTick(); if (tick < 2 && tickDelay > 0f) { yield return (object)new WaitForSeconds(tickDelay); } } } private static void ApplyFlameDamageTick() { //IL_0018: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_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_006f: 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_0088: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) RoundManager instance = RoundManager.Instance; if ((Object)(object)instance == (Object)null || instance.SpawnedEnemies == null) { return; } Vector3 droneCombatPosition = GetDroneCombatPosition(); float num = 10.240001f; PlayerControllerB val = ResolveCombatOwner(); for (int i = 0; i < instance.SpawnedEnemies.Count; i++) { EnemyAI val2 = instance.SpawnedEnemies[i]; if (!IsCombatEligibleEnemy(val2)) { continue; } Vector3 val3 = ResolveEnemyCenter(val2); Vector3 val4 = val3 - droneCombatPosition; if (!(((Vector3)(ref val4)).sqrMagnitude > num)) { val4 = val3 - droneCombatPosition; Vector3 val5; if (!(((Vector3)(ref val4)).sqrMagnitude > 0.001f)) { val5 = Vector3.up; } else { val4 = val3 - droneCombatPosition; val5 = ((Vector3)(ref val4)).normalized; } Vector3 val6 = val5; val2.HitEnemyOnLocalClient(1, val6, val, false, 74043); NotifyDroneAttackedEnemy(val2); } } } private static void FireDroneGrenade(Vector3 targetPosition) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_001c: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0063: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) Transform val = ResolveGrenadeMuzzle(); Vector3 start = (((Object)(object)val != (Object)null) ? val.position : GetDroneCombatOrigin()); Vector3 val2 = CalculateGrenadeVelocity(start, targetPosition); if (!(val2 == Vector3.zero)) { _nextGrenadeAt = Time.time + 8f; int grenadeId = _nextGrenadeId++; if (_nextGrenadeId == int.MaxValue) { _nextGrenadeId = 1; } PlayGrenadeLaunchLocal(grenadeId, start, val2); BroadcastGrenadeLaunch(grenadeId, start, val2); StartCoroutineOnAvailableHost(GrenadeDetonationRoutine(grenadeId, start, val2)); } } private static bool HandleManualFireRequest(int playerId, ManualFireKind fireKind, Vector3 targetPosition) { //IL_0064: 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_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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (!CanDroneUseManualCombat() || playerId != _ownerPlayerId) { return false; } int num = ResolveCombatTier(); switch (fireKind) { case ManualFireKind.Flame: if (num < 1 || Time.time < _nextFlameAt) { return false; } FireDroneFlame(manualMode: true); return true; case ManualFireKind.Grenade: { if (num < 2 || Time.time < _nextGrenadeAt) { return false; } Transform val = ResolveGrenadeMuzzle(); Vector3 val2 = (((Object)(object)val != (Object)null) ? val.position : GetDroneCombatOrigin()); if (val2 == Vector3.zero) { return false; } FireDroneGrenade(ClampManualGrenadeTarget(val2, targetPosition)); return true; } default: return false; } } private static IEnumerator GrenadeDetonationRoutine(int grenadeId, Vector3 start, Vector3 velocity) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float elapsed = 0f; Vector3 previous = start; Vector3 detonation = start; int mask = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); RaycastHit val3 = default(RaycastHit); while (elapsed < 2.5f) { elapsed += Time.deltaTime; Vector3 val = EvaluateGrenadePosition(start, velocity, elapsed); Vector3 val2 = val - previous; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude > 0.001f && Physics.SphereCast(previous, 0.18f, ((Vector3)(ref val2)).normalized, ref val3, magnitude, mask, (QueryTriggerInteraction)1)) { detonation = ((RaycastHit)(ref val3)).point; DetonateDroneGrenade(grenadeId, detonation); yield break; } previous = val; detonation = val; yield return null; } DetonateDroneGrenade(grenadeId, detonation); } private static void DetonateDroneGrenade(int grenadeId, Vector3 position) { //IL_0001: 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_000e: Unknown result type (might be due to invalid IL or missing references) PlayGrenadeExplosionLocal(grenadeId, position); BroadcastGrenadeExplosion(grenadeId, position); try { Landmine.SpawnExplosion(position, false, 3f, 5.5f, 50, 0f, (GameObject)null, false); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"Courier Drone grenade Landmine.SpawnExplosion threw: {arg}"); } } } private static Vector3 CalculateGrenadeVelocity(Vector3 start, Vector3 target) { //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_000a: 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_004d: 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_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) Vector3 val = target - start; Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(val.x, 0f, val.z); float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude <= 0.001f) { return Vector3.zero; } float num = Mathf.Clamp(magnitude / 15.5f, 0.75f, 2.05f); Vector3 val3 = Random.insideUnitSphere * 0.45f; val3.y = Mathf.Abs(val3.y) * 0.25f; return (target + val3 - start - 0.5f * Physics.gravity * num * num) / num; } private static Vector3 EvaluateGrenadePosition(Vector3 start, Vector3 velocity, float elapsed) { //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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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) return start + velocity * elapsed + 0.5f * Physics.gravity * elapsed * elapsed; } private static PlayerControllerB ResolveCombatOwner() { PlayerControllerB val = ResolvePlayer(_ownerPlayerId); if (!((Object)(object)val != (Object)null) || val.isPlayerDead) { return null; } return val; } private static Transform ResolveGrenadeMuzzle() { return CourierDroneRuntimeAssets.FindGrenadeMuzzle(_droneVisual); } private static Vector3 GetDroneCombatPosition() { //IL_0022: 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_0012: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_droneVisual != (Object)null)) { return ToFlightPosition(_droneGroundPosition); } return _droneVisual.transform.position; } private static Vector3 GetDroneCombatOrigin() { //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) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) Vector3 droneCombatPosition = GetDroneCombatPosition(); if (!(droneCombatPosition != Vector3.zero)) { return Vector3.zero; } return droneCombatPosition + Vector3.up * 0.12f; } private static Vector3 ResolveEnemyCenter(EnemyAI enemy) { //IL_0009: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return Vector3.zero; } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position; } Renderer val = null; if (enemy.skinnedMeshRenderers != null) { for (int i = 0; i < enemy.skinnedMeshRenderers.Length; i++) { if (!((Object)(object)enemy.skinnedMeshRenderers[i] == (Object)null)) { val = (Renderer)(object)enemy.skinnedMeshRenderers[i]; break; } } } if ((Object)(object)val == (Object)null && enemy.meshRenderers != null) { for (int j = 0; j < enemy.meshRenderers.Length; j++) { if (!((Object)(object)enemy.meshRenderers[j] == (Object)null)) { val = (Renderer)(object)enemy.meshRenderers[j]; break; } } } if (!((Object)(object)val != (Object)null)) { return ((Component)enemy).transform.position + Vector3.up * 1.2f; } Bounds bounds = val.bounds; return ((Bounds)(ref bounds)).center; } private static bool HasDroneLineOfSight(Vector3 origin, Vector3 target) { //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_000d: 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_0037: 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) if (origin == Vector3.zero || target == Vector3.zero) { return false; } int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); return !Physics.Linecast(origin, target, num, (QueryTriggerInteraction)1); } private static bool IsPlayerInGrenadeDanger(Vector3 impactPosition) { //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_005d: 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) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return false; } float num = 56.25f; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && !val.isPlayerDead && !((Object)(object)((Component)val).transform == (Object)null) && val.isInsideFactory == _droneIsInside) { Vector3 val2 = ((Component)val).transform.position - impactPosition; if (((Vector3)(ref val2)).sqrMagnitude <= num) { return true; } } } return false; } private static void PlayDroneFlameLocal(Vector3 position) { //IL_001c: 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_002a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual != (Object)null) { CourierDroneRuntimeAssets.PlayFireAttack(_droneVisual); } GameObject val = SpawnCompanionEffect("FireAttackParticles", position, ((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform.rotation : Quaternion.identity, 2.2f); if ((Object)(object)val != (Object)null && (Object)(object)_droneVisual != (Object)null) { val.transform.SetParent(_droneVisual.transform, true); } } private static void PlayGrenadeLaunchLocal(int grenadeId, Vector3 start, Vector3 velocity) { //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_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0072: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) Vector3 val = velocity; float num = Vector3.Dot(val, val); if (num > 0.001f) { ((Vector3)(ref val)).Normalize(); } Quaternion rotation = ((num > 0.001f) ? Quaternion.LookRotation(val, Vector3.up) : Quaternion.identity); SpawnCompanionEffect("GrenadeLaunchDustParticles", start, rotation, 2f); GameObject val2 = CourierDroneRuntimeAssets.InstantiateCompanionPrefab("Grenade", start, rotation); if ((Object)(object)val2 == (Object)null) { val2 = GameObject.CreatePrimitive((PrimitiveType)0); } ((Object)val2).name = "Y4NGZ_CourierDroneGrenade"; val2.transform.position = start; val2.transform.rotation = rotation; val2.transform.localScale = Vector3.one * 0.35f; Collider component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Rigidbody val3 = val2.GetComponent(); if ((Object)(object)val3 == (Object)null) { val3 = val2.AddComponent(); } val3.useGravity = true; val3.isKinematic = false; val3.velocity = velocity; val3.angularVelocity = Random.onUnitSphere * 9f; if (ActiveGrenadeVisuals.TryGetValue(grenadeId, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } ActiveGrenadeVisuals[grenadeId] = val2; Object.Destroy((Object)(object)val2, 3.5f); } private static void PlayGrenadeExplosionLocal(int grenadeId, Vector3 position) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (ActiveGrenadeVisuals.TryGetValue(grenadeId, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } ActiveGrenadeVisuals.Remove(grenadeId); SpawnCompanionEffect("GrenadeExplosionParticles", position, Quaternion.identity, 4f); } private static void DestroyActiveGrenadeVisuals() { foreach (KeyValuePair activeGrenadeVisual in ActiveGrenadeVisuals) { if ((Object)(object)activeGrenadeVisual.Value != (Object)null) { Object.Destroy((Object)(object)activeGrenadeVisual.Value); } } ActiveGrenadeVisuals.Clear(); } private static GameObject SpawnCompanionEffect(string assetName, Vector3 position, Quaternion rotation, float destroyAfter) { //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) GameObject val = CourierDroneRuntimeAssets.InstantiateCompanionPrefab(assetName, position, rotation); if ((Object)(object)val == (Object)null) { return null; } val.SetActive(true); ParticleSystem[] componentsInChildren = val.GetComponentsInChildren(true); foreach (ParticleSystem val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { ((Component)val2).gameObject.SetActive(true); val2.Play(true); } } Object.Destroy((Object)(object)val, destroyAfter); return val; } private static void MarkDroneThreat(EnemyAI enemy, float seconds) { DroneThreats[GetEnemyKey(enemy)] = Time.time + Mathf.Max(0.1f, seconds); } private static bool IsDroneThreat(EnemyAI enemy) { ulong enemyKey = GetEnemyKey(enemy); if (!DroneThreats.TryGetValue(enemyKey, out var value)) { return false; } if (Time.time <= value) { return true; } DroneThreats.Remove(enemyKey); return false; } private static void SteerEnemyTowardDrone(EnemyAI enemy) { //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) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) Vector3 droneTargetPosition = GetDroneTargetPosition(); if (droneTargetPosition == Vector3.zero) { return; } try { enemy.SetDestinationToPosition(droneTargetPosition, false); if ((Object)(object)enemy.agent != (Object)null && ((Behaviour)enemy.agent).enabled && enemy.agent.isOnNavMesh) { enemy.agent.SetDestination(droneTargetPosition); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("Courier Drone enemy aggro steer skipped for " + ((object)enemy).GetType().Name + ": " + ex.Message)); } } } private static void TryEnemyContactDamageDrone(EnemyAI enemy) { ulong enemyKey = GetEnemyKey(enemy); if (!NextDroneHitByEnemy.TryGetValue(enemyKey, out var value) || !(Time.time < value)) { NextDroneHitByEnemy[enemyKey] = Time.time + 1.1f; PlayVerifiedEnemyAttackPresentation(enemy); ApplyDroneDamage(10, enemy); } } private static bool EnemySharesDroneSpace(EnemyAI enemy) { if ((Object)(object)enemy != (Object)null) { return enemy.isOutside != _droneIsInside; } return false; } private static Vector3 GetDroneTargetPosition() { //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) return CurrentDroneGroundPositionOr(_droneGroundPosition); } private static ulong GetEnemyKey(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return 0uL; } if ((Object)(object)((NetworkBehaviour)enemy).NetworkObject != (Object)null) { return ((NetworkBehaviour)enemy).NetworkObjectId; } return (ulong)((Object)enemy).GetInstanceID(); } private static void ApplyDroneDamage(int damage, EnemyAI sourceEnemy) { if (damage > 0 && CanDroneBeDamaged() && IsServerAuthority()) { _droneHealth = Mathf.Max(0, _droneHealth - damage); bool bigHit = damage > 3; PlayDroneHitLocal(damage, bigHit, _droneHealth); BroadcastDroneHit(damage, bigHit, _droneHealth); if (_droneHealth <= 0) { DestroyDroneFromDamage(sourceEnemy); } else { BroadcastDroneState(); } } } private static void PlayDroneHitLocal(int damageAmount, bool bigHit, int healthAfter) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_002e: 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) if (!((Object)(object)_droneVisual == (Object)null)) { Vector3 val = Random.insideUnitSphere; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude <= 0.001f) { val = Vector3.right; } CourierDroneRuntimeAssets.PlayHitReaction(_droneVisual, bigHit, ((Vector3)(ref val)).normalized, 0.12f, 0.25f); MaybeDisplayOwnerAttackWarning(healthAfter); } } private static void MaybeDisplayOwnerAttackWarning(int healthAfter) { if (healthAfter > 0 && !(Time.time < _nextDroneAttackWarningAt)) { _nextDroneAttackWarningAt = Time.time + 5f; int num = Mathf.CeilToInt(Mathf.Clamp01((float)healthAfter / 30f) * 100f); DisplayOwnerTip(_ownerPlayerId, $"Under attack — {num}%", isWarning: true); } } private static void PlayVerifiedEnemyAttackPresentation(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return; } int ownerPlayerId = Mathf.Max(0, _ownerPlayerId); CrawlerAI crawler = (CrawlerAI)(object)((enemy is CrawlerAI) ? enemy : null); if (crawler != null) { TryPlayVerifiedEnemyAttack("CrawlerAI", delegate { crawler.HitPlayerClientRpc(ownerPlayerId); }); return; } HoarderBugAI val = (HoarderBugAI)(object)((enemy is HoarderBugAI) ? enemy : null); if (val != null) { TryPlayVerifiedEnemyAttack("HoarderBugAI", (Action)val.HitPlayerClientRpc); return; } SandSpiderAI sandSpider = (SandSpiderAI)(object)((enemy is SandSpiderAI) ? enemy : null); if (sandSpider != null) { TryPlayVerifiedEnemyAttack("SandSpiderAI", delegate { sandSpider.HitPlayerClientRpc(ownerPlayerId); }); } } private static void TryPlayVerifiedEnemyAttack(string enemyType, Action playAttack) { try { playAttack?.Invoke(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("Courier Drone " + enemyType + " attack presentation skipped: " + ex.Message)); } } } private static void DestroyDroneFromDamage(EnemyAI sourceEnemy) { //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) //IL_001e: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) if (!_droneDestroyedThisRound) { _droneHealth = 0; _droneDestroyedThisRound = true; Vector3 val = CurrentDroneGroundPositionOr(_droneGroundPosition); if (val != Vector3.zero) { _droneGroundPosition = val; } DestroyDroneLocal(dropCargo: true, notifyOwner: true); BroadcastDroneDeath(_droneGroundPosition, _droneIsInside); BroadcastDroneState(); } } private static void DestroyDroneLocal(bool dropCargo, bool notifyOwner) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) StopManualControl(resumeDrone: false, notifyOwner: false); _routeVersion++; CourierDroneRuntimeAssets.StopMagnetSound(_droneVisual); GameObject droneVisual = _droneVisual; Vector3 position = (((Object)(object)droneVisual != (Object)null) ? droneVisual.transform.position : ToFlightPosition(_droneGroundPosition)); bool flag = (Object)(object)droneVisual != (Object)null && CourierDroneRuntimeAssets.PlayDeath(droneVisual); if (dropCargo) { DropCarriedScrapAtDrone(); } else { CarriedItems.Clear(); } PlannedItems.Clear(); DroneThreats.Clear(); NextDroneHitByEnemy.Clear(); DestroyActiveGrenadeVisuals(); _mode = DroneMode.NotSpawned; _isFollowingPlayer = false; _followSettled = false; ClearFollowPathCache(); _reportedNoEntranceScrap = false; _commandCooldownEnd = 0f; _combatLandedUntil = 0f; _nextGuardScrapScanAt = 0f; _flashlightEnabled = false; _magnetPickupActive = false; _nextDroneAttackWarningAt = 0f; ClearPointerTargetState(); if (!flag) { SpawnDroneDeathEffect(position); } if ((Object)(object)droneVisual != (Object)null) { Object.Destroy((Object)(object)droneVisual, flag ? 5f : 0f); if ((Object)(object)_droneVisual == (Object)(object)droneVisual) { _droneVisual = null; ClearDroneRendererCache(); } } if (notifyOwner) { DisplayOwnerTip(_ownerPlayerId, "Drone destroyed. It can be redeployed next round.", isWarning: true); } } private static void SpawnDroneDeathEffect(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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown if (!(position == Vector3.zero)) { GameObject val = new GameObject("Y4NGZ_CourierDroneDeathFlash"); val.transform.position = position; Light obj = val.AddComponent(); obj.type = (LightType)2; obj.color = new Color(1f, 0.22f, 0.12f); obj.range = 6f; obj.intensity = 9f; obj.shadows = (LightShadows)0; Object.Destroy((Object)val, 0.45f); } } private static void MoveScrapToPlayer(GrabbableObject item, Vector3 dropPosition, bool dropIsInShip, bool dropIsInFactory, Vector3 worldScale, bool bodyWasKinematic, bool bodyUsedGravity, int courierPlayerId) { //IL_0042: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)item == (Object)null) { return; } bool wasInside = ProgressionManager.IsInsideShip(item); Transform val = ((dropIsInShip && (Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.elevatorTransform : null); ((Component)item).transform.SetParent(val, true); SetWorldScale(((Component)item).transform, worldScale); ((Component)item).transform.position = dropPosition; SetWorldScale(((Component)item).transform, worldScale); item.parentObject = null; item.playerHeldBy = null; item.isHeld = false; item.isPocketed = false; item.isHeldByEnemy = false; item.grabbable = true; item.grabbableToEnemies = true; item.isInShipRoom = dropIsInShip; item.isInElevator = dropIsInShip; ProgressionManager.RecordAttributedBoundaryCrossing(ResolveCourierHandlerClientId(courierPlayerId), item, wasInside); item.isInFactory = dropIsInFactory; item.hasHitGround = false; item.reachedFloorTarget = false; item.fallTime = 0f; item.floorYRot = -1; item.startFallingPosition = (((Object)(object)val != (Object)null) ? val.InverseTransformPoint(dropPosition) : dropPosition); Vector3 itemFloorPosition = item.GetItemFloorPosition(dropPosition); item.targetFloorPosition = (((Object)(object)val != (Object)null) ? val.InverseTransformPoint(itemFloorPosition) : itemFloorPosition); item.EnablePhysics(true); item.EnableItemMeshes(true); SetItemKinematic(item, bodyWasKinematic, bodyUsedGravity); SetWorldScale(((Component)item).transform, worldScale); if (!dropIsInShip) { return; } try { RoundManager instance = RoundManager.Instance; if (instance != null) { instance.CollectNewScrapForThisRound(item); } item.OnBroughtToShip(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("Courier Drone scrap collection bookkeeping skipped: " + ex.Message)); } } } private static void EnsureDroneVisualAt(Vector3 groundPosition) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual != (Object)null) { _droneVisual.SetActive(true); _droneVisual.transform.position = ToFlightPosition(groundPosition); _droneGroundPosition = groundPosition; CourierDroneRuntimeAssets.EnsureDroneAudio(_droneVisual); UpdateCarriedItemTransforms(); } else { _droneVisual = CourierDroneRuntimeAssets.InstantiateDroneVisual(ToFlightPosition(groundPosition), Quaternion.identity) ?? CreateFallbackDroneVisual(ToFlightPosition(groundPosition)); ClearDroneRendererCache(); _droneGroundPosition = groundPosition; CourierDroneRuntimeAssets.EnsureDroneAudio(_droneVisual); UpdateCarriedItemTransforms(); } } private static void ResetDroneState(bool destroyVisual) { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) StopManualControl(resumeDrone: false, notifyOwner: false); _routeVersion++; CourierDroneRuntimeAssets.StopMagnetSound(_droneVisual); PlannedItems.Clear(); CarriedItems.Clear(); KnownGrabbableItems.Clear(); DroneThreats.Clear(); NextDroneHitByEnemy.Clear(); DestroyActiveGrenadeVisuals(); _ownerCourierTier = 0; _nextEnemyScanAt = 0f; _lastEnemyScanFrame = -1; _nextFlameAt = 0f; _nextGrenadeAt = 0f; _combatLandedUntil = 0f; _nextEntranceScrapScanAt = 0f; _nextGuardScrapScanAt = 0f; _flashlightEnabled = false; _magnetPickupActive = false; ClearPointerTargetState(); _mode = DroneMode.NotSpawned; _droneGroundPosition = Vector3.zero; _droneIsInside = false; _isFollowingPlayer = false; _followSettled = false; ClearFollowPathCache(); _reportedNoEntranceScrap = false; _ownerPlayerId = -1; if (destroyVisual && (Object)(object)_droneVisual != (Object)null) { Object.Destroy((Object)(object)_droneVisual); _droneVisual = null; ClearDroneRendererCache(); } } private static bool IsPointerFetchEligible(GrabbableObject item) { if (IsCourierEligibleItem(item) && item.isInFactory == _droneIsInside && !IsAlreadyCarried(((NetworkBehaviour)item).NetworkObjectId) && !IsAlreadyPlanned(((NetworkBehaviour)item).NetworkObjectId)) { return !WouldExceedCargoWeight(item, GetReservedCargoWeightPounds()); } return false; } private static bool IsCourierEligibleItem(GrabbableObject item) { if ((Object)(object)item != (Object)null && (Object)(object)item.itemProperties != (Object)null && item.itemProperties.isScrap && !item.isHeld && !item.isPocketed && !item.isHeldByEnemy && !item.isInShipRoom) { return item.grabbable; } return false; } private static bool IsCourierEligibleEntranceScrap(GrabbableObject item, List searchPositions, float radiusSqr) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (IsCourierEligibleItem(item)) { return DistanceToClosestPointSqr(((Component)item).transform.position, searchPositions) <= radiusSqr; } return false; } private static MainEntranceRoute FindMainEntranceRoute() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) EntranceTeleport[] array = Object.FindObjectsOfType(); MainEntranceRoute mainEntranceRoute = new MainEntranceRoute(); foreach (EntranceTeleport val in array) { if ((Object)(object)val == (Object)null || val.entranceId != 0) { continue; } Vector3 val2 = ResolveEntrancePosition(val); if (!(val2 == Vector3.zero)) { if (val.isEntranceToBuilding) { mainEntranceRoute.OutsidePosition = FirstNonZero(mainEntranceRoute.OutsidePosition, val2); } else { mainEntranceRoute.InsidePosition = FirstNonZero(mainEntranceRoute.InsidePosition, val2); } } } return mainEntranceRoute; } private static Vector3 ResolveEntrancePosition(EntranceTeleport entrance) { //IL_0020: 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) if (!((Object)(object)entrance.entrancePoint != (Object)null)) { return ((Component)entrance).transform.position; } return entrance.entrancePoint.position; } private static Vector3 FirstNonZero(Vector3 preferred, Vector3 fallback) { //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_000f: 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) if (!(preferred != Vector3.zero)) { return fallback; } return preferred; } private static List FindMainEntranceSearchPositions(CourierCommand command) { //IL_0008: 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_0013: 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) List list = new List(); AddRoutePoint(list, FirstNonZero(command.InsideEntrancePosition, command.EntrancePosition)); if (list.Count == 0) { AddRoutePoint(list, command.OutsideEntrancePosition); } return list; } private static float DistanceToClosestPointSqr(Vector3 position, List points) { //IL_000a: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) float num = float.MaxValue; for (int i = 0; i < points.Count; i++) { Vector3 val = position - points[i]; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (sqrMagnitude < num) { num = sqrMagnitude; } } return num; } private static Vector3 FindDroneStartPosition(PlayerControllerB player) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0018: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } if (IsPlayerInShip(player)) { return FindShipDroneDockPosition(player); } return ProjectToNavMesh(((Component)player).transform.position + ((Component)player).transform.right * 1.15f + ((Component)player).transform.forward * 0.35f + Vector3.up * 0.15f, 3.5f); } private static Vector3 FindDroneFollowPosition(PlayerControllerB player) { //IL_0009: 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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_0065: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_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_0084: 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_0062: 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_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_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } if (IsPlayerInShip(player)) { return FindShipDroneDockPosition(player); } Vector3 val = CurrentDroneGroundPositionOr(Vector3.zero); if (val != Vector3.zero) { Vector3 val2 = val - ((Component)player).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).magnitude <= 3.4f) { return val; } } Vector3 val3 = ((val != Vector3.zero) ? (val - ((Component)player).transform.position) : Vector3.right); val3.y = 0f; if (((Vector3)(ref val3)).sqrMagnitude <= 0.001f) { val3 = Vector3.right; } ((Vector3)(ref val3)).Normalize(); return ProjectToNavMesh(((Component)player).transform.position + val3 * 2.3f, 3.5f); } private static bool IsPlayerInShip(PlayerControllerB player) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).transform == (Object)null) { return false; } if (player.isInHangarShipRoom) { return true; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; return ((Bounds)(ref bounds)).Contains(((Component)player).transform.position); } return false; } private static Vector3 FindShipDroneDockPosition(PlayerControllerB player) { //IL_0017: 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_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: 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_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_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_016b: 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_01a0: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).transform == (Object)null) { return Vector3.zero; } Vector3 val = ((Component)player).transform.position + ((Component)player).transform.right * 1.05f - ((Component)player).transform.forward * 0.55f; StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if (instance.insideShipPositions != null && instance.insideShipPositions.Length != 0 && (Object)(object)instance.insideShipPositions[0] != (Object)null) { val.y = instance.insideShipPositions[0].position.y + 0.05f; } else if ((Object)(object)instance.elevatorTransform != (Object)null) { val.y = instance.elevatorTransform.position.y + 0.05f; } else if ((Object)(object)instance.middleOfShipNode != (Object)null) { val.y = instance.middleOfShipNode.position.y + 0.05f; } if ((Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; val.x = ClampInsideBounds(val.x, ((Bounds)(ref bounds)).min.x, ((Bounds)(ref bounds)).max.x, 0.75f); val.z = ClampInsideBounds(val.z, ((Bounds)(ref bounds)).min.z, ((Bounds)(ref bounds)).max.z, 0.75f); float num = ((Bounds)(ref bounds)).max.y - 0.95f - 0.25f; if (num > ((Bounds)(ref bounds)).min.y) { val.y = Mathf.Min(val.y, num); } val.y = Mathf.Max(val.y, ((Bounds)(ref bounds)).min.y + 0.05f); } } return val; } private static Vector3 ProjectToNavMesh(Vector3 point, float radius) { //IL_0000: 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_000e: Unknown result type (might be due to invalid IL or missing references) NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(point, ref val, radius, -1)) { return ((NavMeshHit)(ref val)).position; } return Vector3.zero; } private static int GetDroneCollisionMask() { if (!((Object)(object)StartOfRound.Instance != (Object)null)) { return -1; } return StartOfRound.Instance.collidersAndRoomMask; } private static Vector3 ResampleGroundPoint(Vector3 candidate, Vector3 fallback) { //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_000f: 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_0027: 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_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_003c: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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) if (candidate == Vector3.zero) { return fallback; } NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(candidate, ref val, 2f, -1)) { return ((NavMeshHit)(ref val)).position; } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(candidate + Vector3.up * 2f, Vector3.down, ref val2, 6f, GetDroneCollisionMask(), (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val2)).point; } if (!(fallback != Vector3.zero)) { return candidate; } return fallback; } private static Vector3 ToSmoothedFlightPosition(Vector3 groundPosition, float currentFlightY) { //IL_0000: 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_000f: 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) float num = ResolveDynamicHoverHeight(groundPosition, blockedAtCurrentHeight: false); return new Vector3(groundPosition.x, Mathf.MoveTowards(currentFlightY, groundPosition.y + num, 3f * Time.deltaTime), groundPosition.z); } private static bool CanMoveDirectToFollowTarget(Vector3 currentGround, Vector3 targetGround) { //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_000d: 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_001c: 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_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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) if (currentGround == Vector3.zero || targetGround == Vector3.zero) { return false; } Vector3 val = targetGround - currentGround; if (((Vector3)(ref val)).sqrMagnitude > 16f) { return false; } Vector3 val2 = ToFlightPosition(currentGround); Vector3 val3 = ToFlightPosition(targetGround) - val2; float magnitude = ((Vector3)(ref val3)).magnitude; if (magnitude <= 0.001f) { return true; } RaycastHit val4 = default(RaycastHit); return !Physics.SphereCast(val2, 0.3f, ((Vector3)(ref val3)).normalized, ref val4, magnitude, GetDroneCollisionMask(), (QueryTriggerInteraction)1); } private static bool CanReachWaypointAtHoverHeight(Vector3 currentGround, Vector3 candidateGround) { //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_000d: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) if (currentGround == Vector3.zero || candidateGround == Vector3.zero) { return false; } float num = Mathf.Clamp(_dynamicHoverHeight, 0.55f, 1.9f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(currentGround.x, currentGround.y + num, currentGround.z); Vector3 val2 = new Vector3(candidateGround.x, candidateGround.y + num, candidateGround.z) - val; float magnitude = ((Vector3)(ref val2)).magnitude; if (magnitude <= 0.001f) { return true; } RaycastHit val3 = default(RaycastHit); return !Physics.SphereCast(val, 0.3f, ((Vector3)(ref val2)).normalized, ref val3, magnitude, GetDroneCollisionMask(), (QueryTriggerInteraction)1); } private static bool TryResolveClutterMove(Vector3 fromFlight, Vector3 toFlight, Vector3 nextGround, out Vector3 adjustedFlight, out bool blocked) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00ad: 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_003f: 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_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: 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_0071: 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_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_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_012d: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: 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_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01fe: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01e8: Unknown result type (might be due to invalid IL or missing references) adjustedFlight = toFlight; blocked = false; Vector3 horizontalDelta = default(Vector3); ((Vector3)(ref horizontalDelta))..ctor(toFlight.x - fromFlight.x, 0f, toFlight.z - fromFlight.z); if (((Vector3)(ref horizontalDelta)).magnitude <= 0.001f) { float hoverHeight = Mathf.Clamp(toFlight.y - nextGround.y, 0.55f, 1.9f); if (!IsHoverBandClear(nextGround, hoverHeight)) { float num = ResolveDynamicHoverHeight(nextGround, blockedAtCurrentHeight: true); adjustedFlight = new Vector3(toFlight.x, nextGround.y + num, toFlight.z); return true; } return false; } Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(fromFlight.x, toFlight.y, fromFlight.z); if (TryMoveWithSphereCast(val, horizontalDelta, out var candidate, out var travelled, out var hit)) { return false; } TryCollisionRepathThrottled(); Vector3 slideCandidate = val; float slideTravel = 0f; TrySlideMove(val, horizontalDelta, ((RaycastHit)(ref hit)).normal, out slideCandidate, out slideTravel); if (slideTravel > travelled) { adjustedFlight = new Vector3(slideCandidate.x, toFlight.y, slideCandidate.z); blocked = slideTravel <= 0.01f; } else { adjustedFlight = new Vector3(candidate.x, toFlight.y, candidate.z); blocked = travelled <= 0.01f; } if (!blocked) { return true; } float num2 = ResolveDynamicHoverHeight(nextGround, blockedAtCurrentHeight: true); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(toFlight.x, nextGround.y + num2, toFlight.z); Vector3 horizontalDelta2 = default(Vector3); ((Vector3)(ref horizontalDelta2))..ctor(val2.x - fromFlight.x, 0f, val2.z - fromFlight.z); Vector3 castStart = default(Vector3); ((Vector3)(ref castStart))..ctor(fromFlight.x, val2.y, fromFlight.z); if (((Vector3)(ref horizontalDelta2)).sqrMagnitude > 0.0001f && TryMoveWithSphereCast(castStart, horizontalDelta2, out var candidate2, out var _, out var _)) { adjustedFlight = new Vector3(candidate2.x, val2.y, candidate2.z); blocked = false; } else if (IsHoverBandClear(nextGround, num2)) { adjustedFlight = new Vector3(fromFlight.x, val2.y, fromFlight.z); } return true; } private static bool TrySlideMove(Vector3 castStart, Vector3 horizontalDelta, Vector3 hitNormal, out Vector3 slideCandidate, out float slideTravel) { //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_000f: 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_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_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) slideCandidate = castStart; slideTravel = 0f; Vector3 horizontalDelta2 = Vector3.ProjectOnPlane(horizontalDelta, hitNormal); horizontalDelta2.y = 0f; if (((Vector3)(ref horizontalDelta2)).sqrMagnitude <= 0.0001f) { return false; } horizontalDelta2 = ((Vector3)(ref horizontalDelta2)).normalized * ((Vector3)(ref horizontalDelta)).magnitude; RaycastHit hit; return TryMoveWithSphereCast(castStart, horizontalDelta2, out slideCandidate, out slideTravel, out hit); } private static bool TryMoveWithSphereCast(Vector3 castStart, Vector3 horizontalDelta, out Vector3 candidate, out float travelled, out RaycastHit hit) { //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_0010: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_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) candidate = castStart; travelled = 0f; hit = default(RaycastHit); float magnitude = ((Vector3)(ref horizontalDelta)).magnitude; if (magnitude <= 0.001f) { return true; } Vector3 val = horizontalDelta / magnitude; if (!Physics.SphereCast(castStart, 0.3f, val, ref hit, magnitude, GetDroneCollisionMask(), (QueryTriggerInteraction)1)) { candidate = castStart + horizontalDelta; travelled = magnitude; return true; } travelled = Mathf.Max(0f, ((RaycastHit)(ref hit)).distance - 0.35f); candidate = castStart + val * travelled; return false; } private static float ResolveDynamicHoverHeight(Vector3 groundPosition, bool blockedAtCurrentHeight) { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008c: 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) if (groundPosition == Vector3.zero) { return _dynamicHoverHeight; } if (!blockedAtCurrentHeight && Time.time < _nextHoverProbeAt) { return Mathf.Clamp(_dynamicHoverHeight, 0.55f, 1.9f); } _nextHoverProbeAt = Time.time + 0.2f; float num = 0.95f; RaycastHit val = default(RaycastHit); if (Physics.Raycast(groundPosition + Vector3.up * 2.2f, Vector3.down, ref val, 2.25f, GetDroneCollisionMask(), (QueryTriggerInteraction)1)) { float num2 = Mathf.Max(0f, ((RaycastHit)(ref val)).point.y - groundPosition.y); if (blockedAtCurrentHeight && num2 > 0.55f) { num = Mathf.Max(0.95f, num2 + 0.22f); } } if (blockedAtCurrentHeight) { for (float num3 = Mathf.Max(num, _dynamicHoverHeight + 0.2f); num3 <= 1.901f; num3 += 0.2f) { if (IsHoverBandClear(groundPosition, num3)) { num = num3; break; } } } _dynamicHoverHeight = Mathf.Clamp(num, 0.55f, 1.9f); return _dynamicHoverHeight; } private static bool IsHoverBandClear(Vector3 groundPosition, float hoverHeight) { //IL_0000: 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_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) return !Physics.CheckSphere(new Vector3(groundPosition.x, groundPosition.y + hoverHeight, groundPosition.z), 0.3f, GetDroneCollisionMask(), (QueryTriggerInteraction)1); } private static void TryCollisionRepathThrottled() { if (!(Time.time < _nextCollisionRepathAt)) { _nextCollisionRepathAt = Time.time + 0.6f; ClearFollowPathCache(); } } private static Vector3 ApplyFlightBob(Vector3 flightPosition) { //IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) float num = Time.time * 1.2f * MathF.PI * 2f; return flightPosition + Vector3.up * (Mathf.Sin(num) * 0.05f); } private static void ApplyIdleSway(Vector3 groundPosition, PlayerControllerB owner) { //IL_000d: 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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_droneVisual == (Object)null) && !(groundPosition == Vector3.zero)) { float num = Time.time * 1.2f * MathF.PI * 2f; float num2 = Time.time * 0.4f * MathF.PI * 2f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Sin(num2) * 0.08f, Mathf.Sin(num) * 0.05f, Mathf.Sin(num2 + MathF.PI / 2f) * 0.08f); _droneVisual.transform.position = ToFlightPosition(groundPosition) + val; EaseIdleYawTowardOwner(owner); } } private static void EaseIdleYawTowardOwner(PlayerControllerB owner) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null) { return; } PlayerControllerB val = owner ?? ResolvePlayer(_ownerPlayerId); if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).transform == (Object)null)) { Vector3 val2 = ((Component)val).transform.position - _droneVisual.transform.position; val2.y = 0f; if (!(((Vector3)(ref val2)).sqrMagnitude <= 0.001f)) { Quaternion val3 = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); _droneVisual.transform.rotation = Quaternion.Slerp(_droneVisual.transform.rotation, val3, Mathf.Clamp01(Time.deltaTime * 1.8f)); } } } private static float ClampInsideBounds(float value, float min, float max, float margin) { if (max <= min) { return value; } float num = min + margin; float num2 = max - margin; if (num > num2) { return (min + max) * 0.5f; } return Mathf.Clamp(value, num, num2); } private static Vector3 FindPlayerDropPosition(PlayerControllerB player) { //IL_0015: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } return ((Component)player).transform.position + ((Component)player).transform.right * 1.25f + ((Component)player).transform.forward * 0.65f + Vector3.up * 0.1f; } private static Vector3 FindShipDropPosition(PlayerControllerB player) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.middleOfShipNode != (Object)null) { return instance.middleOfShipNode.position + Vector3.up * 0.1f; } if (instance.insideShipPositions != null && instance.insideShipPositions.Length != 0 && (Object)(object)instance.insideShipPositions[0] != (Object)null) { return instance.insideShipPositions[0].position + Vector3.up * 0.1f; } if ((Object)(object)instance.shipInnerRoomBounds != (Object)null) { Bounds bounds = instance.shipInnerRoomBounds.bounds; return ((Bounds)(ref bounds)).center + Vector3.up * 0.1f; } if ((Object)(object)instance.elevatorTransform != (Object)null) { return instance.elevatorTransform.position + Vector3.up * 0.1f; } } return FindPlayerDropPosition(player); } private static Vector3 FindShipApproachPosition(Vector3 fallback) { //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.outsideDoorPosition != (Object)null) { return instance.outsideDoorPosition.position + Vector3.up * 0.1f; } if ((Object)(object)instance.shipDoorNode != (Object)null) { return instance.shipDoorNode.position + Vector3.up * 0.1f; } if ((Object)(object)instance.groundOutsideShipSpawnPosition != (Object)null) { return instance.groundOutsideShipSpawnPosition.position + Vector3.up * 0.1f; } } return fallback; } private static Vector3 CurrentDroneGroundPositionOr(Vector3 fallback) { //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) //IL_0013: 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) if (!(_droneGroundPosition != Vector3.zero)) { return fallback; } return _droneGroundPosition; } private static void AddRoutePoint(List route, Vector3 point) { //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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (point == Vector3.zero) { return; } if (route.Count > 0) { Vector3 val = route[route.Count - 1] - point; if (((Vector3)(ref val)).sqrMagnitude < 0.25f) { return; } } route.Add(point); } private static Vector3 ToFlightPosition(Vector3 groundPosition) { //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) return groundPosition + Vector3.up * 0.95f; } private static bool IsEntranceTransition(CourierCommand command, Vector3 from, Vector3 to) { //IL_0004: 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_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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if (command == null || command.OutsideEntrancePosition == Vector3.zero || command.InsideEntrancePosition == Vector3.zero) { return false; } if (!IsSameRoutePoint(from, command.OutsideEntrancePosition) || !IsSameRoutePoint(to, command.InsideEntrancePosition)) { if (IsSameRoutePoint(from, command.InsideEntrancePosition)) { return IsSameRoutePoint(to, command.OutsideEntrancePosition); } return false; } return true; } private static bool IsMainEntrancePoint(CourierCommand command, Vector3 point) { //IL_0005: 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_0013: 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) if (command == null) { return false; } if (!IsSameRoutePoint(point, command.OutsideEntrancePosition)) { return IsSameRoutePoint(point, command.InsideEntrancePosition); } return true; } private static bool IsSameRoutePoint(Vector3 a, Vector3 b) { //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_000d: 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_001a: 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_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) if (a != Vector3.zero && b != Vector3.zero) { Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude <= 0.35f; } return false; } private static Vector3 GetCarryWorldPosition(Vector3 carryOffset) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_0030: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null) { return carryOffset; } Transform transform = _droneVisual.transform; Transform val = CourierDroneRuntimeAssets.FindCarryAnchor(_droneVisual); if ((Object)(object)val != (Object)null) { Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(carryOffset.x, carryOffset.y + 0.55f, carryOffset.z); return val.position + transform.right * val2.x + transform.forward * val2.z + Vector3.up * val2.y; } return transform.position + transform.right * carryOffset.x + transform.forward * carryOffset.z + Vector3.up * carryOffset.y; } private static void UpdateCarriedItemTransforms() { //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) //IL_006f: 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_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_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: 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_00fc: 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_00ad: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_droneVisual == (Object)null) { return; } for (int i = 0; i < CarriedItems.Count; i++) { CarriedCourierItem carriedCourierItem = CarriedItems[i]; GrabbableObject item = carriedCourierItem.Item; if (!((Object)(object)item == (Object)null)) { ((Component)item).transform.SetParent((Transform)null, true); item.parentObject = null; item.isHeld = false; item.isPocketed = false; item.isHeldByEnemy = false; item.playerHeldBy = null; Vector3 carryWorldPosition = GetCarryWorldPosition(carriedCourierItem.CarryOffset); Vector3 val = ResampleGroundPoint(new Vector3(carryWorldPosition.x, _droneGroundPosition.y, carryWorldPosition.z), _droneGroundPosition); if (val != Vector3.zero) { carryWorldPosition.y = Mathf.Max(carryWorldPosition.y, val.y + 0.15f); } ((Component)item).transform.position = carryWorldPosition; ((Component)item).transform.rotation = _droneVisual.transform.rotation * carriedCourierItem.CarryLocalRotation; SetWorldScale(((Component)item).transform, carriedCourierItem.WorldScale); } } } private static void SetItemKinematic(GrabbableObject item, bool isKinematic, bool useGravity) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)item == (Object)null) && !((Object)(object)item.propBody == (Object)null)) { item.propBody.velocity = Vector3.zero; item.propBody.angularVelocity = Vector3.zero; item.propBody.isKinematic = isKinematic; item.propBody.useGravity = useGravity; } } private static void SetWorldScale(Transform transform, Vector3 worldScale) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_008b: 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) if (!((Object)(object)transform == (Object)null) && !(worldScale == Vector3.zero)) { Transform parent = transform.parent; if ((Object)(object)parent == (Object)null) { transform.localScale = worldScale; return; } Vector3 lossyScale = parent.lossyScale; transform.localScale = new Vector3(SafeDivideScale(worldScale.x, lossyScale.x, transform.localScale.x), SafeDivideScale(worldScale.y, lossyScale.y, transform.localScale.y), SafeDivideScale(worldScale.z, lossyScale.z, transform.localScale.z)); } } private static float SafeDivideScale(float worldAxis, float parentAxis, float fallback) { if (!(Mathf.Abs(parentAxis) > 0.0001f)) { return fallback; } return worldAxis / parentAxis; } private static bool IsAlreadyCarried(ulong networkObjectId) { for (int i = 0; i < CarriedItems.Count; i++) { if (CarriedItems[i].Move.NetworkObjectId == networkObjectId) { return true; } } return false; } private static bool IsAlreadyPlanned(ulong networkObjectId) { for (int i = 0; i < PlannedItems.Count; i++) { if (PlannedItems[i].NetworkObjectId == networkObjectId) { return true; } } return false; } private static void StartCoroutineOnAvailableHost(IEnumerator routine) { MonoBehaviour val = (MonoBehaviour)(((Object)(object)HUDManager.Instance != (Object)null) ? ((object)HUDManager.Instance) : ((object)Object.FindObjectOfType())); if ((Object)(object)val != (Object)null) { val.StartCoroutine(routine); } } private static GameObject CreateFallbackDroneVisual(Vector3 position) { //IL_0017: 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_002d: 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_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown //IL_009a: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)0); ((Object)obj).name = "Y4NGZ_CourierDrone_Placeholder"; obj.transform.position = position; obj.transform.localScale = Vector3.one * 0.45f; Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.material = new Material(Shader.Find("Sprites/Default") ?? Shader.Find("Standard")); component2.material.color = new Color(0.45f, 0.95f, 1f, 0.65f); } Light obj2 = obj.AddComponent(); obj2.type = (LightType)2; obj2.color = new Color(0.45f, 0.95f, 1f); obj2.range = 5f; obj2.intensity = 2f; obj2.shadows = (LightShadows)0; return obj; } private static void FaceTravelDirection(Transform transform, float deltaX, float deltaY, float deltaZ) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00d2: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(deltaX, deltaY, deltaZ); if (!((Object)(object)transform == (Object)null) && !(((Vector3)(ref val)).sqrMagnitude <= 0.0001f)) { Vector3 forward = default(Vector3); ((Vector3)(ref forward))..ctor(val.x, 0f, val.z); if (((Vector3)(ref forward)).sqrMagnitude <= 0.0001f) { forward = transform.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 val2 = default(Vector3); ((Vector3)(ref val2))..ctor(transform.forward.x, 0f, transform.forward.z); if (((Vector3)(ref val2)).sqrMagnitude <= 0.0001f) { val2 = forward; } else { ((Vector3)(ref val2)).Normalize(); } float num = Mathf.Clamp((0f - Vector3.SignedAngle(val2, forward, Vector3.up)) * 0.45f, -13f, 13f); float num2 = Mathf.Lerp(0f, 10f, Mathf.Clamp01(((Vector3)(ref forward)).magnitude)); Quaternion val3 = Quaternion.LookRotation(forward, Vector3.up) * Quaternion.Euler(num2, 0f, num); transform.rotation = Quaternion.Slerp(transform.rotation, val3, Mathf.Clamp01(Time.deltaTime * 7.5f)); } } private static void DisplayOwnerTip(int playerId, string message, bool isWarning) { if (!((Object)(object)HUDManager.Instance == (Object)null)) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val != (Object)null) || playerId < 0 || (int)val.playerClientId == playerId) { HUDManager.Instance.DisplayTip("COURIER DRONE", message, isWarning, false, "LC_Tip1"); } } } private static bool CanUse(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu && !player.inSpecialInteractAnimation) { if (!((Object)(object)player.quickMenuManager == (Object)null)) { return !player.quickMenuManager.isMenuOpen; } return true; } return false; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static bool IsServerAuthority() { if (!((Object)(object)NetworkManager.Singleton == (Object)null)) { return NetworkManager.Singleton.IsServer; } return true; } private static ulong ResolveCourierHandlerClientId(int courierPlayerId) { PlayerControllerB val = ((courierPlayerId >= 0) ? ResolvePlayer(courierPlayerId) : null); if (!((Object)(object)val != (Object)null)) { return ulong.MaxValue; } return val.actualClientId; } private static PlayerControllerB ResolvePlayer(int playerId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } if (playerId >= 0 && playerId < array.Length && (Object)(object)array[playerId] != (Object)null) { return array[playerId]; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && (int)val.playerClientId == playerId) { return val; } } return null; } private static PlayerControllerB ResolvePlayerByActualClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.actualClientId == clientId) { return val; } } return null; } private static GrabbableObject ResolveItem(ulong networkId) { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkId, out var value) && (Object)(object)value != (Object)null) { return ((Component)value).GetComponent(); } if (KnownGrabbableItems.TryGetValue(networkId, out var value2)) { if ((Object)(object)value2 != (Object)null) { return value2; } KnownGrabbableItems.Remove(networkId); } return null; } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Expected O, but got Unknown //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Expected O, but got Unknown //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Expected O, but got Unknown //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c5: Expected O, but got Unknown //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Expected O, but got Unknown //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_0223: Expected O, but got Unknown //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024c: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveRequest; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveRequest; <>O.<0>__OnReceiveRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("TechnicianCourier_Request", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceiveCommand; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveCommand; <>O.<1>__OnReceiveCommand = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("TechnicianCourier_Command", (HandleNamedMessageDelegate)obj2); CustomMessagingManager customMessagingManager3 = NetworkManager.Singleton.CustomMessagingManager; object obj3 = <>O.<2>__OnReceiveState; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnReceiveState; <>O.<2>__OnReceiveState = val3; obj3 = (object)val3; } customMessagingManager3.RegisterNamedMessageHandler("TechnicianCourier_State", (HandleNamedMessageDelegate)obj3); CustomMessagingManager customMessagingManager4 = NetworkManager.Singleton.CustomMessagingManager; object obj4 = <>O.<3>__OnReceiveDeath; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnReceiveDeath; <>O.<3>__OnReceiveDeath = val4; obj4 = (object)val4; } customMessagingManager4.RegisterNamedMessageHandler("TechnicianCourier_Death", (HandleNamedMessageDelegate)obj4); CustomMessagingManager customMessagingManager5 = NetworkManager.Singleton.CustomMessagingManager; object obj5 = <>O.<4>__OnReceiveHit; if (obj5 == null) { HandleNamedMessageDelegate val5 = OnReceiveHit; <>O.<4>__OnReceiveHit = val5; obj5 = (object)val5; } customMessagingManager5.RegisterNamedMessageHandler("TechnicianCourier_Hit", (HandleNamedMessageDelegate)obj5); CustomMessagingManager customMessagingManager6 = NetworkManager.Singleton.CustomMessagingManager; object obj6 = <>O.<5>__OnReceiveFlame; if (obj6 == null) { HandleNamedMessageDelegate val6 = OnReceiveFlame; <>O.<5>__OnReceiveFlame = val6; obj6 = (object)val6; } customMessagingManager6.RegisterNamedMessageHandler("TechnicianCourier_Flame", (HandleNamedMessageDelegate)obj6); CustomMessagingManager customMessagingManager7 = NetworkManager.Singleton.CustomMessagingManager; object obj7 = <>O.<6>__OnReceiveGrenadeLaunch; if (obj7 == null) { HandleNamedMessageDelegate val7 = OnReceiveGrenadeLaunch; <>O.<6>__OnReceiveGrenadeLaunch = val7; obj7 = (object)val7; } customMessagingManager7.RegisterNamedMessageHandler("TechnicianCourier_GrenadeLaunch", (HandleNamedMessageDelegate)obj7); CustomMessagingManager customMessagingManager8 = NetworkManager.Singleton.CustomMessagingManager; object obj8 = <>O.<7>__OnReceiveGrenadeExplosion; if (obj8 == null) { HandleNamedMessageDelegate val8 = OnReceiveGrenadeExplosion; <>O.<7>__OnReceiveGrenadeExplosion = val8; obj8 = (object)val8; } customMessagingManager8.RegisterNamedMessageHandler("TechnicianCourier_GrenadeExplode", (HandleNamedMessageDelegate)obj8); CustomMessagingManager customMessagingManager9 = NetworkManager.Singleton.CustomMessagingManager; object obj9 = <>O.<8>__OnReceiveManualPose; if (obj9 == null) { HandleNamedMessageDelegate val9 = OnReceiveManualPose; <>O.<8>__OnReceiveManualPose = val9; obj9 = (object)val9; } customMessagingManager9.RegisterNamedMessageHandler("TechnicianCourier_ManualPose", (HandleNamedMessageDelegate)obj9); CustomMessagingManager customMessagingManager10 = NetworkManager.Singleton.CustomMessagingManager; object obj10 = <>O.<9>__OnReceiveManualPickup; if (obj10 == null) { HandleNamedMessageDelegate val10 = OnReceiveManualPickup; <>O.<9>__OnReceiveManualPickup = val10; obj10 = (object)val10; } customMessagingManager10.RegisterNamedMessageHandler("TechnicianCourier_ManualPickup", (HandleNamedMessageDelegate)obj10); CustomMessagingManager customMessagingManager11 = NetworkManager.Singleton.CustomMessagingManager; object obj11 = <>O.<10>__OnReceiveManualFire; if (obj11 == null) { HandleNamedMessageDelegate val11 = OnReceiveManualFire; <>O.<10>__OnReceiveManualFire = val11; obj11 = (object)val11; } customMessagingManager11.RegisterNamedMessageHandler("TechnicianCourier_ManualFire", (HandleNamedMessageDelegate)obj11); CustomMessagingManager customMessagingManager12 = NetworkManager.Singleton.CustomMessagingManager; object obj12 = <>O.<11>__OnReceivePointerCommand; if (obj12 == null) { HandleNamedMessageDelegate val12 = OnReceivePointerCommand; <>O.<11>__OnReceivePointerCommand = val12; obj12 = (object)val12; } customMessagingManager12.RegisterNamedMessageHandler("TechnicianCourier_PointerCommand", (HandleNamedMessageDelegate)obj12); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void SendPointerCommand(int playerId, int courierTier, CourierCommandType commandType, NetworkObjectReference targetReference) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_004a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null || !NetworkManager.Singleton.IsClient) { HandlePointerCommand(playerId, courierTier, commandType, targetReference); return; } if (NetworkManager.Singleton.IsServer) { if (HandlePointerCommand(playerId, courierTier, commandType, targetReference)) { BroadcastPointerCommand(playerId, courierTier, commandType, targetReference); } return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(36, (Allocator)2, -1); try { WritePointerCommandPayload(ref writer, playerId, courierTier, commandType, targetReference); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("TechnicianCourier_PointerCommand", 0uL, writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastPointerCommand(int playerId, int courierTier, CourierCommandType commandType, NetworkObjectReference targetReference) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(36, (Allocator)2, -1); try { WritePointerCommandPayload(ref writer, playerId, courierTier, commandType, targetReference); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_PointerCommand", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void WritePointerCommandPayload(ref FastBufferWriter writer, int playerId, int courierTier, CourierCommandType commandType, NetworkObjectReference targetReference) { //IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref courierTier, default(ForPrimitives)); int num = (int)commandType; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteNetworkSerializable(ref targetReference); } private static void OnReceivePointerCommand(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); int courierTier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref courierTier, default(ForPrimitives)); int commandType = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref commandType, default(ForPrimitives)); NetworkObjectReference targetReference = default(NetworkObjectReference); ((FastBufferReader)(ref reader)).ReadNetworkSerializable(ref targetReference); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && senderClientId != 0L) { PlayerControllerB val = ResolvePlayer(playerId) ?? ResolvePlayerByActualClientId(senderClientId); if (!((Object)(object)val == (Object)null)) { playerId = (int)val.playerClientId; if (HandlePointerCommand(playerId, courierTier, (CourierCommandType)commandType, targetReference)) { BroadcastPointerCommand(playerId, courierTier, (CourierCommandType)commandType, targetReference); } } } else if (!((Object)(object)NetworkManager.Singleton != (Object)null) || senderClientId != NetworkManager.Singleton.LocalClientId) { ApplyPointerCommandBroadcast(playerId, courierTier, (CourierCommandType)commandType, targetReference); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed pointer command: " + ex.Message)); } } } private static void ApplyPointerCommandBroadcast(int playerId, int courierTier, CourierCommandType commandType, NetworkObjectReference targetReference) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = ResolvePlayer(playerId); if ((Object)(object)val == (Object)null || (Object)(object)_droneVisual == (Object)null || _droneDestroyedThisRound) { return; } switch (commandType) { case CourierCommandType.PointerAttack: { if (TryResolvePointerAttackTarget(targetReference, out var enemy)) { StartPointerAttack(val, enemy, courierTier); } break; } case CourierCommandType.PointerFetch: { if (TryResolvePointerFetchTarget(targetReference, out var item)) { StartPointerFetch(val, item, courierTier); } break; } } } private static void SendRequest(int playerId, CourierCommandType commandType) { //IL_002b: 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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); int tier = CourierDroneUpgrade.GetTier(); ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); tier = (int)commandType; ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("TechnicianCourier_Request", 0uL, val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); int courierTierOverride = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref courierTierOverride, default(ForPrimitives)); int commandType = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref commandType, default(ForPrimitives)); CourierCommand command = BuildCommand(ResolvePlayer(playerId) ?? ResolvePlayerByActualClientId(senderClientId), (CourierCommandType)commandType, courierTierOverride); ApplyCommand(command); BroadcastCommand(command); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed request: " + ex.Message)); } } } private static void BroadcastCommand(CourierCommand command) { //IL_0054: 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_006a: 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_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_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_0205: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null || command == null) { return; } int count = command.Items.Count; FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(72 + count * 36, (Allocator)2, -1); try { int type = (int)command.Type; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref type, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref command.PlayerId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref command.CourierTier, default(ForPrimitives)); type = BuildCommandFlags(command); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref type, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref count, default(ForPrimitives)); type = (_droneIsInside ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref type, default(ForPrimitives)); WriteVector(ref writer, command.DroneStartPosition.x, command.DroneStartPosition.y, command.DroneStartPosition.z); WriteVector(ref writer, command.OutsideEntrancePosition.x, command.OutsideEntrancePosition.y, command.OutsideEntrancePosition.z); WriteVector(ref writer, command.InsideEntrancePosition.x, command.InsideEntrancePosition.y, command.InsideEntrancePosition.z); WriteVector(ref writer, command.DropPosition.x, command.DropPosition.y, command.DropPosition.z); for (int i = 0; i < count; i++) { CourierItemMove courierItemMove = command.Items[i]; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref courierItemMove.NetworkObjectId, default(ForPrimitives)); type = (command.Items[i].PickupIsInFactory ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref type, default(ForPrimitives)); WriteVector(ref writer, command.Items[i].PickupPosition.x, command.Items[i].PickupPosition.y, command.Items[i].PickupPosition.z); WriteVector(ref writer, command.Items[i].DropPosition.x, command.Items[i].DropPosition.y, command.Items[i].DropPosition.z); } NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_Command", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastDroneState() { //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_0031: 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_004c: 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_0067: 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_0082: 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_009a: 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_00b5: 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_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } Vector3 val = CurrentDroneGroundPositionOr(_droneGroundPosition); FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(32, (Allocator)2, -1); try { ((FastBufferWriter)(ref writer)).WriteValueSafe(ref _droneHealth, default(ForPrimitives)); int num = (_droneDestroyedThisRound ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); num = (_droneIsInside ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); num = (int)_mode; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); num = (_flashlightEnabled ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); WriteVector(ref writer, val.x, val.y, val.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_State", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastDroneDeath(Vector3 groundPosition, bool isInside) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(16, (Allocator)2, -1); try { int num = (isInside ? 1 : 0); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); WriteVector(ref writer, groundPosition.x, groundPosition.y, groundPosition.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_Death", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastDroneHit(int damageAmount, bool bigHit, int healthAfter) { //IL_0038: 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_004a: 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_005c: 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_0077: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(9, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref damageAmount, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref bigHit, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref healthAfter, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_Hit", val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void BroadcastDroneFlame(Vector3 position) { //IL_0034: 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_0040: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(12, (Allocator)2, -1); try { WriteVector(ref writer, position.x, position.y, position.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_Flame", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastGrenadeLaunch(int grenadeId, Vector3 start, Vector3 velocity) { //IL_0038: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_006b: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(28, (Allocator)2, -1); try { ((FastBufferWriter)(ref writer)).WriteValueSafe(ref grenadeId, default(ForPrimitives)); WriteVector(ref writer, start.x, start.y, start.z); WriteVector(ref writer, velocity.x, velocity.y, velocity.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_GrenadeLaunch", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void BroadcastGrenadeExplosion(int grenadeId, Vector3 position) { //IL_0038: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref writer)).WriteValueSafe(ref grenadeId, default(ForPrimitives)); WriteVector(ref writer, position.x, position.y, position.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("TechnicianCourier_GrenadeExplode", writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void WriteManualPosePayload(ref FastBufferWriter writer, int playerId, int activeFlag, int insideFlag, Vector3 position, float yaw) { //IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref activeFlag, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref insideFlag, default(ForPrimitives)); WriteVector(ref writer, position.x, position.y, position.z); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref yaw, default(ForPrimitives)); } private static void WriteManualPickupPayload(ref FastBufferWriter writer, int playerId, int insideFlag, ulong itemId, Vector3 pickup, Vector3 drop) { //IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_005d: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref insideFlag, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref itemId, default(ForPrimitives)); WriteVector(ref writer, pickup.x, pickup.y, pickup.z); WriteVector(ref writer, drop.x, drop.y, drop.z); } private static void BroadcastManualPose(bool active) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0074: 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) //IL_008d: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } Vector3 position = (((Object)(object)_droneVisual != (Object)null) ? _droneVisual.transform.position : Vector3.zero); FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(28, (Allocator)2, -1); try { WriteManualPosePayload(ref writer, (_manualControlPlayerId >= 0) ? _manualControlPlayerId : _ownerPlayerId, active ? 1 : 0, _droneIsInside ? 1 : 0, position, _manualYaw); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("TechnicianCourier_ManualPose", writer, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("TechnicianCourier_ManualPose", 0uL, writer, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: manual pose send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void RelayManualPose(ulong excludeClientId, int playerId, int activeFlag, int insideFlag, Vector3 position, float yaw) { //IL_005a: 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) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter writer = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref writer))..ctor(28, (Allocator)2, -1); try { WriteManualPosePayload(ref writer, playerId, activeFlag, insideFlag, position, yaw); val.SendNamedMessage("TechnicianCourier_ManualPose", connectedClientsId, writer, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"CourierDronePatch: manual pose relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } } private static void BroadcastManualPickup(CourierItemMove move) { //IL_0054: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(40, (Allocator)2, -1); try { WriteManualPickupPayload(ref writer, (_manualControlPlayerId >= 0) ? _manualControlPlayerId : _ownerPlayerId, move.PickupIsInFactory ? 1 : 0, move.NetworkObjectId, move.PickupPosition, move.DropPosition); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("TechnicianCourier_ManualPickup", writer, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("TechnicianCourier_ManualPickup", 0uL, writer, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: manual pickup send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void RelayManualPickup(ulong excludeClientId, int playerId, int insideFlag, ulong itemId, Vector3 pickup, Vector3 drop) { //IL_005a: 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_006a: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter writer = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref writer))..ctor(40, (Allocator)2, -1); try { WriteManualPickupPayload(ref writer, playerId, insideFlag, itemId, pickup, drop); val.SendNamedMessage("TechnicianCourier_ManualPickup", connectedClientsId, writer, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"CourierDronePatch: manual pickup relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } } private static void SendManualFireRequest(int playerId, ManualFireKind fireKind, Vector3 targetPosition) { //IL_0038: 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_004c: 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_005a: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsClient || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter writer = default(FastBufferWriter); ((FastBufferWriter)(ref writer))..ctor(20, (Allocator)2, -1); try { ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerId, default(ForPrimitives)); int num = (int)fireKind; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref num, default(ForPrimitives)); WriteVector(ref writer, targetPosition.x, targetPosition.y, targetPosition.z); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("TechnicianCourier_ManualFire", 0uL, writer, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref writer)).Dispose(); } } private static void OnReceiveCommand(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0087: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_018e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int type = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref type, default(ForPrimitives)); int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); int courierTier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref courierTier, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); int num3 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); CourierCommand courierCommand = new CourierCommand { Type = (CourierCommandType)type, PlayerId = playerId, CourierTier = courierTier, PlayerWasInside = ((num & 1) != 0), DropIsInShip = ((num & 2) != 0), DropIsInFactory = ((num & 4) != 0), FlashlightEnabled = ((num & 8) != 0), DroneStartPosition = ReadVector(ref reader), OutsideEntrancePosition = ReadVector(ref reader), InsideEntrancePosition = ReadVector(ref reader), DropPosition = ReadVector(ref reader) }; courierCommand.EntrancePosition = (courierCommand.PlayerWasInside ? FirstNonZero(courierCommand.InsideEntrancePosition, courierCommand.OutsideEntrancePosition) : FirstNonZero(courierCommand.OutsideEntrancePosition, courierCommand.InsideEntrancePosition)); ulong networkObjectId = default(ulong); int num4 = default(int); for (int i = 0; i < num2; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref networkObjectId, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); Vector3 pickupPosition = ReadVector(ref reader); Vector3 dropPosition = ReadVector(ref reader); courierCommand.Items.Add(new CourierItemMove(networkObjectId, pickupPosition, dropPosition, (num4 & 1) != 0)); } if ((Object)(object)_droneVisual == (Object)null) { _droneIsInside = num3 != 0; } ApplyCommand(courierCommand); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed command: " + ex.Message)); } } } private static void OnReceiveState(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); int num3 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); int mode = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref mode, default(ForPrimitives)); int num4 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); Vector3 val = ReadVector(ref reader); bool droneDestroyedThisRound = _droneDestroyedThisRound; _droneHealth = Mathf.Clamp(num, 0, 30); _droneDestroyedThisRound = num2 != 0; _droneIsInside = num3 != 0; _mode = (DroneMode)mode; ApplyFlashlightState(num4 != 0); if (val != Vector3.zero) { _droneGroundPosition = val; } if (_droneDestroyedThisRound) { DestroyDroneLocal(!droneDestroyedThisRound, notifyOwner: false); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed state sync: " + ex.Message)); } } } private static void OnReceiveDeath(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); Vector3 val = ReadVector(ref reader); bool droneDestroyedThisRound = _droneDestroyedThisRound; _droneHealth = 0; _droneDestroyedThisRound = true; _droneIsInside = num != 0; if (val != Vector3.zero) { _droneGroundPosition = val; } DestroyDroneLocal(!droneDestroyedThisRound, notifyOwner: false); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed death sync: " + ex.Message)); } } } private static void OnReceiveHit(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0034: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int damageAmount = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref damageAmount, default(ForPrimitives)); bool bigHit = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref bigHit, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); _droneHealth = Mathf.Clamp(num, 0, 30); PlayDroneHitLocal(damageAmount, bigHit, _droneHealth); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed hit sync: " + ex.Message)); } } } private static void OnReceiveFlame(ulong senderClientId, FastBufferReader reader) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { PlayDroneFlameLocal(ReadVector(ref reader)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed flame sync: " + ex.Message)); } } } private static void OnReceiveGrenadeLaunch(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int grenadeId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref grenadeId, default(ForPrimitives)); Vector3 start = ReadVector(ref reader); Vector3 velocity = ReadVector(ref reader); PlayGrenadeLaunchLocal(grenadeId, start, velocity); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed grenade launch sync: " + ex.Message)); } } } private static void OnReceiveGrenadeExplosion(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int grenadeId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref grenadeId, default(ForPrimitives)); Vector3 position = ReadVector(ref reader); PlayGrenadeExplosionLocal(grenadeId, position); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed grenade explosion sync: " + ex.Message)); } } } private static void OnReceiveManualPose(ulong senderClientId, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_017d: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: 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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0127: 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_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && senderClientId == singleton.LocalClientId) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); int num3 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); Vector3 val = ReadVector(ref reader); float num4 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { PlayerControllerB val2 = ResolvePlayerByActualClientId(senderClientId); if ((Object)(object)val2 == (Object)null) { return; } num = (int)val2.playerClientId; RelayManualPose(senderClientId, num, num2, num3, val, num4); } if (_manualControlActive) { return; } if (num2 == 0) { if (_mode == DroneMode.ManualControl && (Object)(object)_droneVisual != (Object)null && !_droneDestroyedThisRound) { _mode = DroneMode.IdleAtPlayer; StartIdleFollow(++_routeVersion); } } else if (!_droneDestroyedThisRound && !(val == Vector3.zero)) { if ((Object)(object)_droneVisual == (Object)null) { EnsureDroneVisualAt(ResampleGroundPoint(val, _droneGroundPosition)); } _ownerPlayerId = num; _ownerCourierTier = Mathf.Max(_ownerCourierTier, 3); _droneIsInside = num3 != 0; _mode = DroneMode.ManualControl; Vector3 position = _droneVisual.transform.position; _droneVisual.transform.position = val; _droneGroundPosition = ResolveManualGroundPosition(val); Quaternion val3 = Quaternion.Euler(0f, num4, 0f); _droneVisual.transform.rotation = Quaternion.Slerp(_droneVisual.transform.rotation, val3, Mathf.Clamp01(Time.deltaTime * 7.5f)); Vector3 val4 = val - position; if (((Vector3)(ref val4)).sqrMagnitude > 0.001f) { FaceTravelDirection(_droneVisual.transform, val.x - position.x, val.y - position.y, val.z - position.z); } UpdateCarriedItemTransforms(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed manual pose sync: " + ex.Message)); } } } private static void OnReceiveManualPickup(ulong senderClientId, FastBufferReader reader) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_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_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && senderClientId == singleton.LocalClientId) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); int num2 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); ulong num3 = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); Vector3 val = ReadVector(ref reader); Vector3 val2 = ReadVector(ref reader); if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { PlayerControllerB val3 = ResolvePlayerByActualClientId(senderClientId); if ((Object)(object)val3 == (Object)null) { return; } num = (int)val3.playerClientId; RelayManualPickup(senderClientId, num, num2, num3, val, val2); } if (!_droneDestroyedThisRound && !IsCargoWeightFull() && !IsAlreadyCarried(num3)) { GrabbableObject val4 = ResolveItem(num3); if (!((Object)(object)val4 == (Object)null) && !WouldExceedCargoWeight(val4, GetCarriedCargoWeightPounds())) { _ownerPlayerId = num; _droneIsInside = num2 != 0; CourierItemMove itemMove = new CourierItemMove(num3, val, val2, _droneIsInside); _manualPickupLockedUntil = Time.time + 1.25f; StartCoroutineOnAvailableHost(MagnetPickUpScrap(itemMove, itemMove.PickupIsInFactory, val4, _routeVersion)); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed manual pickup sync: " + ex.Message)); } } } private static void OnReceiveManualFire(ulong senderClientId, FastBufferReader reader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); int fireKind = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref fireKind, default(ForPrimitives)); Vector3 targetPosition = ReadVector(ref reader); PlayerControllerB val = ResolvePlayer(playerId) ?? ResolvePlayerByActualClientId(senderClientId); if (!((Object)(object)val == (Object)null)) { HandleManualFireRequest((int)val.playerClientId, (ManualFireKind)fireKind, targetPosition); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("CourierDronePatch: malformed manual fire request: " + ex.Message)); } } } private static int BuildCommandFlags(CourierCommand command) { int num = 0; if (command.PlayerWasInside) { num |= 1; } if (command.DropIsInShip) { num |= 2; } if (command.DropIsInFactory) { num |= 4; } if (command.FlashlightEnabled) { num |= 8; } return num; } private static void WriteVector(ref FastBufferWriter writer, float x, float y, float z) { //IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref x, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref y, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref z, default(ForPrimitives)); } private static Vector3 ReadVector(ref FastBufferReader reader) { //IL_0005: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_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_0036: Unknown result type (might be due to invalid IL or missing references) float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); return new Vector3(num, num2, num3); } } [HarmonyPatch] internal static class DeathboundPatch { private sealed class ProtectedItemState { internal PlayerControllerB Player; internal GrabbableObject Item; internal int SlotIndex; } private static bool _localDeathDropActive; private static ProtectedItemState _pendingState; [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static void PreKillPlayer(PlayerControllerB __instance) { if (ShouldProtectPlayer(__instance)) { _localDeathDropActive = true; } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { if (ShouldProtectPlayer(__instance)) { StartRestoreCoroutine(__instance, 0.15f); } _localDeathDropActive = false; } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPrefix] private static void PreDropAllHeldItems(PlayerControllerB __instance, out ProtectedItemState __state) { __state = null; if (!_localDeathDropActive || !ShouldProtectPlayer(__instance)) { return; } int num = 0; if (__instance.ItemSlots == null || num < 0 || num >= __instance.ItemSlots.Length) { return; } GrabbableObject val = __instance.ItemSlots[num]; if (!((Object)(object)val == (Object)null)) { __state = new ProtectedItemState { Player = __instance, Item = val, SlotIndex = num }; _pendingState = __state; __instance.ItemSlots[num] = null; if ((Object)(object)__instance.currentlyHeldObjectServer == (Object)(object)val) { __instance.currentlyHeldObjectServer = null; __instance.isHoldingObject = false; } } } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPostfix] private static void PostDropAllHeldItems(ProtectedItemState __state) { RestoreProtectedItem(__state, equipIfSelected: false); } [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] [HarmonyPostfix] private static void PostReviveDeadPlayers() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { StartRestoreCoroutine(val, 0.1f); } } private static bool ShouldProtectPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null || !DeathboundUpgrade.IsUnlocked()) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void StartRestoreCoroutine(PlayerControllerB player, float delaySeconds) { if (_pendingState != null && !((Object)(object)_pendingState.Player != (Object)(object)player) && (Object)(object)GameNetworkManager.Instance != (Object)null) { ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(RestoreAfterDelay(player, delaySeconds)); } } private static IEnumerator RestoreAfterDelay(PlayerControllerB player, float delaySeconds) { yield return (object)new WaitForSeconds(delaySeconds); RestoreProtectedItem(_pendingState, (Object)(object)player != (Object)null && !player.isPlayerDead); } private static void RestoreProtectedItem(ProtectedItemState state, bool equipIfSelected) { //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if (state == null || (Object)(object)state.Player == (Object)null || (Object)(object)state.Item == (Object)null) { return; } PlayerControllerB player = state.Player; GrabbableObject item = state.Item; int slotIndex = state.SlotIndex; if (player.ItemSlots != null && slotIndex >= 0 && slotIndex < player.ItemSlots.Length) { player.ItemSlots[slotIndex] = item; item.playerHeldBy = player; item.isHeld = true; item.isHeldByEnemy = false; item.grabbable = false; item.grabbableToEnemies = false; bool flag = equipIfSelected && player.currentItemSlot == slotIndex && !player.isPlayerDead; item.isPocketed = !flag; if (flag) { player.currentlyHeldObjectServer = item; player.isHoldingObject = true; } else if ((Object)(object)player.currentlyHeldObjectServer == (Object)(object)item) { player.currentlyHeldObjectServer = null; player.isHoldingObject = false; } Transform val = ResolveItemHolder(player); if ((Object)(object)val != (Object)null) { item.parentObject = val; ((Component)item).transform.SetParent(val, false); ((Component)item).transform.localPosition = Vector3.zero; ((Component)item).transform.localRotation = Quaternion.identity; } item.EnablePhysics(false); if ((Object)(object)item.propBody != (Object)null) { item.propBody.velocity = Vector3.zero; item.propBody.angularVelocity = Vector3.zero; item.propBody.isKinematic = true; item.propBody.useGravity = false; } RefreshSlotIcon(item, slotIndex); if (!player.isPlayerDead) { _pendingState = null; } } } private static Transform ResolveItemHolder(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return null; } return player.localItemHolder ?? player.serverItemHolder ?? player.leftHandItemTarget ?? ((Component)player).transform; } private static void RefreshSlotIcon(GrabbableObject item, int slot) { HUDManager instance = HUDManager.Instance; if (!((Object)(object)instance == (Object)null) && instance.itemSlotIcons != null && slot >= 0 && slot < instance.itemSlotIcons.Length) { Image val = instance.itemSlotIcons[slot]; if (!((Object)(object)val == (Object)null)) { val.sprite = (((Object)(object)item != (Object)null && (Object)(object)item.itemProperties != (Object)null) ? item.itemProperties.itemIcon : null); ((Behaviour)val).enabled = (Object)(object)val.sprite != (Object)null; } } } } [HarmonyPatch(typeof(DepositItemsDesk))] internal class DepositItemsDeskPatch { [HarmonyPatch("UpdateEffects")] [HarmonyPrefix] private static bool UpdateEffectsPrefix(DepositItemsDesk __instance) { if ((Object)(object)__instance.deskAudio == (Object)null || (Object)(object)__instance.deskObjectsContainer == (Object)null || (Object)(object)__instance.speakerAudio == (Object)null) { return false; } return true; } } [HarmonyPatch] internal static class EnemyStatusEffectPatch { [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { EnemyStatusEffects.RegisterNetworkHandlers(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { EnemyStatusEffects.ResetNetworkHandlers(); } [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] [HarmonyPostfix] private static void PostHitEnemyOnLocalClient(EnemyAI __instance, int force, PlayerControllerB playerWhoHit) { if ((Object)(object)__instance == (Object)null || force == 0) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; bool num = (Object)(object)val != (Object)null && (Object)(object)playerWhoHit == (Object)(object)val; bool flag = (Object)(object)val != (Object)null && IsHoldingFlamethrower(val); bool flag2 = (Object)(object)playerWhoHit == (Object)null && flag; bool flag3 = num || flag2; LogHitDecision(__instance, force, playerWhoHit, val, flag3, flag); ConfigEntry burningStatusEnabled = Plugin.BurningStatusEnabled; if (burningStatusEnabled == null || burningStatusEnabled.Value) { ConfigEntry burningFromFlamethrowerEnabled = Plugin.BurningFromFlamethrowerEnabled; if ((burningFromFlamethrowerEnabled == null || burningFromFlamethrowerEnabled.Value) && flag3 && flag) { LogBurnDebug($"ApplyBurning fired for enemy='{((Object)((Component)__instance).gameObject).name}' netId={((NetworkBehaviour)__instance).NetworkObjectId} force={force}."); EnemyStatusEffects.ApplyBurning(__instance, val); } } } private static bool IsHoldingFlamethrower(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null) { return false; } if (ArmoryItemProbe.IsArmoryWeapon(currentlyHeldObjectServer)) { return false; } if (NameSuggestsFlamethrower(((object)currentlyHeldObjectServer).GetType().Name)) { return true; } if (NameSuggestsFlamethrower(((Object)currentlyHeldObjectServer).name)) { return true; } Item itemProperties = currentlyHeldObjectServer.itemProperties; if ((Object)(object)itemProperties == (Object)null) { return false; } if (!NameSuggestsFlamethrower(itemProperties.itemName)) { return NameSuggestsFlamethrower(((Object)itemProperties).name); } return true; } private static bool NameSuggestsFlamethrower(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } string text = value.ToLowerInvariant(); if (!text.Contains("flamethrower") && !text.Contains("flame thrower") && !text.Contains("flame_thrower")) { return text.Contains("flame-thrower"); } return true; } private static void LogHitDecision(EnemyAI enemy, int force, PlayerControllerB playerWhoHit, PlayerControllerB localPlayer, bool isLocalHit, bool holdingFlamethrower) { if (ShouldLogBurnDebug()) { GrabbableObject val = (((Object)(object)localPlayer != (Object)null) ? localPlayer.currentlyHeldObjectServer : null); Item val2 = (((Object)(object)val != (Object)null) ? val.itemProperties : null); string text = (((Object)(object)val != (Object)null) ? ((object)val).GetType().FullName : ""); string text2 = (((Object)(object)val != (Object)null) ? ((Object)val).name : ""); string text3 = (((Object)(object)val2 != (Object)null) ? val2.itemName : ""); string text4 = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name : ""); string arg = (((Object)(object)playerWhoHit != (Object)null) ? playerWhoHit.playerClientId.ToString() : ""); string arg2 = (((Object)(object)localPlayer != (Object)null) ? localPlayer.playerClientId.ToString() : ""); LogBurnDebug($"HitEnemyOnLocalClient enemy='{((Object)((Component)enemy).gameObject).name}' netId={((NetworkBehaviour)enemy).NetworkObjectId} force={force} " + $"hitter={arg} local={arg2} isLocalHit={isLocalHit} " + $"burningEnabled={Plugin.BurningStatusEnabled?.Value ?? true} flamethrowerEnabled={Plugin.BurningFromFlamethrowerEnabled?.Value ?? true} " + "heldType='" + text + "' heldName='" + text2 + "' itemName='" + text3 + "' itemObjectName='" + text4 + "' " + $"holdingFlamethrower={holdingFlamethrower}."); } } private static bool ShouldLogBurnDebug() { if (Plugin.BurningDebugLogging != null) { return Plugin.BurningDebugLogging.Value; } return false; } private static void LogBurnDebug(string message) { if (ShouldLogBurnDebug()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[BurnDebug] " + message)); } } } } [HarmonyPatch] internal static class EscapeArtistDoubleJumpPatch { private static readonly HashSet AirJumpConsumedByPlayer = new HashSet(); internal static void OnRoundStarted() { AirJumpConsumedByPlayer.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { AirJumpConsumedByPlayer.Clear(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocallyControlled(__instance) && (__instance.isPlayerDead || ((Object)(object)__instance.thisController != (Object)null && __instance.thisController.isGrounded))) { AirJumpConsumedByPlayer.Remove(((NetworkBehaviour)__instance).NetworkObjectId); if ((Object)(object)__instance.playerBodyAnimator != (Object)null) { __instance.playerBodyAnimator.SetBool("Jumping", false); } } } [HarmonyPatch(typeof(PlayerControllerB), "Jump_performed")] [HarmonyPrefix] private static bool PreJumpPerformed(PlayerControllerB __instance) { if (!CanUseAirJump(__instance)) { return true; } UseAirJump(__instance); return false; } private static bool CanUseAirJump(PlayerControllerB player) { if (!IsLocallyControlled(player) || !PanicSlideUpgrade.HasDoubleJump()) { return false; } if ((Object)(object)player.thisController == (Object)null || player.thisController.isGrounded) { return false; } if (AirJumpConsumedByPlayer.Contains(((NetworkBehaviour)player).NetworkObjectId)) { return false; } if (player.isPlayerDead || player.isClimbingLadder || player.inSpecialInteractAnimation || player.isTypingChat || player.inTerminalMenu || player.isExhausted || player.isCrouching || player.isPlayerSliding || player.isUnderwater) { return false; } if ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) { return false; } if (player.isMovementHindered > 0 || PanicSlidePatch.IsSlideActive() || LedgeMantlePatch.IsMantleActive) { return false; } return true; } private static void UseAirJump(PlayerControllerB player) { AirJumpConsumedByPlayer.Add(((NetworkBehaviour)player).NetworkObjectId); player.fallValue = player.jumpForce; player.fallValueUncapped = player.jumpForce; player.isFallingFromJump = true; player.sprintMeter = Mathf.Clamp01(player.sprintMeter - 0.08f); if ((Object)(object)player.sprintMeterUI != (Object)null) { player.sprintMeterUI.fillAmount = player.sprintMeter; } if ((Object)(object)player.playerBodyAnimator != (Object)null) { player.playerBodyAnimator.SetBool("Jumping", true); } ((UnityEvent)(object)StartOfRound.Instance?.PlayerJumpEvent)?.Invoke(player); PlayLocalJumpAudio(player); if ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.connectedPlayersAmount != 0) { player.PlayerJumpedServerRpc(); } } private static void PlayLocalJumpAudio(PlayerControllerB player) { if ((Object)(object)player == (Object)null || (Object)(object)player.movementAudio == (Object)null || (Object)(object)StartOfRound.Instance == (Object)null) { return; } AudioClip val = StartOfRound.Instance.playerJumpSFX; if ((Object)(object)StartOfRound.Instance.unlockablesList != (Object)null && player.currentSuitID >= 0 && player.currentSuitID < StartOfRound.Instance.unlockablesList.unlockables.Count) { AudioClip jumpAudio = StartOfRound.Instance.unlockablesList.unlockables[player.currentSuitID].jumpAudio; if ((Object)(object)jumpAudio != (Object)null) { val = jumpAudio; } } if ((Object)(object)val != (Object)null) { player.movementAudio.PlayOneShot(val); } } private static bool IsLocallyControlled(PlayerControllerB player) { if ((Object)(object)player != (Object)null && ((NetworkBehaviour)player).IsOwner && player.isPlayerControlled) { return (Object)(object)player == (Object)(object)GameNetworkManager.Instance?.localPlayerController; } return false; } } [HarmonyPatch] internal static class EscapeReflexPatch { private static RawImage _vignette; private static Texture2D _vignetteTexture; [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber) { if (IsLocalPlayer(__instance) && damageNumber > 0 && !__instance.isPlayerDead && EscapeReflexUpgrade.IsUnlocked() && !EscapeReflexUpgrade.UsedThisRound && __instance.health > 0 && __instance.health <= 35) { TriggerEscapeReflex(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { ApplySpeedBoost(__instance); UpdateVignette(); } } internal static void OnRoundStarted() { ResetState(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ResetState(); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { EscapeReflexUpgrade.SpeedBoostEndTime = 0f; ApplySpeedBoost(__instance); HideVignette(); } } private static void TriggerEscapeReflex(PlayerControllerB player) { EscapeReflexUpgrade.UsedThisRound = true; EscapeReflexUpgrade.VisualEndTime = Time.unscaledTime + 1.15f; player.sprintMeter = 1f; if ((Object)(object)player.sprintMeterUI != (Object)null) { player.sprintMeterUI.fillAmount = player.sprintMeter; } int tier = EscapeReflexUpgrade.GetTier(); if (tier >= 2) { ShadowStepPatch.ActivateExternalInvisibility(player, 2f, "Escape Reflex"); } if (tier >= 3) { EscapeReflexUpgrade.SpeedBoostEndTime = Time.time + 5f; } } private static void ApplySpeedBoost(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { float num = player.movementSpeed - EscapeReflexUpgrade.AppliedSpeedBonus; float num2 = ((EscapeReflexUpgrade.HasSpeedBoost() && Time.time < EscapeReflexUpgrade.SpeedBoostEndTime && !player.isPlayerDead) ? (Mathf.Max(0f, num) * 0.15f) : 0f); player.movementSpeed = Mathf.Max(0.1f, num + num2); EscapeReflexUpgrade.AppliedSpeedBonus = num2; } } private static void ResetState() { EscapeReflexUpgrade.SpeedBoostEndTime = 0f; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && EscapeReflexUpgrade.AppliedSpeedBonus != 0f) { ApplySpeedBoost(val); } EscapeReflexUpgrade.UsedThisRound = false; EscapeReflexUpgrade.AppliedSpeedBonus = 0f; EscapeReflexUpgrade.VisualEndTime = 0f; HideVignette(); } private static void UpdateVignette() { //IL_008a: Unknown result type (might be due to invalid IL or missing references) if (Time.unscaledTime >= EscapeReflexUpgrade.VisualEndTime) { HideVignette(); return; } EnsureVignette(); if (!((Object)(object)_vignette == (Object)null)) { float num = Mathf.Clamp01((EscapeReflexUpgrade.VisualEndTime - Time.unscaledTime) / 1.15f); float num2 = Mathf.Abs(Mathf.Sin(Time.unscaledTime * 16f)) * 0.08f; ((Component)_vignette).gameObject.SetActive(true); ((Graphic)_vignette).color = new Color(0.22f, 0.95f, 0.78f, Mathf.Clamp01(num * 0.35f + num2)); } } private static void EnsureVignette() { //IL_004d: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0081: 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_00d2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_vignette != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { GameObject val = new GameObject("Y4NGZ_EscapeReflexVignette"); val.transform.SetParent(((Component)canvas).transform, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _vignette = val.AddComponent(); _vignette.texture = (Texture)(object)GetVignetteTexture(); ((Graphic)_vignette).raycastTarget = false; ((Graphic)_vignette).color = new Color(0.22f, 0.95f, 0.78f, 0f); } } } private static Texture2D GetVignetteTexture() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_003b: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteTexture != (Object)null) { return _vignetteTexture; } Texture2D val = new Texture2D(256, 256, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; float num = 127.5f; float num2 = num * 0.5f; float num3 = num - num2; Color[] array = (Color[])(object)new Color[65536]; for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num4 = (float)j - num; float num5 = (float)i - num; float num6 = Mathf.Clamp01((Mathf.Sqrt(num4 * num4 + num5 * num5) - num2) / num3); num6 *= num6; array[i * 256 + j] = new Color(1f, 1f, 1f, num6); } } val.SetPixels(array); val.Apply(false, true); _vignetteTexture = val; return _vignetteTexture; } private static void HideVignette() { if ((Object)(object)_vignette != (Object)null) { ((Component)_vignette).gameObject.SetActive(false); } } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } internal static class ExtraSlotManager { internal const int VanillaSlotCount = 4; internal const int MaximumBonusSlots = 3; internal const int PhysicalSlotCount = 7; internal const int UtilitySlotIndex = 50; private static bool _compatibilityValidated; private static bool _compatibilityErrorLogged; private static bool _externalInventoryOwnerWarningLogged; private static bool _upgradeHooked; private static int _lastCapacitySignature = int.MinValue; private static HUDManager _layoutHud; private static Vector2 _layoutCenter; private static Vector2 _layoutStep; private static Vector2 _frameSize; private static Vector2 _iconSize; private static Vector3 _frameEuler; private static Vector3 _iconEuler; private static Vector3 _frameScale; private static Vector3 _iconScale; internal static bool NativeSlotsEnabled => _compatibilityValidated; internal static void Initialize() { if (!OptionalPluginCapabilities.NativeInventoryAvailable) { DisableForHotbarPlus(); return; } if (!_upgradeHooked) { Y4NGZUpgradeManager.UpgradesChanged += RefreshCapacityImmediately; _upgradeHooked = true; } RefreshCapacityImmediately(); } internal static void Shutdown() { if (_upgradeHooked) { Y4NGZUpgradeManager.UpgradesChanged -= RefreshCapacityImmediately; _upgradeHooked = false; } _compatibilityValidated = false; _compatibilityErrorLogged = false; _externalInventoryOwnerWarningLogged = false; _lastCapacitySignature = int.MinValue; _layoutHud = null; } internal static void DisableForHotbarPlus() { _compatibilityValidated = false; if (!_externalInventoryOwnerWarningLogged) { _externalInventoryOwnerWarningLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"HotbarPlus detected: Y4NGZUpgrades remains active, while native Deeper Pockets inventory expansion, HUD slots, scroll RPC replacement, and number-key handling are disabled. Saved Deeper Pockets levels remain dormant until HotbarPlus is absent."); } } } internal static void SetScrollCompatibilityResult(bool valid, string reason = null) { _compatibilityValidated = valid; if (valid) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"Native Deeper Pockets enabled: v81 slot RPC contract validated (2/2 scroll calls replaced)."); } } else if (!_compatibilityErrorLogged) { _compatibilityErrorLogged = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("Native Deeper Pockets disabled for compatibility. Inventories will remain at four slots. " + (string.IsNullOrWhiteSpace(reason) ? "The v81 slot-switch contract did not validate." : reason))); } } } internal static int GetUnlockedSlotCount() { if (!NativeSlotsEnabled) { return 4; } return NativeInventoryModel.GetUnlockedSlotCount(ExtraSlotUpgrade.GetTier()); } internal static void EnsureAllPlayerInventories() { if (NativeSlotsEnabled && StartOfRound.Instance?.allPlayerScripts != null) { PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; for (int i = 0; i < allPlayerScripts.Length; i++) { EnsurePhysicalInventory(allPlayerScripts[i]); } } } internal static void EnsurePhysicalInventory(PlayerControllerB player) { if (NativeSlotsEnabled && player?.ItemSlots != null && player.ItemSlots.Length < 7) { GrabbableObject[] array = (GrabbableObject[])(object)new GrabbableObject[7]; Array.Copy(player.ItemSlots, array, player.ItemSlots.Length); player.ItemSlots = array; } } internal static bool TryGetFirstEmptySlot(PlayerControllerB player, GrabbableObject attemptingGrab, out int slot) { slot = -1; if (!NativeSlotsEnabled || player?.ItemSlots == null) { return false; } EnsurePhysicalInventory(player); int unlockedSlotCount = (IsAuthoritativeLocalPlayer(player) ? GetUnlockedSlotCount() : 7); bool utilitySlotAvailable = (Object)(object)player.ItemOnlySlot == (Object)null && (Object)(object)attemptingGrab != (Object)null && (Object)(object)attemptingGrab.itemProperties != (Object)null && !attemptingGrab.itemProperties.isScrap && !attemptingGrab.itemProperties.twoHanded && !attemptingGrab.itemProperties.disallowUtilitySlot; slot = NativeInventoryModel.FindFirstEmptySlot(utilitySlotAvailable, player.currentItemSlot, unlockedSlotCount, GetOccupancyMask(player)); return true; } internal static bool TryGetNextItemSlot(PlayerControllerB player, bool forward, out int slot) { slot = -1; if (!NativeSlotsEnabled || !IsAuthoritativeLocalPlayer(player) || player.ItemSlots == null) { return false; } slot = NativeInventoryModel.FindNextSelectableSlot(player.currentItemSlot, forward, GetUnlockedSlotCount(), GetOccupancyMask(player)); return true; } internal static void AllocateHudSlots(HUDManager hud) { if (!NativeSlotsEnabled || hud?.itemSlotIconFrames == null || hud.itemSlotIcons == null) { return; } if (hud.itemSlotIconFrames.Length < 4 || hud.itemSlotIcons.Length < 4) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)"Native Deeper Pockets could not allocate HUD slots: vanilla templates were unavailable."); } return; } CaptureVanillaLayout(hud); if (hud.itemSlotIconFrames.Length >= 7 && hud.itemSlotIcons.Length >= 7) { _lastCapacitySignature = int.MinValue; RefreshCapacityImmediately(); return; } Image[] array = (Image[])(object)new Image[7]; Image[] array2 = (Image[])(object)new Image[7]; Array.Copy(hud.itemSlotIconFrames, array, Math.Min(hud.itemSlotIconFrames.Length, 7)); Array.Copy(hud.itemSlotIcons, array2, Math.Min(hud.itemSlotIcons.Length, 7)); Image val = array[3] ?? array[0]; Image val2 = array2[3] ?? array2[0]; if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)"Native Deeper Pockets could not allocate HUD slots: a vanilla template was null."); } return; } for (int i = 4; i < 7; i++) { Image val3 = Object.Instantiate(val, ((Component)val).transform.parent); ((Object)val3).name = $"Y4NGZHotbarSlot{i + 1}"; ((Component)val3).transform.SetSiblingIndex(((Component)array[i - 1]).transform.GetSiblingIndex() + 1); Image val4 = ResolveClonedIcon(val3, val, val2); if ((Object)(object)val4 == (Object)null) { Object.Destroy((Object)(object)((Component)val3).gameObject); ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)"Native Deeper Pockets could not allocate HUD slots: a cloned icon was missing."); } return; } ((Object)val4).name = $"Y4NGZHotbarIcon{i + 1}"; val4.sprite = null; ((Behaviour)val4).enabled = false; array[i] = val3; array2[i] = val4; } hud.itemSlotIconFrames = array; hud.itemSlotIcons = array2; _lastCapacitySignature = int.MinValue; RefreshCapacityImmediately(); } internal static void TickLocalCapacity(PlayerControllerB player) { if (NativeSlotsEnabled && IsAuthoritativeLocalPlayer(player)) { int num = BuildCapacitySignature(player); if (num != _lastCapacitySignature || !((Object)(object)HUDManager.Instance == (Object)(object)_layoutHud)) { _lastCapacitySignature = num; RefreshLocalHudAndSelection(player); } } } internal static void BindHotbarActions(IngameKeybinds keybinds) { if (keybinds != null && OptionalPluginCapabilities.NativeInventoryAvailable) { keybinds.HotbarSlot1.performed += OnHotbarAction; keybinds.HotbarSlot2.performed += OnHotbarAction; keybinds.HotbarSlot3.performed += OnHotbarAction; keybinds.HotbarSlot4.performed += OnHotbarAction; keybinds.HotbarSlot5.performed += OnHotbarAction; keybinds.HotbarSlot6.performed += OnHotbarAction; keybinds.HotbarSlot7.performed += OnHotbarAction; } } internal static void UnbindHotbarActions(IngameKeybinds keybinds) { if (keybinds != null) { keybinds.HotbarSlot1.performed -= OnHotbarAction; keybinds.HotbarSlot2.performed -= OnHotbarAction; keybinds.HotbarSlot3.performed -= OnHotbarAction; keybinds.HotbarSlot4.performed -= OnHotbarAction; keybinds.HotbarSlot5.performed -= OnHotbarAction; keybinds.HotbarSlot6.performed -= OnHotbarAction; keybinds.HotbarSlot7.performed -= OnHotbarAction; } } internal static bool TrySelectSlot(PlayerControllerB player, int slot) { if (!NativeSlotsEnabled || !IsAuthoritativeLocalPlayer(player) || player.isPlayerDead || player.ItemSlots == null || slot < 0 || slot >= 7 || slot >= player.ItemSlots.Length || slot == player.currentItemSlot || !NativeInventoryModel.IsSelectable(slot, GetUnlockedSlotCount(), GetOccupancyMask(player)) || !CanSwitchSlotsNow(player)) { return false; } using (ScannerTransporterPatch.BeginSlotSwitchScope(player)) { ShipBuildModeManager instance = ShipBuildModeManager.Instance; if (instance != null) { instance.CancelBuildMode(true); } Animator playerBodyAnimator = player.playerBodyAnimator; if (playerBodyAnimator != null) { playerBodyAnimator.SetBool("GrabValidated", false); } player.SwitchToItemSlot(slot, (GrabbableObject)null); player.SwitchToSlotServerRpc(slot); PlayHeldItemSwitchSound(player); player.timeSinceSwitchingSlots = 0f; } return true; } internal static bool IsAuthoritativeLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = StartOfRound.Instance?.localPlayerController ?? GameNetworkManager.Instance?.localPlayerController; return (Object)(object)player == (Object)(object)val; } internal static int GetOccupancyMask(PlayerControllerB player) { int num = 0; if (player?.ItemSlots == null) { return num; } int num2 = Math.Min(player.ItemSlots.Length, 7); for (int i = 0; i < num2; i++) { if ((Object)(object)player.ItemSlots[i] != (Object)null) { num |= 1 << i; } } return num; } private static void RefreshCapacityImmediately() { if (NativeSlotsEnabled) { EnsureAllPlayerInventories(); PlayerControllerB val = StartOfRound.Instance?.localPlayerController ?? GameNetworkManager.Instance?.localPlayerController; _lastCapacitySignature = int.MinValue; if ((Object)(object)val != (Object)null) { TickLocalCapacity(val); } } } private static void RefreshLocalHudAndSelection(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } int unlockedSlotCount = GetUnlockedSlotCount(); int occupancyMask = GetOccupancyMask(player); if (player.currentItemSlot >= unlockedSlotCount && player.currentItemSlot < 7 && (occupancyMask & (1 << player.currentItemSlot)) == 0) { int highestUnlockedSlot = NativeInventoryModel.GetHighestUnlockedSlot(unlockedSlotCount); if (player.currentItemSlot != highestUnlockedSlot && CanSwitchSlotsNow(player)) { using (ScannerTransporterPatch.BeginSlotSwitchScope(player)) { player.SwitchToItemSlot(highestUnlockedSlot, (GrabbableObject)null); player.SwitchToSlotServerRpc(highestUnlockedSlot); player.timeSinceSwitchingSlots = 0f; } } } RecenterVisibleHudSlots(HUDManager.Instance, unlockedSlotCount, occupancyMask); } private static void CaptureVanillaLayout(HUDManager hud) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_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_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_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_00e1: 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_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)hud == (Object)null) && hud.itemSlotIconFrames != null && hud.itemSlotIcons != null) { Image val = hud.itemSlotIconFrames[0]; Image val2 = hud.itemSlotIconFrames[3]; Image val3 = hud.itemSlotIcons[0]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null) && !((Object)(object)val3 == (Object)null)) { _layoutHud = hud; _layoutCenter = (((Graphic)val).rectTransform.anchoredPosition + ((Graphic)val2).rectTransform.anchoredPosition) * 0.5f; _layoutStep = (((Graphic)val2).rectTransform.anchoredPosition - ((Graphic)val).rectTransform.anchoredPosition) / 3f; _frameSize = ((Graphic)val).rectTransform.sizeDelta; _iconSize = ((Graphic)val3).rectTransform.sizeDelta; _frameEuler = ((Transform)((Graphic)val).rectTransform).localEulerAngles; _iconEuler = ((Transform)((Graphic)val3).rectTransform).localEulerAngles; _frameScale = ((Transform)((Graphic)val).rectTransform).localScale; _iconScale = ((Transform)((Graphic)val3).rectTransform).localScale; } } } private static Image ResolveClonedIcon(Image clonedFrame, Image templateFrame, Image templateIcon) { if ((Object)(object)clonedFrame == (Object)null || (Object)(object)templateFrame == (Object)null || (Object)(object)templateIcon == (Object)null) { return null; } string relativePath = GetRelativePath(((Component)templateFrame).transform, ((Component)templateIcon).transform); Transform obj = (string.IsNullOrEmpty(relativePath) ? ((Component)clonedFrame).transform : ((Component)clonedFrame).transform.Find(relativePath)); if (obj == null) { return null; } return ((Component)obj).GetComponent(); } private static string GetRelativePath(Transform root, Transform child) { if ((Object)(object)root == (Object)null || (Object)(object)child == (Object)null || (Object)(object)child == (Object)(object)root) { return string.Empty; } string text = ((Object)child).name; Transform parent = child.parent; while ((Object)(object)parent != (Object)null && (Object)(object)parent != (Object)(object)root) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } if (!((Object)(object)parent == (Object)(object)root)) { return string.Empty; } return text; } private static void RecenterVisibleHudSlots(HUDManager hud, int unlocked, int occupancyMask) { //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0131: 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) if ((Object)(object)hud == (Object)null || hud.itemSlotIconFrames == null || hud.itemSlotIcons == null || hud.itemSlotIconFrames.Length < 7 || hud.itemSlotIcons.Length < 7) { return; } if ((Object)(object)_layoutHud != (Object)(object)hud) { CaptureVanillaLayout(hud); } int num = 0; for (int i = 0; i < 7; i++) { if (NativeInventoryModel.IsSelectable(i, unlocked, occupancyMask)) { num++; } } int num2 = 0; for (int j = 0; j < 7; j++) { Image val = hud.itemSlotIconFrames[j]; Image val2 = hud.itemSlotIcons[j]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val2 == (Object)null)) { bool flag = NativeInventoryModel.IsSelectable(j, unlocked, occupancyMask); ((Component)val).gameObject.SetActive(flag); if (flag) { float num3 = (float)num2 - (float)(num - 1) * 0.5f; ((Graphic)val).rectTransform.anchoredPosition = _layoutCenter + _layoutStep * num3; ((Graphic)val).rectTransform.sizeDelta = _frameSize; ((Transform)((Graphic)val).rectTransform).localEulerAngles = _frameEuler; ((Transform)((Graphic)val).rectTransform).localScale = _frameScale; ((Graphic)val2).rectTransform.sizeDelta = _iconSize; ((Transform)((Graphic)val2).rectTransform).localEulerAngles = _iconEuler; ((Transform)((Graphic)val2).rectTransform).localScale = _iconScale; num2++; } } } } private static int BuildCapacitySignature(PlayerControllerB player) { return (ExtraSlotUpgrade.GetTier() & 3) | (GetOccupancyMask(player) << 2); } private static bool CanSwitchSlotsNow(PlayerControllerB player) { if ((Object)(object)player == (Object)null || !((NetworkBehaviour)player).IsOwner || !player.isPlayerControlled || (((NetworkBehaviour)player).IsServer && !player.isHostPlayerObject) || player.isPlayerDead || player.timeSinceSwitchingSlots < 0.3f || player.isGrabbingObjectAnimation || (Object)(object)player.quickMenuManager == (Object)null || player.quickMenuManager.isMenuOpen || player.inTerminalMenu || player.inSpecialInteractAnimation || player.throwingObject || player.isTypingChat || (player.twoHanded && !ExtraSlotUpgrade.CanCarryTwoTwoHandedItems()) || player.activatingItem) { return false; } if ((player.jetpackControls || player.disablingJetpackControls) && !((Object)(object)player.currentlyHeldObjectServer == (Object)null) && !((Object)(object)player.currentlyHeldObjectServer.itemProperties == (Object)null)) { return player.currentlyHeldObjectServer.itemProperties.itemId != 13; } return true; } private static void PlayHeldItemSwitchSound(PlayerControllerB player) { GrabbableObject val = player?.currentlyHeldObjectServer; if (!((Object)(object)val?.itemProperties?.grabSFX == (Object)null)) { AudioSource component = ((Component)val).GetComponent(); if (component != null) { component.PlayOneShot(val.itemProperties.grabSFX, 0.6f); } } } private static void OnHotbarAction(CallbackContext context) { try { int num = ResolveActionSlot(Y4NGZUpgrades.Gui.Plugin.Keybinds, ((CallbackContext)(ref context)).action); if (num >= 0) { TrySelectSlot(StartOfRound.Instance?.localPlayerController ?? GameNetworkManager.Instance?.localPlayerController, num); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"Native Deeper Pockets number-key selection failed: {arg}"); } } } private static int ResolveActionSlot(IngameKeybinds keybinds, InputAction action) { if (keybinds == null || action == null) { return -1; } if (action == keybinds.HotbarSlot1) { return 0; } if (action == keybinds.HotbarSlot2) { return 1; } if (action == keybinds.HotbarSlot3) { return 2; } if (action == keybinds.HotbarSlot4) { return 3; } if (action == keybinds.HotbarSlot5) { return 4; } if (action == keybinds.HotbarSlot6) { return 5; } if (action == keybinds.HotbarSlot7) { return 6; } return -1; } } [HarmonyPatch(typeof(PlayerControllerB), "Awake")] internal static class ExtraSlotPlayerAwakePatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { ExtraSlotManager.EnsurePhysicalInventory(__instance); } } [HarmonyPatch(typeof(HUDManager), "Awake")] internal static class ExtraSlotHudAwakePatch { [HarmonyPostfix] private static void Postfix(HUDManager __instance) { ExtraSlotManager.AllocateHudSlots(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] internal static class ExtraSlotConnectPatch { [HarmonyPostfix] private static void Postfix() { ExtraSlotManager.EnsureAllPlayerInventories(); } } [HarmonyPatch(typeof(PlayerControllerB), "FirstEmptyItemSlot")] internal static class ExtraSlotFirstEmptyPatch { [HarmonyPrefix] private static bool Prefix(PlayerControllerB __instance, GrabbableObject attemptingGrab, ref int __result) { if (!ExtraSlotManager.TryGetFirstEmptySlot(__instance, attemptingGrab, out var slot)) { return true; } __result = slot; return false; } } [HarmonyPatch(typeof(PlayerControllerB), "NextItemSlot")] internal static class ExtraSlotNextItemPatch { [HarmonyPrefix] private static bool Prefix(PlayerControllerB __instance, bool forward, ref int __result) { if (!ExtraSlotManager.TryGetNextItemSlot(__instance, forward, out var slot)) { return true; } __result = slot; return false; } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class ExtraSlotCapacityTickPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { ExtraSlotManager.TickLocalCapacity(__instance); } } [HarmonyPatch] internal static class ExtraSlotScrollRpcPatch { private static MethodInfo _scrollMethod; private static MethodInfo _directionRpc; private static MethodInfo _exactSlotRpc; private static FieldInfo _currentItemSlot; [HarmonyPrepare] private static bool Prepare() { if (!OptionalPluginCapabilities.NativeInventoryAvailable) { ExtraSlotManager.DisableForHotbarPlus(); return false; } ResolveContract(); int num; if (_scrollMethod != null && _directionRpc != null && _exactSlotRpc != null && _exactSlotRpc.ReturnType == typeof(void) && !_exactSlotRpc.IsStatic && _currentItemSlot != null) { num = ((_currentItemSlot.FieldType == typeof(int)) ? 1 : 0); if (num != 0) { goto IL_0098; } } else { num = 0; } ExtraSlotManager.SetScrollCompatibilityResult(valid: false, "The exact v81 SwitchToSlotServerRpc(int) contract or scroll method was not found."); goto IL_0098; IL_0098: return (byte)num != 0; } private static void ResolveContract() { _scrollMethod = AccessTools.DeclaredMethod(typeof(PlayerControllerB), "ScrollMouse_performed", new Type[1] { typeof(CallbackContext) }, (Type[])null); _directionRpc = AccessTools.DeclaredMethod(typeof(PlayerControllerB), "SwitchItemSlotsServerRpc", new Type[1] { typeof(bool) }, (Type[])null); _exactSlotRpc = AccessTools.DeclaredMethod(typeof(PlayerControllerB), "SwitchToSlotServerRpc", new Type[1] { typeof(int) }, (Type[])null); _currentItemSlot = AccessTools.DeclaredField(typeof(PlayerControllerB), "currentItemSlot"); } [HarmonyTargetMethod] private static MethodBase TargetMethod() { if (_scrollMethod == null) { ResolveContract(); } return _scrollMethod; } [HarmonyTranspiler] private static IEnumerable Transpiler(IEnumerable instructions) { //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Expected O, but got Unknown //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Expected O, but got Unknown List list = instructions.ToList(); int num = list.Count((CodeInstruction instruction) => CodeInstructionExtensions.Calls(instruction, _directionRpc)); if (num != 2) { ExtraSlotManager.SetScrollCompatibilityResult(valid: false, $"Expected exactly two v81 boolean scroll RPC calls, but found {num}."); return list; } List list2 = new List(list.Count + num * 3); for (int num2 = 0; num2 < list.Count; num2++) { CodeInstruction val = list[num2]; if (!CodeInstructionExtensions.Calls(val, _directionRpc)) { list2.Add(val); continue; } CodeInstruction val2 = new CodeInstruction(OpCodes.Pop, (object)null); val2.labels.AddRange(val.labels); val2.blocks.AddRange(val.blocks); list2.Add(val2); list2.Add(new CodeInstruction(OpCodes.Dup, (object)null)); list2.Add(new CodeInstruction(OpCodes.Ldfld, (object)_currentItemSlot)); list2.Add(new CodeInstruction(OpCodes.Call, (object)_exactSlotRpc)); } ExtraSlotManager.SetScrollCompatibilityResult(valid: true); return list2; } } [HarmonyPatch] internal static class FieldMechanicCompanyPatch { [HarmonyPatch] internal static class FuelPumpStallChancePatch { private static bool Prepare() { return CompanyType("FuelPumpItem") != null; } private static MethodBase TargetMethod() { return AccessTools.Method(CompanyType("FuelPumpItem"), "ServerTickFill", (Type[])null, (Type[])null); } private static IEnumerable Transpiler(IEnumerable instructions) { MethodInfo getter = AccessTools.PropertyGetter(CompanyType("ShipFuelConfig"), "PumpStallChance01"); MethodInfo multiplier = AccessTools.Method(typeof(FieldMechanicCompanyPatch), "ApplyBreakChanceMultiplier", (Type[])null, (Type[])null); foreach (CodeInstruction instruction in instructions) { yield return instruction; if (getter != null && multiplier != null && CodeInstructionExtensions.Calls(instruction, getter)) { yield return new CodeInstruction(OpCodes.Call, (object)multiplier); } } } } [HarmonyPatch] internal static class CameraHackPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnCameraHackRequest; } private const string MSG_CAMERA_HACK = "Y4NGZFieldMechanic.CameraHackServerRpc"; private static bool _handlersRegistered; private static float _cameraHackHold; internal static void ResetLocalState() { _cameraHackHold = 0f; } private static bool Prepare() { return CompanyType("CCTVCamera") != null; } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)val) { return; } if (!TurretHackerUpgrade.CanHackCameras()) { _cameraHackHold = 0f; ClearCameraHackPrompt(); return; } if (__instance.isPlayerDead || __instance.isTypingChat || __instance.inTerminalMenu || __instance.inSpecialInteractAnimation || ((Object)(object)__instance.quickMenuManager != (Object)null && __instance.quickMenuManager.isMenuOpen)) { _cameraHackHold = 0f; ClearCameraHackPrompt(); return; } if (!TryFindTargetedCamera(__instance, out var cameraIndex)) { _cameraHackHold = 0f; ClearCameraHackPrompt(); return; } string text = UpgradeInteractInput.DisplayLabel(); Y4ngzPromptOverlay.SetPersistentPrompt("FieldMechanic.CameraHack", "Disable camera: Hold [" + text + "]"); if (UpgradeInteractInput.IsHeld()) { _cameraHackHold += Time.deltaTime; if (_cameraHackHold >= 1.2f) { _cameraHackHold = 0f; RequestCameraDisable(cameraIndex); ClearCameraHackPrompt(); } } else { _cameraHackHold = Mathf.MoveTowards(_cameraHackHold, 0f, Time.deltaTime * 2f); } } private static bool TryFindTargetedCamera(PlayerControllerB player, out int cameraIndex) { //IL_004b: 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_005b: Unknown result type (might be due to invalid IL or missing references) cameraIndex = -1; Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return false; } float num = ((player.grabDistance > 0f) ? player.grabDistance : 4f); RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), num, -1, (QueryTriggerInteraction)2); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num2 = 0; num2 < array.Length; num2++) { if ((Object)(object)((RaycastHit)(ref array[num2])).collider == (Object)null) { continue; } Component val2 = ResolveCameraComponent(((RaycastHit)(ref array[num2])).collider); if (!((Object)(object)val2 == (Object)null)) { int cameraIndex2 = GetCameraIndex(val2); if (cameraIndex2 < 0 || IsCameraDisabled(cameraIndex2)) { return false; } cameraIndex = cameraIndex2; return true; } } return false; } private static Component ResolveCameraComponent(Collider collider) { Type type = CompanyType("CCTVCamera"); Component val = ((type != null) ? ((Component)collider).GetComponentInParent(type) : null); if ((Object)(object)val != (Object)null) { return val; } Type type2 = CompanyType("CctvBreakableCamera"); if (type2 == null) { return null; } Component componentInParent = ((Component)collider).GetComponentInParent(type2); if ((Object)(object)componentInParent == (Object)null) { return null; } FieldInfo fieldInfo = AccessTools.Field(type2, "_camera"); if (!(fieldInfo != null)) { return null; } object? value = fieldInfo.GetValue(componentInParent); return (Component)((value is Component) ? value : null); } private static int GetCameraIndex(Component cctvCamera) { try { return (((object)cctvCamera)?.GetType().GetProperty("CameraIndex", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(cctvCamera) is int num) ? num : (-1); } catch { return -1; } } private static bool IsCameraDisabled(int cameraIndex) { return OptionalCctvBridge.IsCameraDisabled(cameraIndex); } private static bool HostTryDisableCamera(int cameraIndex) { return OptionalCctvBridge.TryDisableCamera(cameraIndex); } private static void RequestCameraDisable(int cameraIndex) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsServer) { HostTryDisableCamera(cameraIndex); } else if (singleton.CustomMessagingManager != null) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref cameraIndex, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZFieldMechanic.CameraHackServerRpc", 0uL, val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } } private static void RegisterNetworkHandlers() { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null || !NetworkManager.Singleton.IsServer) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnCameraHackRequest; if (obj == null) { HandleNamedMessageDelegate val = OnCameraHackRequest; <>O.<0>__OnCameraHackRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZFieldMechanic.CameraHackServerRpc", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[FieldMechanic] RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void OnCameraHackRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } int cameraIndex = default(int); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref cameraIndex, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[FieldMechanic] malformed camera hack request: " + ex.Message)); } return; } if (UpgradeTierSync.GetTier(senderClientId, "turret_hacker") >= 1) { HostTryDisableCamera(cameraIndex); } } } private const string CameraHackPromptKey = "FieldMechanic.CameraHack"; private static readonly Dictionary CompanyTypeCache = new Dictionary(StringComparer.Ordinal); internal static void OnRoundStarted() { ResetInteractionPrompts(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ResetInteractionPrompts(); } internal static float ApplyBreakChanceMultiplier(float chance) { return chance * TurretHackerUpgrade.GetBreakChanceMultiplier(); } private static Type CompanyType(string typeName) { if (CompanyTypeCache.TryGetValue(typeName, out var value)) { return value; } Type type = Type.GetType("Y4NGZCompany.ShipSystems.Layout." + typeName + ", Y4NGZShipSystems", throwOnError: false) ?? Type.GetType("Y4NGZCompany.ShipSystems.Fuel." + typeName + ", Y4NGZShipSystems", throwOnError: false) ?? Type.GetType("Y4NGZCompany.ShipSystems.Power." + typeName + ", Y4NGZShipSystems", throwOnError: false) ?? Type.GetType("Y4NGZCompany.Facility.Cameras." + typeName + ", LethalCCTV", throwOnError: false) ?? Type.GetType("Y4NGZCompany.Facility.Security." + typeName + ", LethalCCTV", throwOnError: false) ?? FindCompanyTypeByName(typeName); CompanyTypeCache[typeName] = type; return type; } private static Type FindCompanyTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { string text = assembly?.GetName().Name; if (!(text != "Y4NGZShipSystems") || !(text != "Y4NGZCompany") || !(text != "LethalCCTV") || !(text != "Y4NGZCore")) { Type type = FindTypeByName(assembly, typeName); if (type != null) { return type; } } } return null; } private static Type FindTypeByName(Assembly assembly, string typeName) { try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type != null && string.Equals(type.Name, typeName, StringComparison.Ordinal)) { return type; } } } catch (ReflectionTypeLoadException ex) { Type[] types2 = ex.Types; foreach (Type type2 in types2) { if (type2 != null && string.Equals(type2.Name, typeName, StringComparison.Ordinal)) { return type2; } } } catch { } return null; } private static void ResetInteractionPrompts() { CameraHackPatch.ResetLocalState(); ClearCameraHackPrompt(); } private static void ClearCameraHackPrompt() { Y4ngzPromptOverlay.ClearPersistentPrompt("FieldMechanic.CameraHack"); } } [HarmonyPatch] internal static class FieldOperationsTabletPatch { private readonly struct TabletRendererState { internal readonly Renderer Renderer; private readonly bool _enabled; private readonly bool _forceRenderingOff; private readonly ShadowCastingMode _shadowCastingMode; private readonly int _layer; internal TabletRendererState(Renderer renderer) { //IL_0045: 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) Renderer = renderer; _enabled = (Object)(object)renderer != (Object)null && renderer.enabled; _forceRenderingOff = (Object)(object)renderer != (Object)null && renderer.forceRenderingOff; _shadowCastingMode = (ShadowCastingMode)(((Object)(object)renderer != (Object)null) ? ((int)renderer.shadowCastingMode) : 0); _layer = (((Object)(object)renderer != (Object)null && (Object)(object)((Component)renderer).gameObject != (Object)null) ? ((Component)renderer).gameObject.layer : 0); } internal void Restore() { //IL_0038: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)Renderer == (Object)null)) { Renderer.enabled = _enabled; Renderer.forceRenderingOff = _forceRenderingOff; Renderer.shadowCastingMode = _shadowCastingMode; if ((Object)(object)((Component)Renderer).gameObject != (Object)null) { ((Component)Renderer).gameObject.layer = _layer; } } } } [CompilerGenerated] private static class <>O { public static Action <0>__FireTabletActionGesture; public static HandleNamedMessageDelegate <1>__OnReceiveTabletStart; public static HandleNamedMessageDelegate <2>__OnReceiveTabletStop; } private const string PackId = "y4ngz.upgrades.field_operations_tablet"; private const string InteractionId = "y4ngz.drone_tablet.inspect_livebody"; private const string ManifestFileName = "y4ngz-interactions-dronetablet-livebody.manifest.json"; private const string PromptKey = "field_operations_tablet"; private const string ActionReadyBoolName = "Y4NGZ_DroneTablet_ActionReady"; private const string ActionIndexIntName = "Y4NGZ_DroneTablet_ActionIndex"; private const string ActionTriggerName = "Y4NGZ_DroneTablet_Action"; private const string MsgTabletStart = "Y4NGZ_FieldTabletStart"; private const string MsgTabletStop = "Y4NGZ_FieldTabletStop"; private const float WallRaiseEnterDistance = 1.25f; private const float WallRaiseExitDistance = 1.55f; private const float WallNormalMaxY = 0.45f; private const float WallCastRadius = 0.25f; private const float WallExtraPullDistanceWindow = 0.8f; private const float TabletOffsetLerpSpeed = 10f; private const float WallExtraPullLerpSpeed = 12f; private const float GestureRaiseSeconds = 1.2f; private const float TabletNearFocusEnd = 0.2f; private const string StowReason = "field-tablet"; private const string StowTabletCursorTip = "STOW TABLET"; private const float StowTimeoutSeconds = 900f; private static bool _packRegistered; private static bool _networkHandlersRegistered; private static bool _missingManifestLogged; private static bool _startFailureLogged; private static bool _savedDisableInteract; private static bool _savedDisableInteractValue; private static bool _wallRaiseActive; private static float _wallHitDistance = 1.55f; private static float _currentWallExtraPull; private static Vector3 _currentArmsOffset; private static bool _actionReadyApplied; private static bool _pilotActionReadyHold; private static bool _commandScreenActionReadyHold; private static float _gestureRaiseUntil; private static int _nextActionIndex = 1; private static float _nextRegistrationAttemptAt; private static InteractionAnimationHandle _activeHandle = InteractionAnimationHandle.Empty; private static readonly Dictionary RemoteHandles = new Dictionary(); private static readonly List ThirdPersonRendererStates = new List(); private static bool _thirdPersonPresentationSaved; private static HeldItemStowHandle _tabletStow; private static DepthOfField _tabletDepthOfField; private static float _savedNearFocusEnd; private static bool _savedNearFocusOverride; private static bool _ownsTabletNearFocus; private static bool _missingTabletDepthOfFieldLogged; private static string _cachedTabletPath; private static string _cachedTabletPreviousPath; private static string _cachedTabletNextPath; private static string _cachedTabletUpPath; private static string _cachedTabletDownPath; private static string _cachedTabletActivatePath; private static string _cachedTabletPrimaryPath; private static string _cachedTabletBackPath; private static string[] _cachedIdlePrompt; private static string[] _cachedCommandPrompt; private static string[] _cachedActivePrompt; private static string[] _cachedActiveHackPrompt; internal static bool IsTabletActive { get { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (((InteractionAnimationHandle)(ref _activeHandle)).IsValid) { return LCInteractionAnimationAPI.IsInteractionActive(_activeHandle); } return false; } } internal static void Initialize() { EnsurePackRegistered(); RegisterNetworkHandlers(); FieldTabletAudio.Preload(); } internal static void Shutdown() { ReleaseTabletNearFocus(); FieldTabletAudio.Shutdown(); } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } internal static void TrySetPilotActionReadyHold(bool hold) { _pilotActionReadyHold = hold; if (!hold && !_commandScreenActionReadyHold) { _gestureRaiseUntil = 0f; } ApplyActionReadyState(); } internal static void TrySetCommandScreenActionReadyHold(bool hold) { _commandScreenActionReadyHold = hold; if (!hold && !_pilotActionReadyHold) { _gestureRaiseUntil = 0f; } ApplyActionReadyState(); } private static void ApplyActionReadyState() { //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (((InteractionAnimationHandle)(ref _activeHandle)).IsValid) { bool flag = _pilotActionReadyHold || _commandScreenActionReadyHold || _wallRaiseActive || Time.unscaledTime < _gestureRaiseUntil; if (flag != _actionReadyApplied) { LCInteractionAnimationAPI.TrySetInteractionBool(_activeHandle, "Y4NGZ_DroneTablet_ActionReady", flag); _actionReadyApplied = flag; } } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { RegisterNetworkHandlers(); ClearInactiveHandle(__instance); ClearInactiveRemoteHandles(); bool num = UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.FieldTablet); UpdateTabletPrompt(__instance); FieldTabletScreenRuntime.TickUplinkState(__instance); if (num) { ToggleTablet(__instance); } if (IsTabletActive) { MaintainTabletNearFocus(); __instance.disableInteract = true; UpdateTabletRaise(__instance); FieldTabletScreenRuntime.UpdateActive(__instance, FireTabletActionGesture); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { ApplyTabletArmsOffset(__instance); if (IsTabletActive) { FieldTabletAudio.FollowBoundAnchor(); } UpdateLocalThirdPersonPresentation(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool BlockGrabWhileTabletActivePrefix(PlayerControllerB __instance) { if (IsTabletActive) { return !IsLocalPlayer(__instance); } return true; } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] private static bool BlockSlotScrollWhileTabletActivePrefix(PlayerControllerB __instance) { if (IsTabletActive) { return !IsLocalPlayer(__instance); } return true; } [HarmonyPatch(typeof(PlayerControllerB), "UseUtilitySlot_performed")] [HarmonyPrefix] private static bool BlockUtilitySlotWhileTabletActivePrefix(PlayerControllerB __instance) { if (IsTabletActive) { return !IsLocalPlayer(__instance); } return true; } private static void UpdateTabletRaise(PlayerControllerB player) { _wallRaiseActive = IsFacingNearbyWall(player, out _wallHitDistance); ApplyActionReadyState(); } private static bool IsFacingNearbyWall(PlayerControllerB player, out float hitDistance) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) hitDistance = 1.55f; Camera val = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null) { return false; } float num = (_wallRaiseActive ? 1.55f : 1.25f); int num2 = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMask : (-5)); RaycastHit val2 = default(RaycastHit); if (!Physics.SphereCast(((Component)val).transform.position, 0.25f, ((Component)val).transform.forward, ref val2, num, num2, (QueryTriggerInteraction)1)) { return false; } if (Mathf.Abs(((RaycastHit)(ref val2)).normal.y) >= 0.45f) { return false; } hitDistance = ((RaycastHit)(ref val2)).distance; return true; } private static float CalculateWallExtraPull() { float num = 0f; if (_wallRaiseActive) { num = Mathf.Clamp01((1.25f - _wallHitDistance) / 0.8f) * Plugin.GetWallMaxExtraPullMeters(); } _currentWallExtraPull = Mathf.Lerp(_currentWallExtraPull, num, SmoothFactor(12f)); return _currentWallExtraPull; } private static void ApplyTabletArmsOffset(PlayerControllerB player) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0097: 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) //IL_00a3: 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) Transform val = (((Object)(object)player != (Object)null) ? player.localArmsTransform : null); Camera val2 = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { _currentArmsOffset = Vector3.zero; return; } Vector3 val3 = Vector3.zero; if (IsTabletActive) { bool actionReadyApplied = _actionReadyApplied; float num = (actionReadyApplied ? Plugin.GetTabletRaisedPullInMeters() : Plugin.GetTabletPullInMeters()) + CalculateWallExtraPull(); float num2 = (actionReadyApplied ? 0f : Plugin.GetTabletPullUpMeters()); val3 = -((Component)val2).transform.forward * num + ((Component)val2).transform.up * num2; } else { _currentWallExtraPull = Mathf.Lerp(_currentWallExtraPull, 0f, SmoothFactor(12f)); } _currentArmsOffset = Vector3.Lerp(_currentArmsOffset, val3, SmoothFactor(10f)); if (((Vector3)(ref _currentArmsOffset)).sqrMagnitude > 1E-06f) { val.position += _currentArmsOffset; } } private static float SmoothFactor(float speed) { return 1f - Mathf.Exp((0f - Mathf.Max(0.01f, speed)) * Mathf.Max(0.0001f, Time.deltaTime)); } private static void AcquireTabletNearFocus() { if (_ownsTabletNearFocus) { MaintainTabletNearFocus(); return; } try { VolumeProfile val = (((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.playerGraphicsVolume != (Object)null) ? HUDManager.Instance.playerGraphicsVolume.sharedProfile : null); DepthOfField val2 = default(DepthOfField); if ((Object)(object)val == (Object)null || !val.TryGet(ref val2) || (Object)(object)val2 == (Object)null) { if (!_missingTabletDepthOfFieldLogged) { _missingTabletDepthOfFieldLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Field Tablet] player graphics DepthOfField was not available; near-focus ownership will retry."); } } return; } _tabletDepthOfField = val2; _savedNearFocusEnd = ((VolumeParameter)(object)val2.nearFocusEnd).value; _savedNearFocusOverride = ((VolumeParameter)val2.nearFocusEnd).overrideState; _ownsTabletNearFocus = true; _missingTabletDepthOfFieldLogged = false; MaintainTabletNearFocus(); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)($"[Field Tablet] near focus acquired saved={_savedNearFocusEnd:0.000}m " + $"override={_savedNearFocusOverride} tablet={0.2f:0.000}m")); } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogDebug((object)("[Field Tablet] near-focus acquire failed: " + ex.Message)); } } } private static void MaintainTabletNearFocus() { if (!_ownsTabletNearFocus) { AcquireTabletNearFocus(); return; } if ((Object)(object)_tabletDepthOfField == (Object)null) { _ownsTabletNearFocus = false; AcquireTabletNearFocus(); return; } ((VolumeParameter)_tabletDepthOfField.nearFocusEnd).overrideState = true; if (!Mathf.Approximately(((VolumeParameter)(object)_tabletDepthOfField.nearFocusEnd).value, 0.2f)) { ((VolumeParameter)(object)_tabletDepthOfField.nearFocusEnd).value = 0.2f; } } private static void ReleaseTabletNearFocus() { if (!_ownsTabletNearFocus) { return; } DepthOfField tabletDepthOfField = _tabletDepthOfField; float savedNearFocusEnd = _savedNearFocusEnd; bool savedNearFocusOverride = _savedNearFocusOverride; _tabletDepthOfField = null; _ownsTabletNearFocus = false; _savedNearFocusEnd = 0f; _savedNearFocusOverride = false; try { if (!((Object)(object)tabletDepthOfField == (Object)null)) { ((VolumeParameter)(object)tabletDepthOfField.nearFocusEnd).value = savedNearFocusEnd; ((VolumeParameter)tabletDepthOfField.nearFocusEnd).overrideState = savedNearFocusOverride; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Field Tablet] near focus restored value={savedNearFocusEnd:0.000}m override={savedNearFocusOverride}"); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogDebug((object)("[Field Tablet] near-focus restore failed: " + ex.Message)); } } } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { SendTabletState("Y4NGZ_FieldTabletStop"); StopTabletImmediate(); StopAllRemoteTablets((InteractionAnimationStopReason)7); FieldTabletScreenRuntime.ResetUplinkState(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { StopTabletImmediate(); StopAllRemoteTablets((InteractionAnimationStopReason)7); FieldTabletScreenRuntime.ResetUplinkState(); _networkHandlersRegistered = false; _packRegistered = false; } private static void ToggleTablet(PlayerControllerB player) { if (IsTabletActive) { CourierDronePatch.StopLocalPilotMode(notifyOwner: false); BeginTabletExit(player); } else { TryStartTablet(player); } } private static void UpdateTabletPrompt(PlayerControllerB player) { if (!FieldOperationsUpgrade.IsUnlocked() || (Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat || player.inTerminalMenu || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("field_operations_tablet"); Y4ngzPromptOverlay.SetCursorTipOverride(null); return; } IngameKeybinds keybinds = Y4NGZUpgrades.Gui.Plugin.Keybinds; string text = UpgradeInput.EffectivePath(keybinds?.FieldTablet); string text2 = UpgradeInput.EffectivePath(keybinds?.TabletPreviousTab); string text3 = UpgradeInput.EffectivePath(keybinds?.TabletNextTab); string text4 = UpgradeInput.EffectivePath(keybinds?.TabletUp); string text5 = UpgradeInput.EffectivePath(keybinds?.TabletDown); string text6 = UpgradeInput.EffectivePath(keybinds?.TabletActivate); string text7 = UpgradeInput.EffectivePath(keybinds?.TabletPrimaryAction); string text8 = UpgradeInput.EffectivePath(keybinds?.TabletBack); if (_cachedIdlePrompt == null || !string.Equals(_cachedTabletPath, text, StringComparison.Ordinal) || !string.Equals(_cachedTabletPreviousPath, text2, StringComparison.Ordinal) || !string.Equals(_cachedTabletNextPath, text3, StringComparison.Ordinal) || !string.Equals(_cachedTabletUpPath, text4, StringComparison.Ordinal) || !string.Equals(_cachedTabletDownPath, text5, StringComparison.Ordinal) || !string.Equals(_cachedTabletActivatePath, text6, StringComparison.Ordinal) || !string.Equals(_cachedTabletPrimaryPath, text7, StringComparison.Ordinal) || !string.Equals(_cachedTabletBackPath, text8, StringComparison.Ordinal)) { _cachedTabletPath = text; _cachedTabletPreviousPath = text2; _cachedTabletNextPath = text3; _cachedTabletUpPath = text4; _cachedTabletDownPath = text5; _cachedTabletActivatePath = text6; _cachedTabletPrimaryPath = text7; _cachedTabletBackPath = text8; string text9 = UpgradeInput.DisplayLabel(keybinds?.FieldTablet, "Y"); string text10 = UpgradeInput.DisplayPair(keybinds?.TabletPreviousTab, "LEFT", keybinds?.TabletNextTab, "RIGHT"); string text11 = UpgradeInput.DisplayPair(keybinds?.TabletUp, "UP", keybinds?.TabletDown, "DOWN"); string text12 = UpgradeInput.DisplayLabel(keybinds?.TabletActivate, "ENTER"); string text13 = UpgradeInput.DisplayPair(keybinds?.TabletActivate, "ENTER", keybinds?.TabletPrimaryAction, "LMB"); string text14 = UpgradeInput.DisplayLabel(keybinds?.TabletBack, "BKSP"); string text15 = "Tablet: [" + text9 + "] Stow"; string text16 = "[" + text10 + "] Tabs [" + text11 + "] Select"; _cachedIdlePrompt = new string[1] { "Tablet: [" + text9 + "]" }; _cachedCommandPrompt = new string[4] { text15, "[" + text11 + "] Select", "[" + text12 + "] Execute", "[" + text14 + "] Back" }; _cachedActivePrompt = new string[4] { text15, text16, "[" + text12 + "] Activate", "[" + text14 + "] Back" }; _cachedActiveHackPrompt = new string[4] { text15, text16, "[" + text13 + "] Splice", "[" + text14 + "] Back" }; } if (!IsTabletActive) { Y4ngzPromptOverlay.SetPostPlayerMenuPromptLines("field_operations_tablet", _cachedIdlePrompt); Y4ngzPromptOverlay.SetCursorTipOverride(null); return; } Y4ngzPromptOverlay.SetCursorTipOverride("STOW TABLET"); if (FieldTabletScreenRuntime.IsCommandScreenOpen) { Y4ngzPromptOverlay.SetPostPlayerMenuPromptLines("field_operations_tablet", _cachedCommandPrompt); } else { Y4ngzPromptOverlay.SetPostPlayerMenuPromptLines("field_operations_tablet", FieldTabletScreenRuntime.HasHackableTarget ? _cachedActiveHackPrompt : _cachedActivePrompt); } } private static void TryStartTablet(PlayerControllerB player) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) if (!FieldOperationsUpgrade.IsUnlocked() || !CanUse(player)) { return; } if (!EnsurePackRegistered()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Field Tablet] Animation pack is not ready."); } } else { if (!TryPocketHeldItem(player)) { return; } InteractionAnimationHandle activeHandle = default(InteractionAnimationHandle); string text = default(string); if (!LCInteractionAnimationAPI.TryStartInteraction(new InteractionAnimationRequest { Player = player, PackId = "y4ngz.upgrades.field_operations_tablet", InteractionId = "y4ngz.drone_tablet.inspect_livebody" }, ref activeHandle, ref text)) { RestorePocketedItem(player); RestoreInteractInput(player); if (!_startFailureLogged) { _startFailureLogged = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Field Tablet] start rejected: " + text)); } } } else { _activeHandle = activeHandle; _nextActionIndex = 1; _startFailureLogged = false; AcquireTabletNearFocus(); FieldTabletScreenRuntime.OnTabletOpened(); FieldTabletAudio.QueueEquip(); SaveAndSuppressInteractInput(player); SendTabletState("Y4NGZ_FieldTabletStart"); } } } private static void BeginTabletExit(PlayerControllerB player) { //IL_001c: 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) if (!((InteractionAnimationHandle)(ref _activeHandle)).IsValid) { return; } FieldTabletAudio.PlayEquip(); SendTabletState("Y4NGZ_FieldTabletStop"); string text = default(string); if (!LCInteractionAnimationAPI.TryBeginInteractionExit(_activeHandle, ref text)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] graceful exit rejected: " + text)); } LCInteractionAnimationAPI.TryStopInteraction(_activeHandle, (InteractionAnimationStopReason)0); ClearInactiveHandle(player); } } private static void StopTabletImmediate() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (((InteractionAnimationHandle)(ref _activeHandle)).IsValid) { LCInteractionAnimationAPI.TryStopInteraction(_activeHandle, (InteractionAnimationStopReason)7); } ClearTabletState(GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController); } private static void ClearInactiveHandle(PlayerControllerB player) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) if (((InteractionAnimationHandle)(ref _activeHandle)).IsValid && !LCInteractionAnimationAPI.IsInteractionActive(_activeHandle)) { ClearTabletState(player); } } private static void ClearTabletState(PlayerControllerB player) { //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) RestoreLocalThirdPersonPresentation(player); CourierDronePatch.StopLocalPilotMode(notifyOwner: false); _activeHandle = InteractionAnimationHandle.Empty; ReleaseTabletNearFocus(); FieldTabletScreenRuntime.Destroy(); RestorePocketedItem(player); RestoreInteractInput(player); Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("field_operations_tablet"); Y4ngzPromptOverlay.SetCursorTipOverride(null); _nextActionIndex = 1; _wallRaiseActive = false; _wallHitDistance = 1.55f; _currentWallExtraPull = 0f; _actionReadyApplied = false; _pilotActionReadyHold = false; _commandScreenActionReadyHold = false; _gestureRaiseUntil = 0f; } private static bool EnsurePackRegistered() { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //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_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown if (_packRegistered) { return true; } if (Time.realtimeSinceStartup < _nextRegistrationAttemptAt) { return false; } _nextRegistrationAttemptAt = Time.realtimeSinceStartup + 2f; string consumerAssetRoot = GetConsumerAssetRoot(); string text = Path.Combine(consumerAssetRoot, "y4ngz-interactions-dronetablet-livebody.manifest.json"); if (!File.Exists(text)) { if (!_missingManifestLogged) { _missingManifestLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] manifest not found: " + text)); } } return false; } string manifestJson; try { manifestJson = File.ReadAllText(text); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Field Tablet] manifest read failed: " + ex.Message)); } return false; } InteractionAnimationPackDefinition val = new InteractionAnimationPackDefinition(); val.PackId = "y4ngz.upgrades.field_operations_tablet"; val.Version = "1.0.0"; val.AssetRootPath = consumerAssetRoot; val.Interactions = (InteractionAnimationDefinition[])(object)new InteractionAnimationDefinition[1] { new InteractionAnimationDefinition { InteractionId = "y4ngz.drone_tablet.inspect_livebody", PresentationKind = (InteractionAnimationPresentationKind)1, ManifestJson = manifestJson } }; string text2 = default(string); if (!LCInteractionAnimationAPI.TryRegisterInteractionPack(val, ref text2)) { if (string.Equals(text2, "pack_already_registered", StringComparison.OrdinalIgnoreCase)) { _packRegistered = true; return true; } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Field Tablet] pack registration failed: " + text2)); } return false; } _packRegistered = true; ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)"[Field Tablet] registered Interactions animation pack."); } return true; } private static string GetConsumerAssetRoot() { return Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? string.Empty; } private static void FireTabletActionGesture() { //IL_000d: 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_0033: Unknown result type (might be due to invalid IL or missing references) if (((InteractionAnimationHandle)(ref _activeHandle)).IsValid) { LCInteractionAnimationAPI.TrySetInteractionBool(_activeHandle, "Y4NGZ_DroneTablet_ActionReady", true); LCInteractionAnimationAPI.TrySetInteractionInt(_activeHandle, "Y4NGZ_DroneTablet_ActionIndex", _nextActionIndex); LCInteractionAnimationAPI.TryFireInteractionTrigger(_activeHandle, "Y4NGZ_DroneTablet_Action"); _actionReadyApplied = true; _gestureRaiseUntil = Time.unscaledTime + 1.2f; _nextActionIndex++; if (_nextActionIndex > 4) { _nextActionIndex = 1; } } } private static bool TryPocketHeldItem(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } SaveAndSuppressInteractInput(player); _tabletStow = HeldItemStowService.Begin(player, "field-tablet", 900f, disableItemActions: true, force: true); return true; } private static void RestorePocketedItem(PlayerControllerB player) { _tabletStow.Dispose(); _tabletStow = default(HeldItemStowHandle); } private static void SaveAndSuppressInteractInput(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !_savedDisableInteract) { _savedDisableInteract = true; _savedDisableInteractValue = player.disableInteract; player.disableInteract = true; } } private static void RestoreInteractInput(PlayerControllerB player) { if (_savedDisableInteract) { if ((Object)(object)player != (Object)null) { player.disableInteract = _savedDisableInteractValue; } _savedDisableInteract = false; _savedDisableInteractValue = false; } } private static bool CanUse(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu) { if (!((Object)(object)player.quickMenuManager == (Object)null)) { return !player.quickMenuManager.isMenuOpen; } return true; } return false; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void RegisterNetworkHandlers() { //IL_0035: 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_0040: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown if (_networkHandlersRegistered) { return; } NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val == null) { return; } try { object obj = <>O.<1>__OnReceiveTabletStart; if (obj == null) { HandleNamedMessageDelegate val2 = OnReceiveTabletStart; <>O.<1>__OnReceiveTabletStart = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZ_FieldTabletStart", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<2>__OnReceiveTabletStop; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnReceiveTabletStop; <>O.<2>__OnReceiveTabletStop = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZ_FieldTabletStop", (HandleNamedMessageDelegate)obj2); _networkHandlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] network handler registration failed: " + ex.Message)); } } } private static void SendTabletState(string messageName) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)val == (Object)null) && !((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { SendTabletState(messageName, val.playerClientId, singleton.IsServer ? ((ulong?)null) : new ulong?(0uL)); } } private unsafe static void SendTabletState(string messageName, ulong playerClientId, ulong? clientId) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val == null) { return; } FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref playerClientId, default(ForPrimitives)); if (clientId.HasValue) { val.SendNamedMessage(messageName, clientId.Value, val2, (NetworkDelivery)3); } else { val.SendNamedMessageToAll(messageName, val2, (NetworkDelivery)3); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnReceiveTabletStart(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); ApplyRemoteTabletStart(playerClientId); RelayTabletStateIfHost("Y4NGZ_FieldTabletStart", senderClientId, playerClientId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] malformed start message: " + ex.Message)); } } } private static void OnReceiveTabletStop(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); ApplyRemoteTabletStop(playerClientId); RelayTabletStateIfHost("Y4NGZ_FieldTabletStop", senderClientId, playerClientId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] malformed stop message: " + ex.Message)); } } } private static void RelayTabletStateIfHost(string messageName, ulong senderClientId, ulong playerClientId) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendTabletState(messageName, playerClientId, null); } } private static void ApplyRemoteTabletStart(ulong playerClientId) { //IL_004d: 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_0059: 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_0078: Expected O, but got Unknown //IL_0080: 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) PlayerControllerB val = ResolvePlayer(playerClientId); if ((Object)(object)val == (Object)null || IsLocalPlayer(val) || !EnsurePackRegistered()) { return; } if (RemoteHandles.TryGetValue(playerClientId, out var value)) { if (((InteractionAnimationHandle)(ref value)).IsValid && LCInteractionAnimationAPI.IsInteractionActive(value)) { return; } RemoteHandles.Remove(playerClientId); } InteractionAnimationHandle value2 = default(InteractionAnimationHandle); string arg = default(string); if (LCInteractionAnimationAPI.TryStartInteraction(new InteractionAnimationRequest { Player = val, PackId = "y4ngz.upgrades.field_operations_tablet", InteractionId = "y4ngz.drone_tablet.inspect_livebody" }, ref value2, ref arg)) { RemoteHandles[playerClientId] = value2; return; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[Field Tablet] remote presentation start rejected for player {playerClientId}: {arg}"); } } private static void ApplyRemoteTabletStop(ulong playerClientId) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) string text = default(string); if (RemoteHandles.TryGetValue(playerClientId, out var value) && (!((InteractionAnimationHandle)(ref value)).IsValid || !LCInteractionAnimationAPI.IsInteractionActive(value) || !LCInteractionAnimationAPI.TryBeginInteractionExit(value, ref text))) { if (((InteractionAnimationHandle)(ref value)).IsValid) { LCInteractionAnimationAPI.TryStopInteraction(value, (InteractionAnimationStopReason)0); } RemoteHandles.Remove(playerClientId); } } private static void ClearInactiveRemoteHandles() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (RemoteHandles.Count == 0) { return; } List list = new List(); foreach (KeyValuePair remoteHandle in RemoteHandles) { InteractionAnimationHandle value = remoteHandle.Value; if (!((InteractionAnimationHandle)(ref value)).IsValid || !LCInteractionAnimationAPI.IsInteractionActive(remoteHandle.Value)) { list.Add(remoteHandle.Key); } } for (int i = 0; i < list.Count; i++) { RemoteHandles.Remove(list[i]); } } private static void StopAllRemoteTablets(InteractionAnimationStopReason reason) { //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) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) foreach (InteractionAnimationHandle value in RemoteHandles.Values) { InteractionAnimationHandle current = value; if (((InteractionAnimationHandle)(ref current)).IsValid) { LCInteractionAnimationAPI.TryStopInteraction(current, reason); } } RemoteHandles.Clear(); } private static PlayerControllerB ResolvePlayer(ulong playerClientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.playerClientId == playerClientId) { return val; } } return null; } internal static void ReleaseLocalThirdPersonPresentationForDrone() { RestoreLocalThirdPersonPresentation(GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController); } private static void UpdateLocalThirdPersonPresentation(PlayerControllerB player) { if (!IsTabletActive || CourierDronePatch.IsLocalPilotModeActive || !IsThirdPersonCamera(player)) { RestoreLocalThirdPersonPresentation(player); return; } if (!_thirdPersonPresentationSaved) { _thirdPersonPresentationSaved = true; ThirdPersonRendererStates.Clear(); Renderer[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if (IsTabletRenderer(componentsInChildren[i])) { ThirdPersonRendererStates.Add(new TabletRendererState(componentsInChildren[i])); } } } int num = LayerMask.NameToLayer("Default"); if (num < 0) { num = 0; } for (int j = 0; j < ThirdPersonRendererStates.Count; j++) { Renderer renderer = ThirdPersonRendererStates[j].Renderer; if (!((Object)(object)renderer == (Object)null)) { renderer.enabled = true; renderer.forceRenderingOff = false; renderer.shadowCastingMode = (ShadowCastingMode)1; ((Component)renderer).gameObject.layer = num; } } } private static void RestoreLocalThirdPersonPresentation(PlayerControllerB player) { if (_thirdPersonPresentationSaved) { for (int i = 0; i < ThirdPersonRendererStates.Count; i++) { ThirdPersonRendererStates[i].Restore(); } ThirdPersonRendererStates.Clear(); _thirdPersonPresentationSaved = false; } } private static bool IsThirdPersonCamera(PlayerControllerB player) { if ((Object)(object)player != (Object)null) { return LedgeMantlePatch.IsDebugThirdPersonCamActive(); } return false; } private static bool IsTabletRenderer(Renderer renderer) { Transform val = (((Object)(object)renderer != (Object)null) ? ((Component)renderer).transform : null); while ((Object)(object)val != (Object)null) { string text = ((Object)val).name ?? string.Empty; if (text.IndexOf("Y4NGZ_FPSTabletProp", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Y4NGZ_DroneTablet", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("Tablet_01", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } val = val.parent; } return false; } } [HarmonyPatch] internal static class FieldTabletMainframeNet { private struct PendingTrapReenable { internal Component Trap; internal byte Kind; internal float ReenableAt; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnActionResult; public static HandleNamedMessageDelegate <1>__OnCameraDisableRequest; public static HandleNamedMessageDelegate <2>__OnAlarmRequest; public static HandleNamedMessageDelegate <3>__OnLockdownRequest; public static HandleNamedMessageDelegate <4>__OnTrapsDisableRequest; } private const string MsgCameraDisable = "Y4NGZFieldTablet.CameraDisableServerRpc"; private const string MsgAlarm = "Y4NGZFieldTablet.AlarmServerRpc"; private const string MsgLockdown = "Y4NGZFieldTablet.LockdownServerRpc"; private const string MsgTrapsDisable = "Y4NGZFieldTablet.TrapsDisableServerRpc"; private const string MsgActionResult = "Y4NGZFieldTablet.ActionResultClientRpc"; internal const byte ActionLockdownBegin = 1; internal const byte ActionLockdownEnd = 2; internal const byte ActionTraps = 3; internal const byte AlarmOpOff = 0; internal const byte AlarmOpOn = 1; internal const byte AlarmOpSilence = 2; private const float CameraDisableCooldownSeconds = 20f; private const float LockdownCooldownSeconds = 30f; private const float TrapsDisableCooldownSeconds = 90f; private const float TrapDisableFallbackSeconds = 12f; private static bool _handlersRegistered; private static float _hostCameraReadyAt; private static float _hostLockdownReadyAt; private static float _hostTrapsReadyAt; private static readonly List PendingReenables = new List(); private static bool? _companyPresent; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; PendingReenables.Clear(); _hostCameraReadyAt = 0f; _hostLockdownReadyAt = 0f; _hostTrapsReadyAt = 0f; } [HarmonyPatch(typeof(StartOfRound), "Update")] [HarmonyPostfix] private static void PostStartOfRoundUpdate() { if (PendingReenables.Count == 0) { return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { PendingReenables.Clear(); return; } float unscaledTime = Time.unscaledTime; for (int num = PendingReenables.Count - 1; num >= 0; num--) { PendingTrapReenable pendingTrapReenable = PendingReenables[num]; if (!(unscaledTime < pendingTrapReenable.ReenableAt)) { PendingReenables.RemoveAt(num); if (!((Object)(object)pendingTrapReenable.Trap == (Object)null)) { try { ToggleTrap(pendingTrapReenable.Trap, pendingTrapReenable.Kind, enable: true); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] trap re-enable failed: " + ex.Message)); } } } } } } private static void RegisterNetworkHandlers() { //IL_0035: 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_0040: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //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_00c1: Expected O, but got Unknown //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_00e7: Expected O, but got Unknown if (_handlersRegistered) { return; } NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if (val == null) { return; } try { object obj = <>O.<0>__OnActionResult; if (obj == null) { HandleNamedMessageDelegate val2 = OnActionResult; <>O.<0>__OnActionResult = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZFieldTablet.ActionResultClientRpc", (HandleNamedMessageDelegate)obj); if (NetworkManager.Singleton.IsServer) { object obj2 = <>O.<1>__OnCameraDisableRequest; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnCameraDisableRequest; <>O.<1>__OnCameraDisableRequest = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZFieldTablet.CameraDisableServerRpc", (HandleNamedMessageDelegate)obj2); object obj3 = <>O.<2>__OnAlarmRequest; if (obj3 == null) { HandleNamedMessageDelegate val4 = OnAlarmRequest; <>O.<2>__OnAlarmRequest = val4; obj3 = (object)val4; } val.RegisterNamedMessageHandler("Y4NGZFieldTablet.AlarmServerRpc", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnLockdownRequest; if (obj4 == null) { HandleNamedMessageDelegate val5 = OnLockdownRequest; <>O.<3>__OnLockdownRequest = val5; obj4 = (object)val5; } val.RegisterNamedMessageHandler("Y4NGZFieldTablet.LockdownServerRpc", (HandleNamedMessageDelegate)obj4); object obj5 = <>O.<4>__OnTrapsDisableRequest; if (obj5 == null) { HandleNamedMessageDelegate val6 = OnTrapsDisableRequest; <>O.<4>__OnTrapsDisableRequest = val6; obj5 = (object)val6; } val.RegisterNamedMessageHandler("Y4NGZFieldTablet.TrapsDisableServerRpc", (HandleNamedMessageDelegate)obj5); } _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] mainframe net handler registration failed: " + ex.Message)); } } } internal unsafe static void RequestCameraDisable(int cameraId) { //IL_0040: 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_0054: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsServer) { HandleCameraDisable(singleton.LocalClientId, cameraId); return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref cameraId, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZFieldTablet.CameraDisableServerRpc", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } internal unsafe static void RequestAlarm(byte op) { //IL_0040: 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_0054: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsServer) { HandleAlarm(singleton.LocalClientId, op); return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref op, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZFieldTablet.AlarmServerRpc", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } internal unsafe static void RequestLockdown(bool begin) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsServer) { HandleLockdown(singleton.LocalClientId, begin); return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { byte b = (begin ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZFieldTablet.LockdownServerRpc", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } internal unsafe static void RequestTrapsDisable() { //IL_0041: 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_0056: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsServer) { HandleTrapsDisable(singleton.LocalClientId); return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { byte b = 1; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZFieldTablet.TrapsDisableServerRpc", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static bool SenderHasFieldOperations(ulong senderClientId) { return UpgradeTierSync.GetTier(senderClientId, "field_operations") >= 1; } private static void OnCameraDisableRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } int cameraId = default(int); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref cameraId, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] malformed camera disable request: " + ex.Message)); } return; } HandleCameraDisable(senderClientId, cameraId); } private static void HandleCameraDisable(ulong senderClientId, int cameraId) { if (SenderHasFieldOperations(senderClientId)) { float unscaledTime = Time.unscaledTime; if (!(unscaledTime < _hostCameraReadyAt) && IsCompanyPresent()) { _hostCameraReadyAt = unscaledTime + 20f; HostTryDisableCamera(cameraId); } } } private static void OnAlarmRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } byte op = default(byte); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref op, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] malformed alarm request: " + ex.Message)); } return; } HandleAlarm(senderClientId, op); } private static void HandleAlarm(ulong senderClientId, byte op) { if (!SenderHasFieldOperations(senderClientId) || !IsCompanyPresent()) { return; } try { HostApplyAlarmOp(op); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] alarm op failed: " + ex.Message)); } } } private static void OnLockdownRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } byte b = default(byte); try { ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] malformed lockdown request: " + ex.Message)); } return; } HandleLockdown(senderClientId, b != 0); } private static void HandleLockdown(ulong senderClientId, bool begin) { if (!SenderHasFieldOperations(senderClientId)) { return; } float unscaledTime = Time.unscaledTime; if (!(unscaledTime < _hostLockdownReadyAt)) { if (!IsCompanyPresent()) { SendActionResult(senderClientId, (byte)(begin ? 1 : 2), success: false, 0f, 0); return; } _hostLockdownReadyAt = unscaledTime + 30f; bool success = HostTryLockdown(begin); SendActionResult(senderClientId, (byte)(begin ? 1 : 2), success, 0f, 0); } } private static void OnTrapsDisableRequest(ulong senderClientId, FastBufferReader reader) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.IsServer) { HandleTrapsDisable(senderClientId); } } private static void HandleTrapsDisable(ulong senderClientId) { if (!SenderHasFieldOperations(senderClientId)) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _hostTrapsReadyAt) { return; } _hostTrapsReadyAt = unscaledTime + 90f; int num = 0; float maxDuration = 0f; try { Turret[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].turretActive && DisableTrapVanillaStyle((Component)(object)array[i], 0, ref maxDuration)) { num++; } } Landmine[] array2 = Object.FindObjectsOfType(); for (int j = 0; j < array2.Length; j++) { if ((Object)(object)array2[j] != (Object)null && !array2[j].hasExploded && DisableTrapVanillaStyle((Component)(object)array2[j], 1, ref maxDuration)) { num++; } } SpikeRoofTrap[] array3 = Object.FindObjectsOfType(); for (int k = 0; k < array3.Length; k++) { if ((Object)(object)array3[k] != (Object)null && DisableTrapVanillaStyle((Component)(object)array3[k], 2, ref maxDuration)) { num++; } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] traps disable sweep failed: " + ex.Message)); } } SendActionResult(senderClientId, 3, num > 0, maxDuration, num); } private static bool DisableTrapVanillaStyle(Component trap, byte kind, ref float maxDuration) { TerminalAccessibleObject val = trap.GetComponent() ?? trap.GetComponentInParent() ?? trap.GetComponentInChildren(); if ((Object)(object)val != (Object)null && !val.inCooldown) { val.CallFunctionFromTerminal(); float num = ((val.codeAccessCooldownTimer > 0f) ? val.codeAccessCooldownTimer : 12f); maxDuration = Mathf.Max(maxDuration, num); return true; } if ((Object)(object)val != (Object)null) { return false; } ToggleTrap(trap, kind, enable: false); PendingReenables.Add(new PendingTrapReenable { Trap = trap, Kind = kind, ReenableAt = Time.unscaledTime + 12f }); maxDuration = Mathf.Max(maxDuration, 12f); return true; } private static void ToggleTrap(Component trap, byte kind, bool enable) { //IL_0014: 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_002e: Unknown result type (might be due to invalid IL or missing references) switch (kind) { case 0: ((Turret)trap).ToggleTurretServerRpc(enable); break; case 1: ((Landmine)trap).ToggleMineServerRpc(enable); break; case 2: ((SpikeRoofTrap)trap).ToggleSpikesServerRpc(enable); break; } } private unsafe static void SendActionResult(ulong targetClientId, byte action, bool success, float value, int count) { //IL_003f: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (targetClientId == singleton.LocalClientId) { FieldTabletScreenRuntime.OnMainframeActionResult(action, success, value, count); return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(7, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref action, default(ForPrimitives)); byte b = (success ? ((byte)1) : ((byte)0)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref value, default(ForPrimitives)); b = (byte)Mathf.Clamp(count, 0, 255); ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZFieldTablet.ActionResultClientRpc", targetClientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnActionResult(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) try { byte action = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref action, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); float value = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); byte count = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref count, default(ForPrimitives)); FieldTabletScreenRuntime.OnMainframeActionResult(action, b != 0, value, count); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] malformed action result: " + ex.Message)); } } } private static bool IsCompanyPresent() { if (!_companyPresent.HasValue) { _companyPresent = OptionalPluginCapabilities.LethalCctv; } return _companyPresent.Value; } private static bool HostTryDisableCamera(int cameraId) { return OptionalCctvBridge.TryDisableCamera(cameraId); } private static bool HostTryLockdown(bool begin) { return OptionalCctvBridge.TrySetLockdown(begin); } private static void HostApplyAlarmOp(byte op) { OptionalCctvBridge.ApplyAlarmOperation(op, 2); } } [HarmonyPatch] internal static class FieldOpticsFlashlightPatch { private sealed class LightBaseline { internal float Intensity; internal float SpotAngle; } private static readonly ConditionalWeakTable Baselines = new ConditionalWeakTable(); [HarmonyPatch(typeof(FlashlightItem), "Update")] [HarmonyPostfix] private static void BoostOperatedFlashlight(FlashlightItem __instance) { if (!((Object)(object)__instance == (Object)null)) { PlayerControllerB operator_; bool num = IsOperatedByLocalPlayer(__instance, out operator_); float num2 = (num ? FieldOpticsUpgrade.GetLightIntensityMultiplier() : 1f); float coneMultiplier = (num ? FieldOpticsUpgrade.GetLightConeMultiplier() : 1f); Light flashlightBulb = __instance.flashlightBulb; if ((Object)(object)flashlightBulb != (Object)null) { flashlightBulb.intensity *= num2; ApplyCone(flashlightBulb, coneMultiplier); } ApplyFromBaseline(__instance.flashlightBulbGlow, num2, coneMultiplier); if ((Object)(object)operator_ != (Object)null) { ApplyFromBaseline(operator_.helmetLight, num2, coneMultiplier); } } } private static bool IsOperatedByLocalPlayer(FlashlightItem flashlight, out PlayerControllerB operator_) { operator_ = ((GrabbableObject)flashlight).playerHeldBy; if ((Object)(object)operator_ == (Object)null && flashlight.usingPlayerHelmetLight) { operator_ = flashlight.previousPlayerHeldBy; } if ((Object)(object)operator_ == (Object)null) { return false; } return (Object)(object)operator_ == (Object)(object)GameNetworkManager.Instance?.localPlayerController; } private static void ApplyFromBaseline(Light light, float intensityMultiplier, float coneMultiplier) { if (!((Object)(object)light == (Object)null)) { LightBaseline value = Baselines.GetValue(light, CaptureBaseline); light.intensity = value.Intensity * intensityMultiplier; SetSpotAngle(light, value.SpotAngle * coneMultiplier); } } private static void ApplyCone(Light light, float coneMultiplier) { LightBaseline value = Baselines.GetValue(light, CaptureBaseline); SetSpotAngle(light, value.SpotAngle * coneMultiplier); } private static LightBaseline CaptureBaseline(Light light) { return new LightBaseline { Intensity = light.intensity, SpotAngle = light.spotAngle }; } private static void SetSpotAngle(Light light, float angle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) if ((int)light.type != 0) { return; } float num = Mathf.Clamp(angle, 1f, 179f); if (!(Mathf.Abs(light.spotAngle - num) <= 0.01f)) { HDAdditionalLightData component = ((Component)light).GetComponent(); if ((Object)(object)component != (Object)null) { component.SetSpotAngle(num, 0f); } else { light.spotAngle = num; } } } } internal static class FieldTabletAudio { private const string AssetFolderName = "FieldTablet"; private const string SoundFolderName = "Sounds"; private static readonly string[] EquipFiles = new string[2] { "equip01.ogg", "equip02.ogg" }; private static readonly string[] MovementFiles = new string[2] { "movement01.ogg", "movement02.ogg" }; private static readonly string[] SelectFiles = new string[2] { "select01.ogg", "select02.ogg" }; private static readonly string[] DroneCommandFiles = new string[2] { "drone-command01.ogg", "drone-command02.ogg" }; private const string BackFile = "back.ogg"; private const string DroneSummonFile = "drone-summon.ogg"; private const string HackFile = "hack.ogg"; private const float MovementVolume = 0.18f; private const float BackVolume = 0.2f; private const float SelectVolume = 0.22f; private const float EquipVolume = 0.24f; private const float DroneSummonVolume = 0.28f; private const float DroneCommandVolume = 0.24f; private const float HackVolume = 0.24f; private const float SpatialBlend = 0.82f; private const float MinDistance = 0.2f; private const float MaxDistance = 3.2f; private static readonly AudioClip[] EquipClips = (AudioClip[])(object)new AudioClip[EquipFiles.Length]; private static readonly AudioClip[] MovementClips = (AudioClip[])(object)new AudioClip[MovementFiles.Length]; private static readonly AudioClip[] SelectClips = (AudioClip[])(object)new AudioClip[SelectFiles.Length]; private static readonly AudioClip[] DroneCommandClips = (AudioClip[])(object)new AudioClip[DroneCommandFiles.Length]; private static AudioClip _backClip; private static AudioClip _droneSummonClip; private static AudioClip _hackClip; private static GameObject _host; private static AudioSource _inputSource; private static AudioSource _actionSource; private static Transform _anchor; private static bool _loadStarted; private static bool _equipQueued; private static int _lastEquipIndex = -1; private static int _lastMovementIndex = -1; private static int _lastSelectIndex = -1; private static int _lastDroneCommandIndex = -1; internal static void Preload() { if (!_loadStarted) { MonoBehaviour host = Y4NGZPersistentRunner.Host; if (!((Object)(object)host == (Object)null) && ((Behaviour)host).isActiveAndEnabled) { _loadStarted = true; host.StartCoroutine(LoadAll()); } } } internal static void BindTo(Transform anchor, AudioSource mixerSource) { if (!((Object)(object)anchor == (Object)null)) { _anchor = anchor; EnsureSources(); FollowAnchor(); if ((Object)(object)mixerSource != (Object)null) { _inputSource.outputAudioMixerGroup = mixerSource.outputAudioMixerGroup; _actionSource.outputAudioMixerGroup = mixerSource.outputAudioMixerGroup; } TryPlayQueuedEquip(); } } internal static void QueueEquip() { _equipQueued = true; TryPlayQueuedEquip(); } internal static void PlayEquip() { PlayVariant(_actionSource, EquipClips, ref _lastEquipIndex, 0.24f); } internal static void PlayMovement() { PlayVariant(_inputSource, MovementClips, ref _lastMovementIndex, 0.18f); } internal static void PlayBack() { PlayClip(_inputSource, _backClip, 0.2f); } internal static void PlaySelect() { PlayVariant(_inputSource, SelectClips, ref _lastSelectIndex, 0.22f); } internal static void PlayDroneSummon() { PlayClip(_actionSource, _droneSummonClip, 0.28f); } internal static void PlayDroneCommand() { PlayVariant(_actionSource, DroneCommandClips, ref _lastDroneCommandIndex, 0.24f); } internal static void PlayHack() { PlayClip(_actionSource, _hackClip, 0.24f); } internal static void Unbind() { _anchor = null; _equipQueued = false; } internal static void FollowBoundAnchor() { FollowAnchor(); } internal static void Shutdown() { _anchor = null; _equipQueued = false; StopSource(_inputSource); StopSource(_actionSource); if ((Object)(object)_host != (Object)null) { Object.Destroy((Object)(object)_host); } _host = null; _inputSource = null; _actionSource = null; DestroyClips(EquipClips); DestroyClips(MovementClips); DestroyClips(SelectClips); DestroyClips(DroneCommandClips); DestroyClip(ref _backClip); DestroyClip(ref _droneSummonClip); DestroyClip(ref _hackClip); _loadStarted = false; _lastEquipIndex = -1; _lastMovementIndex = -1; _lastSelectIndex = -1; _lastDroneCommandIndex = -1; } private static void EnsureSources() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Expected O, but got Unknown if ((Object)(object)_host == (Object)null) { _host = new GameObject("Y4NGZ_FieldTabletAudio") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_host); } if ((Object)(object)_inputSource == (Object)null) { _inputSource = CreateSource("Input"); } if ((Object)(object)_actionSource == (Object)null) { _actionSource = CreateSource("Action"); } } private static AudioSource CreateSource(string suffix) { //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_0018: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Y4NGZ_FieldTabletAudio_" + suffix) { hideFlags = (HideFlags)61 }; val.transform.SetParent(_host.transform, false); AudioSource obj = val.AddComponent(); obj.playOnAwake = false; obj.loop = false; obj.spatialBlend = 0.82f; obj.dopplerLevel = 0f; obj.spread = 30f; obj.rolloffMode = (AudioRolloffMode)1; obj.minDistance = 0.2f; obj.maxDistance = 3.2f; obj.priority = 160; return obj; } private static void FollowAnchor() { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_host == (Object)null) && !((Object)(object)_anchor == (Object)null)) { _host.transform.SetPositionAndRotation(_anchor.position, _anchor.rotation); } } private static void TryPlayQueuedEquip() { if (_equipQueued && !((Object)(object)_anchor == (Object)null) && PlayVariant(_actionSource, EquipClips, ref _lastEquipIndex, 0.24f)) { _equipQueued = false; } } private static bool PlayVariant(AudioSource source, AudioClip[] clips, ref int lastIndex, float volume) { if ((Object)(object)source == (Object)null || clips == null || clips.Length == 0) { return false; } int num = Random.Range(0, clips.Length); for (int i = 0; i < clips.Length; i++) { int num2 = (num + i) % clips.Length; if (!((Object)(object)clips[num2] == (Object)null) && (num2 != lastIndex || !HasOtherLiveClip(clips, lastIndex))) { lastIndex = num2; return PlayClip(source, clips[num2], volume); } } if (lastIndex >= 0 && lastIndex < clips.Length) { return PlayClip(source, clips[lastIndex], volume); } return false; } private static bool HasOtherLiveClip(AudioClip[] clips, int excludedIndex) { for (int i = 0; i < clips.Length; i++) { if (i != excludedIndex && (Object)(object)clips[i] != (Object)null) { return true; } } return false; } private static bool PlayClip(AudioSource source, AudioClip clip, float volume) { if ((Object)(object)source == (Object)null || (Object)(object)clip == (Object)null) { return false; } FollowAnchor(); source.Stop(); source.clip = clip; source.volume = Mathf.Clamp01(volume); source.Play(); return true; } private static IEnumerator LoadAll() { for (int i = 0; i < EquipFiles.Length; i++) { int index = i; yield return LoadClip(EquipFiles[index], delegate(AudioClip clip) { EquipClips[index] = clip; }); } for (int i = 0; i < MovementFiles.Length; i++) { int index2 = i; yield return LoadClip(MovementFiles[index2], delegate(AudioClip clip) { MovementClips[index2] = clip; }); } for (int i = 0; i < SelectFiles.Length; i++) { int index3 = i; yield return LoadClip(SelectFiles[index3], delegate(AudioClip clip) { SelectClips[index3] = clip; }); } yield return LoadClip("back.ogg", delegate(AudioClip clip) { _backClip = clip; }); yield return LoadClip("drone-summon.ogg", delegate(AudioClip clip) { _droneSummonClip = clip; }); for (int i = 0; i < DroneCommandFiles.Length; i++) { int index4 = i; yield return LoadClip(DroneCommandFiles[index4], delegate(AudioClip clip) { DroneCommandClips[index4] = clip; }); } yield return LoadClip("hack.ogg", delegate(AudioClip clip) { _hackClip = clip; }); TryPlayQueuedEquip(); } private static IEnumerator LoadClip(string fileName, Action assign) { string path = ResolvePath(fileName); if (string.IsNullOrEmpty(path)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Field Tablet] sound missing: Assets/FieldTablet/Sounds/" + fileName)); } yield break; } UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)14); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Field Tablet] failed loading sound '" + path + "': " + request.error)); } yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)content == (Object)null) { yield break; } ((Object)content).name = "Y4NGZ_FieldTablet_" + Path.GetFileNameWithoutExtension(fileName); assign?.Invoke(content); } finally { ((IDisposable)request)?.Dispose(); } } private static string ResolvePath(string fileName) { string text = Path.GetDirectoryName(typeof(FieldTabletAudio).Assembly.Location) ?? string.Empty; string[] array = new string[4] { Path.Combine(text, "Assets", "FieldTablet", "Sounds", fileName), Path.Combine(text, "InteractiveAssets", "FieldTablet", "Sounds", fileName), Path.Combine(Paths.PluginPath, "y4ngz-Y4NGZUpgrades", "Assets", "FieldTablet", "Sounds", fileName), Path.Combine(Paths.PluginPath, "Y4NGZUpgrades", "Assets", "FieldTablet", "Sounds", fileName) }; for (int i = 0; i < array.Length; i++) { if (File.Exists(array[i])) { return array[i]; } } return null; } private static void StopSource(AudioSource source) { if (!((Object)(object)source == (Object)null)) { source.Stop(); source.clip = null; } } private static void DestroyClips(AudioClip[] clips) { for (int i = 0; i < clips.Length; i++) { DestroyClip(ref clips[i]); } } private static void DestroyClip(ref AudioClip clip) { if ((Object)(object)clip != (Object)null) { Object.Destroy((Object)(object)clip); } clip = null; } } internal static class FieldTabletScreenRuntime { private enum TabletScreenMode { Boot, Scan, Radar, Drone, Command, Hack, Mainframe } private enum MainframeView { Root, StashCodes, Cameras } private enum MainframeAction { None, EstablishUplink, OpenStashCodes, ScrapCheck, OpenCameras, DisableCamera, AlarmToggle, AlarmSilence, Lockdown, DisableTraps } private struct MainframeRow { public string Label; public string Detail; public bool Enabled; public MainframeAction Action; public int CameraId; } private enum TabletHackTargetKind { None, Mainframe, CompanyStash, CctvCamera, Turret, LockedDoor, DronePickup } private struct TabletHackTarget { public TabletHackTargetKind Kind; public Component Component; public GameObject Root; public string Label; public float Distance; public bool IsValid { get { if (Kind != TabletHackTargetKind.None) { if (!((Object)(object)Component != (Object)null)) { return (Object)(object)Root != (Object)null; } return true; } return false; } } } private struct VanillaMapUiState { public bool MapScreenPlayerNameEnabled; public bool MapScreenPlayerNameBgEnabled; public bool HeadMountedCamUiEnabled; public bool LocalPlayerPlaceholderEnabled; public bool CompassRoseEnabled; public bool ShipArrowUiActive; public bool ShipIconActive; public bool LostSignalUiActive; public bool ExitLineEnabled; } internal struct WorldReticleRequest { internal bool Show; internal Color Color; internal float Size; internal float FlashUntil; internal string Label; } private const string PropInstanceName = "Y4NGZ_Y4NGZ_FPSTabletProp_Instance"; private const float BootSeconds = 1.05f; private const float BootTransitionSeconds = 0.42f; private const float UplinkSeconds = 10f; private const float TargetSpliceSeconds = 4f; private const float HackSolvedLingerSeconds = 1.15f; private const float ScanRange = 28f; private const float TargetScanInterval = 0.1f; private const float TabletDynamicTextRefreshInterval = 0.1f; private const float ScreenRenderInterval = 1f / 30f; private const float RadarRenderInterval = 1f / 15f; private const float RadarCameraHeight = 3.636f; private const int ScreenWidth = 1844; private const int ScreenHeight = 1280; private const int ScreenRtBucketStep = 64; private const int ScreenRtMinWidth = 256; private const int ScreenRtMaxWidth = 1024; private const int ScreenRtDefaultWidth = 640; private const float ScreenRtMeasureDelaySeconds = 0.5f; private const float ScreenRtMeasureIntervalSeconds = 0.5f; private const int ScreenRtShrinkGuardPixels = 8; private const int RadarTextureSize = 1024; private const int ScreenRenderLayer = 5; private const float ScreenLocalDepthFallback = 0.0176f; private const float ScreenSurfaceEpsilon = 0.0008f; private const float ScreenPlaneLocalDepth = 0.00601f; private const float TabletMeshLocalHalfDepth = 0.013924f; private const float TabletMeshHalfDepthTolerance = 0.0015f; private const float ScreenTitleFontSize = 132f; private const float ScreenTabFontSize = 112f; private const float ScreenRowFontSize = 104f; private const float ScreenRowSelectedFontSize = 112f; private const float ScreenValueFontSize = 88f; private const float ScreenHintFontSize = 80f; private const float ScreenReadoutFontSize = 140f; private const int ScreenVisibleRows = 5; private const float ScreenRowPitch = 0.128f; private const float ScreenRowHalfBand = 0.062f; private const float ScreenFirstRowY = 0.7f; private const float ScreenStatusY = 0.815f; private const float ScreenFooterY = 0.05f; private const float ScreenRowLabelX = 0.065f; private const float ScreenRowDetailX = 0.935f; private const float ScreenRowBandMinX = 0.045f; private const float ScreenRowBandMaxX = 0.955f; private const float ScreenDividerThickness = 0.0125f; private const float ScreenSelectionAlpha = 0.24f; private const int DroneTelemetrySegments = 5; private static readonly Vector2 ScreenRowLabelSize = new Vector2(945f, 132f); private static readonly Vector2 ScreenRowDetailSize = new Vector2(594f, 112f); private static readonly Vector2 ScreenLineSize = new Vector2(1711f, 132f); private static readonly Vector2 ScreenValueLineSize = new Vector2(1711f, 112f); private const float CameraDisableCooldownSeconds = 20f; private const float LockdownCooldownSeconds = 30f; private const float TrapsDisableCooldownSeconds = 90f; private const int MainframeVisibleRows = 5; private const float WorldReticleDistance = 0.8f; private const float WorldReticleBasePixels = 58f; private static readonly Vector3 ScreenRenderRigPosition = new Vector3(0f, -9500f, 250f); private static readonly Vector3 ScreenLocalPosition = new Vector3(0.01229f, 0.108905f, 0f); private static readonly Vector3 ScreenLocalScale = new Vector3(0.21328f, 0.14803f, 1f); private static readonly Color ScreenGreen = new Color(0.13f, 1f, 0.18f, 0.95f); private static readonly Color ScreenDim = new Color(0.1f, 0.62f, 0.16f, 0.95f); private static readonly Color ScreenPanel = new Color(0.012f, 0.055f, 0.03f, 1f); private static readonly Color ScreenAmber = new Color(1f, 0.7f, 0.26f, 0.95f); private static readonly Color ScreenCyan = new Color(0.3f, 0.95f, 1f, 0.92f); private static readonly Color ScreenRed = new Color(1f, 0.26f, 0.22f, 0.95f); private static TabletScreenMode _mode = TabletScreenMode.Boot; private static TabletHackTarget _currentTarget; private static TabletHackTarget _hackTarget; private static VanillaMapUiState _vanillaMapUiState; private static float _openedAt; private static float _nextTargetScanAt; private static float _nextDynamicTextRefreshAt; private static float _nextScreenRenderAt; private static float _nextRadarRenderAt; private static float _radarZoom = 1f; private static float _hackProgress; private static float _hackSolvedAt; private static bool _hackHoldActive; private static bool _lastTargetWasValid; private static bool _radarRendered; private static bool _hasRenderedScreenTexture; private static TabletScreenMode _lastRadarRenderedMode = TabletScreenMode.Boot; private static bool _screenBindingDiagnosticsLogged; private static bool _screenRenderDiagnosticsLogged; private static bool _screenMissingPropDiagnosticsLogged; private static string _statusLine = "SCAN READY"; private static string _hackResult = string.Empty; private static WorldReticleRequest _dronePointerReticle; private static float _worldReticleAlpha; private static GameObject _lastScanTargetRoot; private static string _lastScanTargetLabelUpper = string.Empty; private static int _lastScanTargetDistanceTenths = int.MinValue; private static int _lastRadarZoomTenths = int.MinValue; private static int _lastHackPercent = int.MinValue; private static string _lastHackTargetLabel = string.Empty; private static string _lastCommandTelemetry = string.Empty; private static int _commandWindowStart; private static string _lastCommandStatusHint = string.Empty; private static GameObject _screenQuad; private static GameObject _screenQuadBack; private static GameObject _screenRigRoot; private static GameObject _screenCanvasRoot; private static GameObject _playerReticleRoot; private static TextMeshProUGUI _worldReticleLabel; private static Camera _screenCamera; private static Camera _radarCamera; private static Camera _radarSourceCamera; private static RenderTexture _screenRenderTexture; private static RenderTexture _radarTexture; private static Material _screenMaterial; private static string _screenMaterialSource = ""; private static Sprite _pixelSprite; private static TMP_FontAsset _font; private static CanvasGroup _bootGroup; private static CanvasGroup _scanGroup; private static CanvasGroup _radarGroup; private static CanvasGroup _droneGroup; private static CanvasGroup _commandGroup; private static CanvasGroup _hackGroup; private static RectTransform _bootFill; private static TextMeshProUGUI _bootTitle; private static TextMeshProUGUI _scanStatus; private static TextMeshProUGUI _scanTarget; private static TextMeshProUGUI _scanLinkReady; private static GameObject _scanLinkGlyph; private static Image _scanCenterDot; private static TextMeshProUGUI _radarStatus; private static TextMeshProUGUI _droneStatusValue; private static TextMeshProUGUI _droneFeedFallback; private static RawImage _droneFeedImage; private static Image _droneMarker; private static readonly List DroneHpSegments = new List(); private static readonly List DroneCargoSegments = new List(); private static TextMeshProUGUI _commandStatusLine; private static TextMeshProUGUI _commandTelemetryLine; private static TextMeshProUGUI _commandPageText; private static readonly List CommandSelectors = new List(); private static readonly List CommandLabels = new List(); private static readonly List CommandReasons = new List(); private static readonly CourierDronePatch.TabletCommandEntry[] CommandEntries = new CourierDronePatch.TabletCommandEntry[6]; private static readonly string[] LastCommandEntryLabels = new string[CommandEntries.Length]; private static readonly string[] LastCommandEntryReasons = new string[CommandEntries.Length]; private static readonly bool[] LastCommandEntrySelected = new bool[CommandEntries.Length]; private static readonly bool[] LastCommandEntryAvailable = new bool[CommandEntries.Length]; private static TextMeshProUGUI _hackStatusText; private static TextMeshProUGUI _hackTargetText; private static TextMeshProUGUI _hackPercentText; private static TextMeshProUGUI _hackHintText; private static RectTransform _scanReticleRoot; private static RectTransform _radarMarkerLayer; private static RectTransform _hackProgressFill; private static RawImage _radarImage; private static Image _rollingScanline; private static Image _scanPulse; private static readonly List ScanReticleLines = new List(); private static readonly List PlayerReticleLines = new List(); private static readonly List RadarMarkers = new List(); private static readonly Dictionary CachedTextValues = new Dictionary(); private static readonly Dictionary CachedTextColors = new Dictionary(); private static readonly Dictionary CachedFontSizes = new Dictionary(); private static readonly Dictionary CachedFontStyles = new Dictionary(); private static readonly Dictionary CachedGraphicColors = new Dictionary(); private static readonly Dictionary CachedActiveStates = new Dictionary(); private static TabletScreenMode _modeBeforeCommand = TabletScreenMode.Scan; private static int _commandSelection; private static bool _uplinkEstablished; private static bool _uplinkChannelActive; private static float _uplinkProgress; private static MainframeView _mainframeView = MainframeView.Root; private static int _mainframeSelection; private static int _mainframeWindowStart; private static string _mainframeStatus = "MAINFRAME"; private static string _scrapCheckResult = string.Empty; private static float _cameraDisableReadyAt; private static float _lockdownReadyAt; private static float _trapsReadyAt; private static readonly List MainframeRows = new List(); private static readonly List MainframeCameraIdBuffer = new List(); private static CanvasGroup _mainframeGroup; private static CanvasGroup _tabBarGroup; private static TextMeshProUGUI _mainframeStatusText; private static TextMeshProUGUI _mainframePageText; private static RectTransform _uplinkProgressFill; private static GameObject _uplinkProgressRoot; private static readonly List MainframeSelectors = new List(); private static readonly List MainframeLabels = new List(); private static readonly List MainframeDetails = new List(); private static readonly List TabLabels = new List(); private static readonly string[] TabNames = new string[4] { "SCAN", "MAP", "DRONE", "MFRM" }; private static float _nextMainframeRowsRefreshAt; private static bool? _companyPresent; private const float WorldReticleLabelFontSize = 10f; private static float _measuredScreenLocalDepth = 0.0176f; private static readonly Vector4 InvalidScreenRect = new Vector4(float.NaN, float.NaN, float.NaN, float.NaN); private static Vector4 _appliedScreenRect = InvalidScreenRect; private static GameObject _calibrationRoot; private static TextMeshProUGUI _calibrationOffsetReadout; private static TextMeshProUGUI _calibrationSizeReadout; private static int _screenRtWidth = 640; private static int _pendingShrinkWidth; private static bool _screenRtMeasured; private static float _nextScreenRtMeasureAt; private static bool _screenRtLoggedThisOpen; internal static bool HasHackableTarget => _currentTarget.IsValid; internal static bool IsCommandScreenOpen => _mode == TabletScreenMode.Command; internal static bool IsUplinkEstablished => _uplinkEstablished; internal static void OnTabletOpened() { _openedAt = Time.unscaledTime; _mode = TabletScreenMode.Boot; _radarZoom = 1f; _commandSelection = 0; _commandWindowStart = 0; _modeBeforeCommand = TabletScreenMode.Scan; _nextTargetScanAt = 0f; _nextDynamicTextRefreshAt = 0f; _nextScreenRenderAt = 0f; _nextRadarRenderAt = 0f; _screenRtMeasured = false; _screenRtLoggedThisOpen = false; _pendingShrinkWidth = 0; _nextScreenRtMeasureAt = _openedAt + 0.5f; _radarRendered = false; _hasRenderedScreenTexture = false; _lastRadarRenderedMode = TabletScreenMode.Boot; _screenBindingDiagnosticsLogged = false; _screenRenderDiagnosticsLogged = false; _screenMissingPropDiagnosticsLogged = false; _statusLine = "SCAN READY"; _currentTarget = default(TabletHackTarget); _mainframeView = MainframeView.Root; _mainframeSelection = 0; _mainframeWindowStart = 0; _uplinkChannelActive = false; _uplinkProgress = 0f; ResetDynamicTextState(); FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); StopHack("tablet-opened"); } internal static void TickUplinkState(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && (player.isPlayerDead || !player.isInsideFactory)) { if (_uplinkEstablished) { _uplinkEstablished = false; _mainframeStatus = "UPLINK LOST"; } if (_uplinkChannelActive) { _uplinkChannelActive = false; _uplinkProgress = 0f; _mainframeStatus = "UPLINK ABORTED"; } } } internal static void ResetUplinkState() { _uplinkEstablished = false; _uplinkChannelActive = false; _uplinkProgress = 0f; _mainframeStatus = "MAINFRAME"; _scrapCheckResult = string.Empty; _cameraDisableReadyAt = 0f; _lockdownReadyAt = 0f; _trapsReadyAt = 0f; } internal static void OnMainframeActionResult(byte action, bool success, float value, int count) { switch (action) { case 1: _mainframeStatus = (success ? "LOCKDOWN ENGAGED" : "LOCKDOWN UNAVAILABLE"); break; case 2: _mainframeStatus = (success ? "GATES OPENED" : "GATES HELD BY ANOTHER SYSTEM"); break; case 3: _mainframeStatus = (success ? ("TRAPS OFFLINE " + count + " FOR ~" + value.ToString("0") + "S") : "NO ACTIVE TRAPS FOUND"); break; } } internal static void UpdateActive(PlayerControllerB player, Action fireTabletActionGesture) { if (!((Object)(object)player == (Object)null)) { EnsureScreenOverlay(player); UpdateScreenRenderTextureSize(player); UpdateBootState(); RefreshHackableTargetScan(player); HandleTabletInputs(player, fireTabletActionGesture); UpdatePlayerCrosshair(player); RenderActiveScreen(player); } } internal static void Destroy() { //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); StopHack("tablet-closed"); FieldTabletAudio.Unbind(); DestroyObject((Object)(object)_screenQuad); DestroyObject((Object)(object)_screenQuadBack); DestroyObject((Object)(object)_screenRigRoot); DestroyObject((Object)(object)_playerReticleRoot); DestroyObject((Object)(object)(((Object)(object)_radarCamera != (Object)null) ? ((Component)_radarCamera).gameObject : null)); DestroyObject((Object)(object)_screenMaterial); if ((Object)(object)_screenRenderTexture != (Object)null) { _screenRenderTexture.Release(); DestroyObject((Object)(object)_screenRenderTexture); } if ((Object)(object)_radarTexture != (Object)null) { _radarTexture.Release(); DestroyObject((Object)(object)_radarTexture); } _screenQuad = null; _screenQuadBack = null; _screenRigRoot = null; _screenCanvasRoot = null; _playerReticleRoot = null; _worldReticleLabel = null; _screenCamera = null; _radarCamera = null; _radarSourceCamera = null; _screenRenderTexture = null; _radarTexture = null; _screenMaterial = null; _screenMaterialSource = ""; _bootGroup = null; _scanGroup = null; _radarGroup = null; _droneGroup = null; _hackGroup = null; _radarImage = null; _droneFeedImage = null; _droneMarker = null; _droneStatusValue = null; _droneFeedFallback = null; _commandGroup = null; _commandStatusLine = null; _commandTelemetryLine = null; _commandPageText = null; _mainframePageText = null; _scanLinkReady = null; _scanLinkGlyph = null; _scanCenterDot = null; _mainframeGroup = null; _tabBarGroup = null; _mainframeStatusText = null; _uplinkProgressFill = null; _uplinkProgressRoot = null; _calibrationRoot = null; _calibrationOffsetReadout = null; _calibrationSizeReadout = null; _appliedScreenRect = InvalidScreenRect; DroneHpSegments.Clear(); DroneCargoSegments.Clear(); CommandSelectors.Clear(); CommandLabels.Clear(); CommandReasons.Clear(); MainframeSelectors.Clear(); MainframeLabels.Clear(); MainframeDetails.Clear(); TabLabels.Clear(); ClearUiWriteCaches(); _screenBindingDiagnosticsLogged = false; _screenRenderDiagnosticsLogged = false; _screenMissingPropDiagnosticsLogged = false; _radarMarkerLayer = null; _hackProgressFill = null; _hackStatusText = null; _hackTargetText = null; _hackPercentText = null; _hackHintText = null; ScanReticleLines.Clear(); PlayerReticleLines.Clear(); RadarMarkers.Clear(); _currentTarget = default(TabletHackTarget); _hackTarget = default(TabletHackTarget); ResetDynamicTextState(); } private static void HandleTabletInputs(PlayerControllerB player, Action fireTabletActionGesture) { Mouse current = Mouse.current; IngameKeybinds keybinds = Y4NGZUpgrades.Gui.Plugin.Keybinds; if (CourierDronePatch.IsLocalPilotModeActive) { FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); _mode = TabletScreenMode.Drone; _statusLine = "REMOTE LINK ACTIVE"; if (UpgradeInput.WasPressed(keybinds?.TabletBack)) { FieldTabletAudio.PlayBack(); fireTabletActionGesture?.Invoke(); CourierDronePatch.StopLocalPilotMode(notifyOwner: false); _statusLine = "REMOTE LINK CLOSED"; } } else { if (_mode == TabletScreenMode.Boot) { return; } bool up = UpgradeInput.WasPressed(keybinds?.TabletUp); bool down = UpgradeInput.WasPressed(keybinds?.TabletDown); bool flag = UpgradeInput.WasPressed(keybinds?.TabletPrimaryAction); bool flag2 = UpgradeInput.WasPressed(keybinds?.TabletActivate) || (_mode == TabletScreenMode.Scan && flag); bool flag3 = UpgradeInput.WasPressed(keybinds?.TabletBack); bool flag4 = UpgradeInput.WasPressed(keybinds?.TabletPreviousTab); bool flag5 = UpgradeInput.WasPressed(keybinds?.TabletNextTab); if (flag4 || flag5) { SwitchTab(flag5 ? 1 : (-1)); FieldTabletAudio.PlayMovement(); fireTabletActionGesture?.Invoke(); return; } switch (_mode) { case TabletScreenMode.Scan: if (flag2 && _currentTarget.IsValid) { BeginTargetSplice(fireTabletActionGesture); } break; case TabletScreenMode.Hack: if (flag3 && _hackSolvedAt <= 0f) { StopHack("aborted"); FieldTabletAudio.PlayBack(); _statusLine = "SPLICE ABORTED"; } break; case TabletScreenMode.Radar: HandleMapInputs(current, up, down); break; case TabletScreenMode.Drone: HandleMapZoomKeys(current); if (flag2) { FieldTabletAudio.PlaySelect(); if (CourierDroneUpgrade.IsUnlocked()) { EnterCommandScreen(); fireTabletActionGesture?.Invoke(); _statusLine = "DRONE COMMAND"; } else { _statusLine = "DRONE MODULE LOCKED"; } } break; case TabletScreenMode.Command: HandleCommandScreenInputs(player, current, up, down, flag2, flag3, fireTabletActionGesture); break; case TabletScreenMode.Mainframe: HandleMainframeInputs(player, up, down, flag2, flag3, fireTabletActionGesture); break; } UpdateSpliceChannel(); UpdateUplinkChannel(player); } } private static int TabIndexForMode(TabletScreenMode mode) { switch (mode) { case TabletScreenMode.Radar: return 1; case TabletScreenMode.Drone: case TabletScreenMode.Command: return 2; case TabletScreenMode.Mainframe: return 3; default: return 0; } } private static void SwitchTab(int delta) { if (_mode == TabletScreenMode.Hack) { StopHack("tab-switch"); } if (_mode == TabletScreenMode.Command) { FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); } if (_uplinkChannelActive) { _uplinkChannelActive = false; _uplinkProgress = 0f; _mainframeStatus = "UPLINK ABORTED"; } int num = TabIndexForMode(_mode) + delta; if (num < 0) { num += TabNames.Length; } switch (num % TabNames.Length) { case 0: _mode = TabletScreenMode.Scan; _statusLine = "SCAN READY"; break; case 1: _mode = TabletScreenMode.Radar; _statusLine = "INTERIOR MAP"; break; case 2: _mode = TabletScreenMode.Drone; _statusLine = "DRONE LINK"; break; default: _mode = TabletScreenMode.Mainframe; _mainframeView = MainframeView.Root; _mainframeSelection = 0; _mainframeWindowStart = 0; _nextMainframeRowsRefreshAt = 0f; _statusLine = "MAINFRAME"; FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: true); break; } if (_mode != TabletScreenMode.Mainframe && _mode != TabletScreenMode.Command) { FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); } } private static void HandleMapInputs(Mouse mouse, bool up, bool down) { if (up) { AdjustRadarZoom(0.12f); FieldTabletAudio.PlayMovement(); } if (down) { AdjustRadarZoom(-0.12f); FieldTabletAudio.PlayMovement(); } HandleMapZoomKeys(mouse); } private static void HandleMapZoomKeys(Mouse mouse) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if (UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.TabletZoomIn)) { AdjustRadarZoom(0.12f); FieldTabletAudio.PlayMovement(); } if (UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.TabletZoomOut)) { AdjustRadarZoom(-0.12f); FieldTabletAudio.PlayMovement(); } if (mouse != null) { float num = ((Mouse.current != null) ? ((InputControl)(object)Mouse.current.scroll).ReadValue().y : 0f); if (Mathf.Abs(num) > 0.01f) { AdjustRadarZoom(Mathf.Sign(num) * 0.12f); FieldTabletAudio.PlayMovement(); } } } private static void AdjustRadarZoom(float delta) { _radarZoom = Mathf.Clamp(_radarZoom + delta, 0.65f, 2.35f); _nextRadarRenderAt = 0f; } private static void HandleCommandScreenInputs(PlayerControllerB player, Mouse mouse, bool up, bool down, bool activate, bool back, Action fireTabletActionGesture) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) if (back) { FieldTabletAudio.PlayBack(); FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); _mode = TabletScreenMode.Drone; _statusLine = "DRONE LINK"; fireTabletActionGesture?.Invoke(); return; } if (up) { MoveCommandSelection(-1); FieldTabletAudio.PlayMovement(); } if (down) { MoveCommandSelection(1); FieldTabletAudio.PlayMovement(); } if (mouse != null) { float y = ((InputControl)(object)mouse.scroll).ReadValue().y; if (Mathf.Abs(y) > 0.01f) { MoveCommandSelection((y < 0f) ? 1 : (-1)); FieldTabletAudio.PlayMovement(); } } if (activate) { ExecuteSelectedCommand(player, fireTabletActionGesture); } } private static void EnterCommandScreen() { if (_mode != TabletScreenMode.Command) { if (_mode == TabletScreenMode.Hack) { StopHack("command-screen"); } _modeBeforeCommand = ((_mode == TabletScreenMode.Boot || _mode == TabletScreenMode.Hack) ? TabletScreenMode.Scan : _mode); _commandSelection = 0; _commandWindowStart = 0; _mode = TabletScreenMode.Command; FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: true); } } private static void ExecuteSelectedCommand(PlayerControllerB player, Action fireTabletActionGesture) { int tabletCommandEntries = CourierDronePatch.GetTabletCommandEntries(player, CommandEntries); if (tabletCommandEntries <= 0) { _statusLine = "NO COMMANDS"; FieldTabletAudio.PlaySelect(); return; } _commandSelection = Mathf.Clamp(_commandSelection, 0, tabletCommandEntries - 1); CourierDronePatch.TabletCommandEntry tabletCommandEntry = CommandEntries[_commandSelection]; fireTabletActionGesture?.Invoke(); if (!tabletCommandEntry.Available) { _statusLine = (string.IsNullOrWhiteSpace(tabletCommandEntry.Reason) ? "COMMAND LOCKED" : tabletCommandEntry.Reason); FieldTabletAudio.PlaySelect(); } else if (CourierDronePatch.TryExecuteTabletCommand(player, tabletCommandEntry.Type)) { if (tabletCommandEntry.Type == CourierDronePatch.CourierCommandType.Spawn) { FieldTabletAudio.PlayDroneSummon(); } else { FieldTabletAudio.PlayDroneCommand(); } _statusLine = ((tabletCommandEntry.Type == CourierDronePatch.CourierCommandType.Pilot) ? "REMOTE LINK ACTIVE" : (tabletCommandEntry.Label + " SENT")); FieldOperationsTabletPatch.TrySetCommandScreenActionReadyHold(hold: false); _mode = ((tabletCommandEntry.Type == CourierDronePatch.CourierCommandType.Pilot) ? TabletScreenMode.Drone : ((_modeBeforeCommand == TabletScreenMode.Command || _modeBeforeCommand == TabletScreenMode.Hack || _modeBeforeCommand == TabletScreenMode.Boot) ? TabletScreenMode.Drone : _modeBeforeCommand)); } else { FieldTabletAudio.PlaySelect(); } } private static void MoveCommandSelection(int delta) { int tabletCommandEntries = CourierDronePatch.GetTabletCommandEntries(GameNetworkManager.Instance?.localPlayerController, CommandEntries); if (tabletCommandEntries <= 0) { _commandSelection = 0; return; } _commandSelection = (_commandSelection + delta) % tabletCommandEntries; if (_commandSelection < 0) { _commandSelection += tabletCommandEntries; } } private static void BeginTargetSplice(Action fireTabletActionGesture) { if (!_hackHoldActive && _currentTarget.IsValid) { _hackHoldActive = true; _hackTarget = _currentTarget; _hackProgress = 0f; _hackSolvedAt = 0f; _hackResult = string.Empty; _statusLine = "SPLICING"; _mode = TabletScreenMode.Hack; FieldTabletAudio.PlayHack(); fireTabletActionGesture?.Invoke(); } } private static void UpdateSpliceChannel() { if (!_hackHoldActive || _mode != TabletScreenMode.Hack || _hackSolvedAt > 0f) { return; } if (!_currentTarget.IsValid || !((Object)(object)_hackTarget.Root != (Object)null) || !((Object)(object)_currentTarget.Root == (Object)(object)_hackTarget.Root)) { StopHack("target-lost"); _statusLine = "LINK LOST"; return; } _hackTarget.Distance = _currentTarget.Distance; _hackProgress += Time.deltaTime / 4f; if (!(_hackProgress < 1f)) { _hackProgress = 1f; _hackSolvedAt = Time.unscaledTime; bool num = TryNotifyHackSuccess(); if (num) { EmployeeStatistics.RecordDeviceHacked((Object)(((Object)(object)_hackTarget.Root != (Object)null) ? ((object)_hackTarget.Root) : ((object)_hackTarget.Component))); } _hackResult = (num ? "ACCESS GRANTED" : "ACCESS COMPLETE"); _statusLine = "SCAN READY"; } } private static void UpdateUplinkChannel(PlayerControllerB player) { if (!_uplinkChannelActive) { return; } if (_mode != TabletScreenMode.Mainframe || (Object)(object)player == (Object)null || player.isPlayerDead || !player.isInsideFactory) { _uplinkChannelActive = false; _uplinkProgress = 0f; _mainframeStatus = "UPLINK ABORTED"; return; } _uplinkProgress += Time.deltaTime / 10f; if (!(_uplinkProgress < 1f)) { _uplinkChannelActive = false; _uplinkProgress = 0f; _uplinkEstablished = true; _mainframeStatus = "UPLINK ESTABLISHED"; } } private static void HandleMainframeInputs(PlayerControllerB player, bool up, bool down, bool activate, bool back, Action fireTabletActionGesture) { BuildMainframeRows(player); int count = MainframeRows.Count; if (count > 0) { _mainframeSelection = Mathf.Clamp(_mainframeSelection, 0, count - 1); if (up) { _mainframeSelection = (_mainframeSelection - 1 + count) % count; FieldTabletAudio.PlayMovement(); } if (down) { _mainframeSelection = (_mainframeSelection + 1) % count; FieldTabletAudio.PlayMovement(); } } else { _mainframeSelection = 0; } if (back) { if (_uplinkChannelActive) { _uplinkChannelActive = false; _uplinkProgress = 0f; _mainframeStatus = "UPLINK ABORTED"; FieldTabletAudio.PlayBack(); } else if (_mainframeView != MainframeView.Root) { _mainframeView = MainframeView.Root; _mainframeSelection = 0; _mainframeWindowStart = 0; _nextMainframeRowsRefreshAt = 0f; fireTabletActionGesture?.Invoke(); FieldTabletAudio.PlayBack(); } } else { if (!activate || count == 0 || _mainframeSelection >= count) { return; } BuildMainframeRows(player, force: true); count = MainframeRows.Count; if (count != 0 && _mainframeSelection < count) { MainframeRow row = MainframeRows[_mainframeSelection]; if (!row.Enabled) { _mainframeStatus = row.Detail; FieldTabletAudio.PlaySelect(); } else { ActivateMainframeRow(player, row, fireTabletActionGesture); } } } } private static void ActivateMainframeRow(PlayerControllerB player, MainframeRow row, Action fireTabletActionGesture) { float unscaledTime = Time.unscaledTime; if (row.Action == MainframeAction.EstablishUplink) { FieldTabletAudio.PlayHack(); } else { FieldTabletAudio.PlaySelect(); } switch (row.Action) { case MainframeAction.EstablishUplink: if (!_uplinkChannelActive) { _uplinkChannelActive = true; _uplinkProgress = 0f; _mainframeStatus = "UPLINKING"; fireTabletActionGesture?.Invoke(); } break; case MainframeAction.OpenStashCodes: _mainframeView = MainframeView.StashCodes; _mainframeSelection = 0; _mainframeWindowStart = 0; _nextMainframeRowsRefreshAt = 0f; fireTabletActionGesture?.Invoke(); break; case MainframeAction.ScrapCheck: RefreshScrapCheck(); _mainframeStatus = _scrapCheckResult; fireTabletActionGesture?.Invoke(); break; case MainframeAction.OpenCameras: _mainframeView = MainframeView.Cameras; _mainframeSelection = 0; _mainframeWindowStart = 0; _nextMainframeRowsRefreshAt = 0f; fireTabletActionGesture?.Invoke(); break; case MainframeAction.DisableCamera: _cameraDisableReadyAt = unscaledTime + 20f; FieldTabletMainframeNet.RequestCameraDisable(row.CameraId); _mainframeStatus = "SHUTDOWN SENT " + row.Label; fireTabletActionGesture?.Invoke(); break; case MainframeAction.AlarmToggle: FieldTabletMainframeNet.RequestAlarm((!CompanyIsAlarmOn()) ? ((byte)1) : ((byte)0)); _mainframeStatus = "ALARM TOGGLE SENT"; fireTabletActionGesture?.Invoke(); break; case MainframeAction.AlarmSilence: FieldTabletMainframeNet.RequestAlarm(2); _mainframeStatus = "SILENCE SENT"; fireTabletActionGesture?.Invoke(); break; case MainframeAction.Lockdown: _lockdownReadyAt = unscaledTime + 30f; FieldTabletMainframeNet.RequestLockdown(!CompanyIsLockdownActive()); _mainframeStatus = "LOCKDOWN REQUEST SENT"; fireTabletActionGesture?.Invoke(); break; case MainframeAction.DisableTraps: _trapsReadyAt = unscaledTime + 90f; FieldTabletMainframeNet.RequestTrapsDisable(); _mainframeStatus = "TRAP SHUTDOWN SENT"; fireTabletActionGesture?.Invoke(); break; } } private static int GetFieldOperationsTier() { return FieldOperationsUpgrade.GetTier(); } private static void BuildMainframeRows(PlayerControllerB player, bool force = false) { float unscaledTime = Time.unscaledTime; if (!force && MainframeRows.Count > 0 && unscaledTime < _nextMainframeRowsRefreshAt) { return; } _nextMainframeRowsRefreshAt = unscaledTime + 0.1f; MainframeRows.Clear(); bool flag = (Object)(object)player != (Object)null && player.isInsideFactory && !player.isPlayerDead; bool flag2 = IsCompanyPresent(); float unscaledTime2 = Time.unscaledTime; if (_mainframeView == MainframeView.StashCodes) { BuildStashCodeRows(flag2); return; } if (_mainframeView == MainframeView.Cameras) { BuildCameraRows(flag2, unscaledTime2); return; } if (!_uplinkEstablished) { MainframeRows.Add(new MainframeRow { Label = "ESTABLISH UPLINK", Detail = (_uplinkChannelActive ? ("LINK " + Mathf.FloorToInt(Mathf.Clamp01(_uplinkProgress) * 100f).ToString("00") + "%") : (flag ? ("[ENT] " + 10f.ToString("0") + "S") : "NO FACILITY")), Enabled = (flag && !_uplinkChannelActive), Action = MainframeAction.EstablishUplink }); } AddMainframeRow("STASH CODES", 1, company: true, flag2, MainframeAction.OpenStashCodes, "VIEW"); AddMainframeRow("SCRAP CHECK", 1, company: false, flag2, MainframeAction.ScrapCheck, string.IsNullOrEmpty(_scrapCheckResult) ? "RUN SWEEP" : _scrapCheckResult); AddMainframeRow("CAMERAS", 1, company: true, flag2, MainframeAction.OpenCameras, "VIEW/DISABLE"); AddMainframeRow("ALARM " + ((flag2 && CompanyIsAlarmOn()) ? "OFF" : "ON"), 1, company: true, flag2, MainframeAction.AlarmToggle, (flag2 && !CompanyIsMainframeHacked()) ? "NEEDS HACK" : ((flag2 && CompanyIsAlarmOn()) ? "ACTIVE" : "QUIET"), flag2 && !CompanyIsMainframeHacked()); AddMainframeRow("SILENCE ALARM", 1, company: true, flag2, MainframeAction.AlarmSilence, (flag2 && CompanyIsSecurityAlarmActive()) ? "SEC ACTIVE" : "SEC QUIET"); bool flag3 = flag2 && CompanyIsLockdownActive(); AddMainframeRow(flag3 ? "LOCKDOWN END" : "LOCKDOWN BEGIN", 1, company: true, flag2, MainframeAction.Lockdown, (unscaledTime2 < _lockdownReadyAt) ? ("CD " + Mathf.CeilToInt(_lockdownReadyAt - unscaledTime2) + "S") : (flag3 ? "GATES DOWN" : "READY"), unscaledTime2 < _lockdownReadyAt); AddMainframeRow("DISABLE TRAPS", 1, company: false, flag2, MainframeAction.DisableTraps, (unscaledTime2 < _trapsReadyAt) ? ("CD " + Mathf.CeilToInt(_trapsReadyAt - unscaledTime2) + "S") : "TEMPORARY", unscaledTime2 < _trapsReadyAt); } private static void AddMainframeRow(string label, int requiredTier, bool company, bool companyPresent, MainframeAction action, string enabledDetail, bool extraLock = false) { string detail = enabledDetail; bool enabled = true; if (company && !companyPresent) { enabled = false; detail = "NO COMPANY"; } else if (GetFieldOperationsTier() < requiredTier) { enabled = false; detail = "TIER " + requiredTier; } else if (!_uplinkEstablished) { enabled = false; detail = "NO UPLINK"; } else if (extraLock) { enabled = false; } MainframeRows.Add(new MainframeRow { Label = label, Detail = detail, Enabled = enabled, Action = action }); } private static void BuildStashCodeRows(bool company) { if (!company || !_uplinkEstablished) { MainframeRows.Add(new MainframeRow { Label = "STASH CODES", Detail = (company ? "NO UPLINK" : "NO COMPANY"), Enabled = false, Action = MainframeAction.None }); } else if (AppendStashCodeRows() == 0) { MainframeRows.Add(new MainframeRow { Label = "NO CODES ON FILE", Detail = string.Empty, Enabled = false, Action = MainframeAction.None }); } } private static void BuildCameraRows(bool company, float now) { if (!company || !_uplinkEstablished) { MainframeRows.Add(new MainframeRow { Label = "CAMERAS", Detail = (company ? "NO UPLINK" : "NO COMPANY"), Enabled = false, Action = MainframeAction.None }); return; } MainframeCameraIdBuffer.Clear(); CompanyCollectCameraIds(MainframeCameraIdBuffer); if (MainframeCameraIdBuffer.Count == 0) { MainframeRows.Add(new MainframeRow { Label = "NO CAMERAS FOUND", Detail = string.Empty, Enabled = false, Action = MainframeAction.None }); return; } bool flag = now < _cameraDisableReadyAt; for (int i = 0; i < MainframeCameraIdBuffer.Count; i++) { int cameraId = MainframeCameraIdBuffer[i]; string text = CompanyGetCameraLabel(cameraId); if (string.IsNullOrWhiteSpace(text)) { text = "CAM_" + cameraId; } bool flag2 = CompanyIsCameraDisabled(cameraId); MainframeRows.Add(new MainframeRow { Label = text.ToUpperInvariant(), Detail = (flag2 ? "OFFLINE" : (flag ? ("CD " + Mathf.CeilToInt(_cameraDisableReadyAt - now) + "S") : "[ENT] OFF")), Enabled = (!flag2 && !flag), Action = MainframeAction.DisableCamera, CameraId = cameraId }); } } private static void RefreshScrapCheck() { int num = 0; int num2 = 0; try { GrabbableObject[] array = Object.FindObjectsOfType(); foreach (GrabbableObject val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.itemProperties == (Object)null) && val.itemProperties.isScrap && val.isInFactory && !val.isInShipRoom && !val.isInElevator) { num += val.scrapValue; num2++; } } _scrapCheckResult = "$" + num + "/" + num2; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] scrap check failed: " + ex.Message)); } _scrapCheckResult = "SWEEP FAILED"; } } private static bool IsCompanyPresent() { if (!_companyPresent.HasValue) { _companyPresent = OptionalPluginCapabilities.LethalCctv; } return _companyPresent.Value; } private static int AppendStashCodeRows() { IReadOnlyList stashCodes = OptionalCctvBridge.GetStashCodes(); if (stashCodes == null) { return 0; } for (int i = 0; i < stashCodes.Count; i++) { MainframeRows.Add(new MainframeRow { Label = "CODE " + OptionalCctvBridge.FormatStashCode(stashCodes[i]), Detail = string.Empty, Enabled = false, Action = MainframeAction.None }); } return stashCodes.Count; } private static void CompanyCollectCameraIds(List output) { IReadOnlyList cameraIds = OptionalCctvBridge.GetCameraIds(); for (int i = 0; i < cameraIds.Count; i++) { output.Add(cameraIds[i]); } } private static string CompanyGetCameraLabel(int cameraId) { return OptionalCctvBridge.GetCameraLabel(cameraId); } private static bool CompanyIsCameraDisabled(int cameraId) { return OptionalCctvBridge.IsCameraDisabled(cameraId); } private static bool CompanyIsAlarmOn() { if (IsCompanyPresent()) { return OptionalCctvBridge.IsAlarmActive; } return false; } private static bool CompanyIsSecurityAlarmActive() { if (IsCompanyPresent()) { return OptionalCctvBridge.IsSecurityAlarmActive(); } return false; } private static bool CompanyIsLockdownActive() { if (IsCompanyPresent()) { return OptionalCctvBridge.IsLockdownActive; } return false; } private static bool CompanyIsMainframeHacked() { if (IsCompanyPresent()) { return OptionalCctvBridge.IsMainframeHacked; } return false; } private static void StopHack(string reason) { _hackHoldActive = false; _hackTarget = default(TabletHackTarget); _hackProgress = 0f; _hackSolvedAt = 0f; _hackResult = string.Empty; if (_mode == TabletScreenMode.Hack) { _mode = TabletScreenMode.Scan; } } private static void UpdateBootState() { if (_mode == TabletScreenMode.Boot && Time.unscaledTime - _openedAt >= 1.4699999f) { _mode = TabletScreenMode.Scan; } } private static void RenderActiveScreen(PlayerControllerB player) { if (!((Object)(object)_screenCanvasRoot == (Object)null)) { UpdateScanlines(Time.unscaledTime); RenderTabBar(); if (_mode == TabletScreenMode.Boot) { RenderTabletBootView(); } else if (_mode == TabletScreenMode.Radar) { RenderTabletRadarView(player); } else if (_mode == TabletScreenMode.Drone) { RenderTabletDroneView(player); } else if (_mode == TabletScreenMode.Command) { RenderTabletCommandView(player); } else if (_mode == TabletScreenMode.Hack) { RenderTabletHackView(); } else if (_mode == TabletScreenMode.Mainframe) { RenderTabletMainframeView(player); } else { RenderTabletScanView(); } RenderScreenTexture(); } } private static void RenderScreenTexture() { if ((Object)(object)_screenCamera == (Object)null || (Object)(object)_screenRenderTexture == (Object)null || (Object)(object)_screenCanvasRoot == (Object)null || !ShouldRenderScreenTexture(Time.unscaledTime)) { return; } try { Canvas.ForceUpdateCanvases(); RenderTexture active = RenderTexture.active; RenderTexture targetTexture = _screenCamera.targetTexture; _screenCamera.targetTexture = _screenRenderTexture; _screenCamera.Render(); RenderTexture.active = active; _screenCamera.targetTexture = targetTexture; if (_screenRenderDiagnosticsLogged) { return; } _screenRenderDiagnosticsLogged = true; float num = ProbeRenderTextureMaxLuma(_screenRenderTexture); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Field Tablet] screen runtime v5 rendered rt={((Texture)_screenRenderTexture).width}x{((Texture)_screenRenderTexture).height} canvasActive={_screenCanvasRoot.activeInHierarchy} cameraLayer={5} cameraEnabled={((Behaviour)_screenCamera).enabled} rtMaxLuma={num:0.000}"); } if (num <= 0.01f) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"[Field Tablet] screen RT probe came back black: the off-screen canvas is not reaching the render texture."); } } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogDebug((object)("[Field Tablet] screen render skipped: " + ex.Message)); } } } private static float ProbeRenderTextureMaxLuma(RenderTexture texture) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)texture == (Object)null) { return -1f; } RenderTexture active = RenderTexture.active; Texture2D val = null; try { RenderTexture.active = texture; val = new Texture2D(64, 64, (TextureFormat)4, false); val.ReadPixels(new Rect((float)(((Texture)texture).width - 64) / 2f, (float)(((Texture)texture).height - 64) / 2f, 64f, 64f), 0, 0); val.Apply(false); Color32[] pixels = val.GetPixels32(); byte b = 0; for (int i = 0; i < pixels.Length; i++) { if (pixels[i].r > b) { b = pixels[i].r; } if (pixels[i].g > b) { b = pixels[i].g; } if (pixels[i].b > b) { b = pixels[i].b; } } return (float)(int)b / 255f; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] RT probe failed: " + ex.Message)); } return -1f; } finally { RenderTexture.active = active; if ((Object)(object)val != (Object)null) { DestroyObject((Object)(object)val); } } } private static void RefreshHackableTargetScan(PlayerControllerB player) { float unscaledTime = Time.unscaledTime; if (!(unscaledTime < _nextTargetScanAt)) { _nextTargetScanAt = unscaledTime + 0.1f; if (TryFindHackableTarget(player, out var target)) { _currentTarget = target; return; } _currentTarget = default(TabletHackTarget); _lastTargetWasValid = false; } } private static bool ShouldRenderScreenTexture(float time) { if (_hasRenderedScreenTexture && time < _nextScreenRenderAt) { return false; } _hasRenderedScreenTexture = true; _nextScreenRenderAt = time + 1f / 30f; return true; } private static bool ShouldRefreshDynamicText(float time) { if (time < _nextDynamicTextRefreshAt) { return false; } _nextDynamicTextRefreshAt = time + 0.1f; return true; } private static void RefreshScanTargetText(bool hasTarget) { if ((Object)(object)_scanTarget == (Object)null) { return; } if (!hasTarget) { _lastScanTargetRoot = null; _lastScanTargetLabelUpper = string.Empty; _lastScanTargetDistanceTenths = int.MinValue; SetTextIfChanged((TMP_Text)(object)_scanTarget, string.Empty); return; } int num = Mathf.RoundToInt(Mathf.Max(0f, _currentTarget.Distance) * 10f); string text = (string.IsNullOrWhiteSpace(_currentTarget.Label) ? FormatTargetKind(_currentTarget.Kind) : _currentTarget.Label); bool flag = (Object)(object)_lastScanTargetRoot != (Object)(object)_currentTarget.Root || !_lastScanTargetLabelUpper.Equals(text, StringComparison.OrdinalIgnoreCase); bool flag2 = _lastScanTargetDistanceTenths != num; if (flag || (flag2 && ShouldRefreshDynamicText(Time.unscaledTime))) { if (flag) { _lastScanTargetRoot = _currentTarget.Root; _lastScanTargetLabelUpper = text.ToUpperInvariant(); } _lastScanTargetDistanceTenths = num; float num2 = (float)num / 10f; SetTextIfChanged((TMP_Text)(object)_scanTarget, _lastScanTargetLabelUpper + " " + num2.ToString("00.0") + "M"); } } private static void RefreshRadarStatusText() { if (!((Object)(object)_radarStatus == (Object)null)) { int num = Mathf.RoundToInt(_radarZoom * 10f); if (_lastRadarZoomTenths != num) { _lastRadarZoomTenths = num; SetTextIfChanged((TMP_Text)(object)_radarStatus, "ZOOM " + ((float)num / 10f).ToString("0.0") + "X"); } } } private static void RefreshHackTargetText() { if (!((Object)(object)_hackTargetText == (Object)null)) { string text = (string.IsNullOrWhiteSpace(_hackTarget.Label) ? "FIELD TARGET" : _hackTarget.Label); if (!_lastHackTargetLabel.Equals(text, StringComparison.OrdinalIgnoreCase)) { _lastHackTargetLabel = text; SetTextIfChanged((TMP_Text)(object)_hackTargetText, text.ToUpperInvariant()); } } } private static void RefreshHackPercentText(bool solved) { if ((Object)(object)_hackPercentText == (Object)null) { return; } if (solved) { _lastHackPercent = int.MinValue; SetTextIfChanged((TMP_Text)(object)_hackPercentText, _hackResult); return; } int num = Mathf.FloorToInt(Mathf.Clamp01(_hackProgress) * 100f); if (_lastHackPercent != num) { _lastHackPercent = num; SetTextIfChanged((TMP_Text)(object)_hackPercentText, num.ToString("00") + "%"); } } private static void RenderTabletBootView() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_bootGroup); float num = Mathf.Max(0f, Time.unscaledTime - _openedAt); float num2 = Mathf.Clamp01(num / 1.05f); float num3 = Mathf.Clamp01((num - 1.05f) / 0.42f); if ((Object)(object)_bootTitle != (Object)null) { SetTextIfChanged((TMP_Text)(object)_bootTitle, "Y4NGZ INDUSTRIES"); ((TMP_Text)_bootTitle).alpha = Mathf.Lerp(0.78f, 1f, Mathf.PingPong(Time.unscaledTime * 2.4f, 1f)); } if ((Object)(object)_bootFill != (Object)null) { _bootFill.anchorMax = new Vector2(Mathf.Lerp(0.3f, 0.7f, num2), 0.45f); } if ((Object)(object)_bootGroup != (Object)null && num3 > 0f) { _bootGroup.alpha = Mathf.Lerp(1f, 0.15f, num3); } if (num3 > 0f) { SetGroup(_scanGroup, active: true, Mathf.Clamp01(num3 * 1.25f)); RefreshTabletScanContent(); } } private static void RenderTabletScanView() { SetActiveGroup(_scanGroup); RefreshTabletScanContent(); } private static void RefreshTabletScanContent() { //IL_0058: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) bool isValid = _currentTarget.IsValid; if ((Object)(object)_scanStatus != (Object)null) { SetTextIfChanged((TMP_Text)(object)_scanStatus, _statusLine); SetColorIfChanged((TMP_Text)(object)_scanStatus, isValid ? ScreenAmber : ScreenGreen); } if ((Object)(object)_scanTarget != (Object)null) { RefreshScanTargetText(isValid); SetColorIfChanged((TMP_Text)(object)_scanTarget, ScreenGreen); } if ((Object)(object)_scanLinkReady != (Object)null) { SetActiveIfChanged(((Component)_scanLinkReady).gameObject, isValid); } if ((Object)(object)_scanLinkGlyph != (Object)null) { SetActiveIfChanged(_scanLinkGlyph, isValid); } if ((Object)(object)_scanCenterDot != (Object)null) { SetActiveIfChanged(((Component)_scanCenterDot).gameObject, !isValid); float num = 0.6f + 0.4f * Mathf.Sin(Time.unscaledTime * 3.4f); ((Graphic)_scanCenterDot).color = new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, num); } UpdateTabletScanReticle(isValid); } private static void RenderTabletRadarView(PlayerControllerB player) { //IL_0011: 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_0069: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_radarGroup); RefreshRadarStatusText(); _radarRendered = TryRenderRadarTextureThrottled(player, ResolveRadarFocus(player), player.isInsideFactory, player.isInHangarShipRoom, updateMarkers: true); if ((Object)(object)_radarImage != (Object)null) { SetEnabledIfChanged((Behaviour)(object)_radarImage, _radarRendered); SetColorIfChanged((Graphic)(object)_radarImage, _radarRendered ? new Color(0.62f, 1f, 0.66f, 0.9f) : new Color(0f, 0f, 0f, 0f)); } } private static void RenderTabletDroneView(PlayerControllerB player) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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_0178: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_droneGroup); Vector3 position; float healthNormalized; float cargoNormalized; int cargoCount; string status; bool droneInside; bool flag = CourierDronePatch.TryGetTabletTelemetry(out position, out healthNormalized, out cargoNormalized, out cargoCount, out status, out droneInside); SetSegmentBar(DroneHpSegments, flag ? healthNormalized : 0f, (healthNormalized <= 0.3f) ? ScreenRed : ScreenGreen); SetSegmentBar(DroneCargoSegments, flag ? cargoNormalized : 0f, ScreenGreen); if ((Object)(object)_droneStatusValue != (Object)null) { bool isLocalPilotModeActive = CourierDronePatch.IsLocalPilotModeActive; SetTextIfChanged((TMP_Text)(object)_droneStatusValue, isLocalPilotModeActive ? "REMOTE LINK ACTIVE" : (flag ? status : "NO LINK")); SetColorIfChanged((TMP_Text)(object)_droneStatusValue, (!flag || status == "DESTROYED") ? ScreenRed : ScreenGreen); } bool flag2 = false; if (flag) { _radarRendered = TryRenderRadarTextureThrottled(player, position + Vector3.up * 0.06f, droneInside, inShipRoom: false, updateMarkers: false); } flag2 = flag && _radarRendered; if ((Object)(object)_droneFeedImage != (Object)null) { if ((Object)(object)_radarTexture != (Object)null && (Object)(object)_droneFeedImage.texture != (Object)(object)_radarTexture) { _droneFeedImage.texture = (Texture)(object)_radarTexture; } SetEnabledIfChanged((Behaviour)(object)_droneFeedImage, flag2); SetColorIfChanged((Graphic)(object)_droneFeedImage, flag2 ? new Color(0.55f, 1f, 0.75f, 0.85f) : new Color(0f, 0f, 0f, 0f)); } if ((Object)(object)_droneMarker != (Object)null) { SetActiveIfChanged(((Component)_droneMarker).gameObject, flag2); } if ((Object)(object)_droneFeedFallback != (Object)null) { SetActiveIfChanged(((Component)_droneFeedFallback).gameObject, !flag2); } } private static void RenderTabletCommandView(PlayerControllerB player) { //IL_02dc: 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_02b2: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_commandGroup); int tabletCommandEntries = CourierDronePatch.GetTabletCommandEntries(player, CommandEntries); if (tabletCommandEntries <= 0) { _commandSelection = 0; _commandWindowStart = 0; if ((Object)(object)_commandStatusLine != (Object)null) { SetTextIfChanged((TMP_Text)(object)_commandStatusLine, BuildCommandStatusHint("NO COMMANDS")); } } else { _commandSelection = Mathf.Clamp(_commandSelection, 0, tabletCommandEntries - 1); if ((Object)(object)_commandStatusLine != (Object)null) { SetTextIfChanged((TMP_Text)(object)_commandStatusLine, BuildCommandStatusHint(string.Empty)); } } _commandWindowStart = ResolveRowWindowStart(_commandSelection, tabletCommandEntries); RenderPageIndicator((TMP_Text)(object)_commandPageText, _commandWindowStart, tabletCommandEntries); for (int i = 0; i < CommandLabels.Count; i++) { int num = _commandWindowStart + i; bool flag = num < tabletCommandEntries; if ((Object)(object)CommandLabels[i] != (Object)null) { SetActiveIfChanged(((Component)CommandLabels[i]).gameObject, flag); } if ((Object)(object)CommandReasons[i] != (Object)null) { SetActiveIfChanged(((Component)CommandReasons[i]).gameObject, flag); } if ((Object)(object)CommandSelectors[i] != (Object)null) { SetActiveIfChanged(((Component)CommandSelectors[i]).gameObject, flag); } if (!flag) { continue; } CourierDronePatch.TabletCommandEntry tabletCommandEntry = CommandEntries[num]; bool flag2 = num == _commandSelection; if ((Object)(object)CommandLabels[i] != (Object)null) { string text = tabletCommandEntry.Label ?? string.Empty; if (!string.Equals(LastCommandEntryLabels[i], text, StringComparison.Ordinal) || LastCommandEntrySelected[i] != flag2) { LastCommandEntryLabels[i] = text; LastCommandEntrySelected[i] = flag2; SetTextIfChanged((TMP_Text)(object)CommandLabels[i], (flag2 ? "> " : " ") + text); } SetColorIfChanged((TMP_Text)(object)CommandLabels[i], ResolveRowLabelColor(flag2, tabletCommandEntry.Available)); SetFontSizeIfChanged((TMP_Text)(object)CommandLabels[i], flag2 ? 112f : 104f); SetFontStyleIfChanged((TMP_Text)(object)CommandLabels[i], (FontStyles)(flag2 ? 1 : 0)); } if ((Object)(object)CommandReasons[i] != (Object)null) { string text2 = (tabletCommandEntry.Available ? string.Empty : (tabletCommandEntry.Reason ?? string.Empty)); if (!string.Equals(LastCommandEntryReasons[i], text2, StringComparison.Ordinal) || LastCommandEntryAvailable[i] != tabletCommandEntry.Available) { LastCommandEntryReasons[i] = text2; LastCommandEntryAvailable[i] = tabletCommandEntry.Available; SetTextIfChanged((TMP_Text)(object)CommandReasons[i], text2); } SetColorIfChanged((TMP_Text)(object)CommandReasons[i], ResolveRowDetailColor(flag2, tabletCommandEntry.Available)); } if ((Object)(object)CommandSelectors[i] != (Object)null) { SetColorIfChanged((Graphic)(object)CommandSelectors[i], ResolveRowSelectorColor(flag2)); } } RenderCommandTelemetry(); } private static int ResolveRowWindowStart(int selection, int count) { if (count <= 5) { return 0; } return Mathf.Clamp(selection, 0, count - 1) / 5 * 5; } private static void RenderPageIndicator(TMP_Text target, int windowStart, int count) { if (!((Object)(object)target == (Object)null)) { bool flag = count > 5; SetActiveIfChanged(((Component)target).gameObject, flag); if (flag) { int num = Mathf.Max(1, Mathf.CeilToInt((float)count / 5f)); SetTextIfChanged(target, "PAGE " + Mathf.Clamp(windowStart / 5 + 1, 1, num) + "/" + num); } } } private static Color ResolveRowLabelColor(bool selected, bool enabled) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!selected) { if (!enabled) { return ScreenDim; } return ScreenGreen; } return ScreenAmber; } private static Color ResolveRowDetailColor(bool selected, bool enabled) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) if (!selected) { if (!enabled) { return ScreenRed; } return ScreenDim; } return ScreenAmber; } private static Color ResolveRowSelectorColor(bool selected) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) if (!selected) { return Color.clear; } return new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.24f); } private static string BuildCommandStatusHint(string baseText) { string text = baseText ?? string.Empty; if (CourierDronePatch.TryGetTabletTelemetry(out var _, out var _, out var _, out var _, out var _, out var _)) { text = text + ((text.Length > 0) ? " " : string.Empty) + "[" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.CourierDroneCommand, "MMB") + "] TARGET"; } if (string.Equals(_lastCommandStatusHint, text, StringComparison.Ordinal)) { return _lastCommandStatusHint; } _lastCommandStatusHint = text; return text; } private static void RenderCommandTelemetry() { //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) Vector3 position; float healthNormalized; float cargoNormalized; int cargoCount; string status; bool droneInside; bool flag = CourierDronePatch.TryGetTabletTelemetry(out position, out healthNormalized, out cargoNormalized, out cargoCount, out status, out droneInside); string tabletActiveModeName = CourierDronePatch.GetTabletActiveModeName(); if (!((Object)(object)_commandTelemetryLine == (Object)null)) { string text = (flag ? ("HP " + Mathf.RoundToInt(Mathf.Clamp01(healthNormalized) * 100f) + "% CGO " + cargoCount + " " + tabletActiveModeName) : "NO LINK"); if (!string.Equals(_lastCommandTelemetry, text, StringComparison.Ordinal)) { _lastCommandTelemetry = text; SetTextIfChanged((TMP_Text)(object)_commandTelemetryLine, text); SetColorIfChanged((TMP_Text)(object)_commandTelemetryLine, (!flag || tabletActiveModeName == "DESTROYED") ? ScreenRed : ScreenDim); } } } private static void SetSegmentBar(List segments, float normalized, Color litColor) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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) int num = Mathf.RoundToInt(Mathf.Clamp01(normalized) * (float)segments.Count); for (int i = 0; i < segments.Count; i++) { if (!((Object)(object)segments[i] == (Object)null)) { SetColorIfChanged((Graphic)(object)segments[i], (Color)((i < num) ? litColor : new Color(litColor.r, litColor.g, litColor.b, 0.14f))); } } } private static void SetActiveGroup(CanvasGroup active) { SetGroup(_bootGroup, (Object)(object)active == (Object)(object)_bootGroup, 1f); SetGroup(_scanGroup, (Object)(object)active == (Object)(object)_scanGroup, 1f); SetGroup(_radarGroup, (Object)(object)active == (Object)(object)_radarGroup, 1f); SetGroup(_droneGroup, (Object)(object)active == (Object)(object)_droneGroup, 1f); SetGroup(_commandGroup, (Object)(object)active == (Object)(object)_commandGroup, 1f); SetGroup(_hackGroup, (Object)(object)active == (Object)(object)_hackGroup, 1f); SetGroup(_mainframeGroup, (Object)(object)active == (Object)(object)_mainframeGroup, 1f); } private static void RenderTabBar() { //IL_0083: 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) if ((Object)(object)_tabBarGroup == (Object)null) { return; } bool flag = _mode != TabletScreenMode.Boot; SetGroup(_tabBarGroup, flag, 1f); if (!flag) { return; } int num = TabIndexForMode(_mode); for (int i = 0; i < TabLabels.Count && i < TabNames.Length; i++) { TextMeshProUGUI val = TabLabels[i]; if (!((Object)(object)val == (Object)null)) { bool flag2 = i == num; SetTextIfChanged((TMP_Text)(object)val, (flag2 ? "> " : " ") + TabNames[i]); SetColorIfChanged((TMP_Text)(object)val, flag2 ? ScreenAmber : ScreenDim); SetFontSizeIfChanged((TMP_Text)(object)val, 112f); SetFontStyleIfChanged((TMP_Text)(object)val, (FontStyles)(flag2 ? 1 : 0)); } } } private static void RenderTabletMainframeView(PlayerControllerB player) { //IL_00ab: 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_02db: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_mainframeGroup); BuildMainframeRows(player); int count = MainframeRows.Count; _mainframeSelection = ((count > 0) ? Mathf.Clamp(_mainframeSelection, 0, count - 1) : 0); _mainframeWindowStart = ResolveRowWindowStart(_mainframeSelection, count); if ((Object)(object)_mainframePageText != (Object)null && _uplinkChannelActive) { SetActiveIfChanged(((Component)_mainframePageText).gameObject, active: false); } else { RenderPageIndicator((TMP_Text)(object)_mainframePageText, _mainframeWindowStart, count); } if ((Object)(object)_mainframeStatusText != (Object)null) { SetTextIfChanged((TMP_Text)(object)_mainframeStatusText, _mainframeStatus); SetColorIfChanged((TMP_Text)(object)_mainframeStatusText, _uplinkEstablished ? ScreenGreen : ScreenAmber); } for (int i = 0; i < MainframeLabels.Count; i++) { int num = _mainframeWindowStart + i; bool flag = num < count; if ((Object)(object)MainframeLabels[i] != (Object)null) { SetActiveIfChanged(((Component)MainframeLabels[i]).gameObject, flag); } if ((Object)(object)MainframeDetails[i] != (Object)null) { SetActiveIfChanged(((Component)MainframeDetails[i]).gameObject, flag); } if ((Object)(object)MainframeSelectors[i] != (Object)null) { SetActiveIfChanged(((Component)MainframeSelectors[i]).gameObject, flag); } if (flag) { MainframeRow mainframeRow = MainframeRows[num]; bool flag2 = num == _mainframeSelection; if ((Object)(object)MainframeLabels[i] != (Object)null) { SetTextIfChanged((TMP_Text)(object)MainframeLabels[i], (flag2 ? "> " : " ") + mainframeRow.Label); SetColorIfChanged((TMP_Text)(object)MainframeLabels[i], ResolveRowLabelColor(flag2, mainframeRow.Enabled)); SetFontSizeIfChanged((TMP_Text)(object)MainframeLabels[i], flag2 ? 112f : 104f); SetFontStyleIfChanged((TMP_Text)(object)MainframeLabels[i], (FontStyles)(flag2 ? 1 : 0)); } if ((Object)(object)MainframeDetails[i] != (Object)null) { SetTextIfChanged((TMP_Text)(object)MainframeDetails[i], mainframeRow.Detail ?? string.Empty); SetColorIfChanged((TMP_Text)(object)MainframeDetails[i], ResolveRowDetailColor(flag2, mainframeRow.Enabled)); } if ((Object)(object)MainframeSelectors[i] != (Object)null) { SetColorIfChanged((Graphic)(object)MainframeSelectors[i], ResolveRowSelectorColor(flag2)); } } } if ((Object)(object)_uplinkProgressRoot != (Object)null) { SetActiveIfChanged(_uplinkProgressRoot, _uplinkChannelActive); } if (_uplinkChannelActive && (Object)(object)_uplinkProgressFill != (Object)null) { _uplinkProgressFill.anchorMax = new Vector2(Mathf.Lerp(0.16f, 0.72f, Mathf.Clamp01(_uplinkProgress)), 0.075f); } } private static void SetTextIfChanged(TMP_Text target, string value) { if ((Object)(object)target == (Object)null) { return; } value = value ?? string.Empty; if (!CachedTextValues.TryGetValue(target, out var value2) || !string.Equals(value2, value, StringComparison.Ordinal)) { if (!CachedTextValues.ContainsKey(target) && string.Equals(target.text, value, StringComparison.Ordinal)) { CachedTextValues[target] = value; return; } target.text = value; CachedTextValues[target] = value; } } private static void SetColorIfChanged(TMP_Text target, Color value) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_0044: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && (!CachedTextColors.TryGetValue(target, out var value2) || !(value2 == value))) { if (!CachedTextColors.ContainsKey(target) && ((Graphic)target).color == value) { CachedTextColors[target] = value; return; } ((Graphic)target).color = value; CachedTextColors[target] = value; } } private static void SetColorIfChanged(Graphic target, Color value) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_0044: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && (!CachedGraphicColors.TryGetValue(target, out var value2) || !(value2 == value))) { if (!CachedGraphicColors.ContainsKey(target) && target.color == value) { CachedGraphicColors[target] = value; return; } target.color = value; CachedGraphicColors[target] = value; } } private static void SetActiveIfChanged(GameObject target, bool active) { if (!((Object)(object)target == (Object)null) && (!CachedActiveStates.TryGetValue(target, out var value) || value != active)) { if (!CachedActiveStates.ContainsKey(target) && target.activeSelf == active) { CachedActiveStates[target] = active; return; } target.SetActive(active); CachedActiveStates[target] = active; } } private static void SetEnabledIfChanged(Behaviour target, bool enabled) { if ((Object)(object)target != (Object)null && target.enabled != enabled) { target.enabled = enabled; } } private static void SetFontSizeIfChanged(TMP_Text target, float value) { if (!((Object)(object)target == (Object)null) && (!CachedFontSizes.TryGetValue(target, out var value2) || !Mathf.Approximately(value2, value))) { if (!CachedFontSizes.ContainsKey(target) && Mathf.Approximately(target.fontSize, value)) { CachedFontSizes[target] = value; return; } target.fontSize = value; CachedFontSizes[target] = value; } } private static void SetFontStyleIfChanged(TMP_Text target, FontStyles value) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && (!CachedFontStyles.TryGetValue(target, out var value2) || value2 != value)) { if (!CachedFontStyles.ContainsKey(target) && target.fontStyle == value) { CachedFontStyles[target] = value; return; } target.fontStyle = value; CachedFontStyles[target] = value; } } private static void ClearUiWriteCaches() { CachedTextValues.Clear(); CachedTextColors.Clear(); CachedFontSizes.Clear(); CachedFontStyles.Clear(); CachedGraphicColors.Clear(); CachedActiveStates.Clear(); } private static void ResetDynamicTextState() { _lastScanTargetRoot = null; _lastScanTargetLabelUpper = string.Empty; _lastScanTargetDistanceTenths = int.MinValue; _lastRadarZoomTenths = int.MinValue; _lastHackPercent = int.MinValue; _lastHackTargetLabel = string.Empty; _lastCommandTelemetry = string.Empty; _lastCommandStatusHint = string.Empty; Array.Clear(LastCommandEntryLabels, 0, LastCommandEntryLabels.Length); Array.Clear(LastCommandEntryReasons, 0, LastCommandEntryReasons.Length); Array.Clear(LastCommandEntrySelected, 0, LastCommandEntrySelected.Length); Array.Clear(LastCommandEntryAvailable, 0, LastCommandEntryAvailable.Length); } private static void RenderTabletHackView() { //IL_008a: 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_004c: 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_00e4: Unknown result type (might be due to invalid IL or missing references) SetActiveGroup(_hackGroup); bool flag = _hackSolvedAt > 0f; if ((Object)(object)_hackStatusText != (Object)null) { SetTextIfChanged((TMP_Text)(object)_hackStatusText, flag ? "LINKED" : "SPLICING"); SetColorIfChanged((TMP_Text)(object)_hackStatusText, flag ? ScreenGreen : ScreenAmber); } if ((Object)(object)_hackTargetText != (Object)null) { RefreshHackTargetText(); } if ((Object)(object)_hackPercentText != (Object)null) { RefreshHackPercentText(flag); SetColorIfChanged((TMP_Text)(object)_hackPercentText, flag ? ScreenGreen : ScreenAmber); } if ((Object)(object)_hackHintText != (Object)null) { SetActiveIfChanged(((Component)_hackHintText).gameObject, !flag); } if ((Object)(object)_hackProgressFill != (Object)null) { _hackProgressFill.anchorMax = new Vector2(Mathf.Lerp(0.16f, 0.84f, Mathf.Clamp01(_hackProgress)), 0.47f); } if (flag && Time.unscaledTime > _hackSolvedAt + 1.15f) { StopHack("solved"); } } private static void UpdateTabletScanReticle(bool hasTarget) { //IL_0062: 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_006f: 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_009e: 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_00f0: 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) if ((Object)(object)_scanReticleRoot == (Object)null) { return; } float num = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * (hasTarget ? 7.8f : 2.2f)); float num2 = (hasTarget ? Mathf.Lerp(172f, 192f, num) : Mathf.Lerp(68f, 80f, num)); _scanReticleRoot.sizeDelta = new Vector2(num2, num2); Color value = (hasTarget ? ScreenAmber : ScreenDim); for (int i = 0; i < ScanReticleLines.Count; i++) { if ((Object)(object)ScanReticleLines[i] != (Object)null) { SetColorIfChanged((Graphic)(object)ScanReticleLines[i], value); } } if ((Object)(object)_scanPulse != (Object)null) { ((Graphic)_scanPulse).color = (hasTarget ? new Color(ScreenAmber.r, ScreenAmber.g, ScreenAmber.b, Mathf.Lerp(0.06f, 0.18f, num)) : new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.035f)); ((Graphic)_scanPulse).rectTransform.sizeDelta = new Vector2(num2 * 1.2f, num2 * 1.2f); } } private static void UpdateScanlines(float time) { //IL_003f: 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) if (!((Object)(object)_rollingScanline == (Object)null)) { float num = Mathf.Lerp(-665.6f, 665.6f, Mathf.Repeat(time * 0.18f, 1f)); ((Graphic)_rollingScanline).rectTransform.anchoredPosition = new Vector2(0f, num); float num2 = 0.17f + Mathf.PerlinNoise(time * 2.7f, 0.33f) * 0.11f; ((Graphic)_rollingScanline).color = new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, num2); } } internal static void SetDronePointerReticle(bool show, Color color, float flashSeconds = 0f, string label = null) { //IL_0010: 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) _dronePointerReticle.Show = show; _dronePointerReticle.Color = color; _dronePointerReticle.Size = 58f; _dronePointerReticle.FlashUntil = ((show && flashSeconds > 0f) ? (Time.unscaledTime + flashSeconds) : (show ? _dronePointerReticle.FlashUntil : 0f)); _dronePointerReticle.Label = (show ? (label ?? string.Empty) : string.Empty); UpdateWorldReticle(GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController); } private static void UpdatePlayerCrosshair(PlayerControllerB player) { UpdateWorldReticle(player); } private static void UpdateWorldReticle(PlayerControllerB player) { //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_019c: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: 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_01f2: 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_0217: 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_024b: Unknown result type (might be due to invalid IL or missing references) //IL_02fb: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e1: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val == (Object)null) { return; } WorldReticleRequest worldReticleRequest = BuildWorldReticleRequest(); EnsurePlayerCrosshair(val); if ((Object)(object)_playerReticleRoot == (Object)null) { return; } Canvas component = _playerReticleRoot.GetComponent(); if ((Object)(object)component != (Object)null) { component.worldCamera = val; } bool show = worldReticleRequest.Show; _worldReticleAlpha = Mathf.MoveTowards(_worldReticleAlpha, show ? 0.92f : 0f, Time.unscaledDeltaTime * 9f); SetActiveIfChanged(_playerReticleRoot, show || _worldReticleAlpha > 0.001f); CanvasGroup component2 = _playerReticleRoot.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.alpha = _worldReticleAlpha; } Transform transform = ((Component)val).transform; _playerReticleRoot.transform.position = transform.position + transform.forward * 0.8f; _playerReticleRoot.transform.rotation = Quaternion.LookRotation(transform.forward, transform.up); float num = ((worldReticleRequest.FlashUntil > Time.unscaledTime) ? (1f + 0.16f * Mathf.Sin(Time.unscaledTime * 46f)) : 1f); float num2 = Mathf.Max(1f, (worldReticleRequest.Size <= 0f) ? 58f : worldReticleRequest.Size) * num; RectTransform component3 = _playerReticleRoot.GetComponent(); if ((Object)(object)component3 != (Object)null) { component3.sizeDelta = new Vector2(num2, num2); float num3 = Mathf.Max(1f, (float)val.pixelHeight); float num4 = 1.6f * Mathf.Tan(val.fieldOfView * (MathF.PI / 180f) * 0.5f) / num3; ((Transform)component3).localScale = Vector3.one * num4; } Color val2 = (Color)(show ? worldReticleRequest.Color : new Color(worldReticleRequest.Color.r, worldReticleRequest.Color.g, worldReticleRequest.Color.b, 0f)); for (int i = 0; i < PlayerReticleLines.Count; i++) { if ((Object)(object)PlayerReticleLines[i] != (Object)null) { SetColorIfChanged((Graphic)(object)PlayerReticleLines[i], val2); } } if ((Object)(object)_worldReticleLabel != (Object)null) { string value = (show ? (worldReticleRequest.Label ?? string.Empty) : string.Empty); bool flag = show && !string.IsNullOrWhiteSpace(value); SetActiveIfChanged(((Component)_worldReticleLabel).gameObject, flag || _worldReticleAlpha > 0.001f); SetTextIfChanged((TMP_Text)(object)_worldReticleLabel, value); SetColorIfChanged((TMP_Text)(object)_worldReticleLabel, (Color)(flag ? val2 : new Color(val2.r, val2.g, val2.b, 0f))); } } private static WorldReticleRequest BuildWorldReticleRequest() { //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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (FieldOperationsTabletPatch.IsTabletActive && _currentTarget.IsValid) { float num = 0.5f + 0.5f * Mathf.Sin(Time.unscaledTime * 8f); return new WorldReticleRequest { Show = true, Color = ScreenAmber, Size = Mathf.Lerp(54f, 64f, num), FlashUntil = 0f, Label = string.Empty }; } if (_dronePointerReticle.Show) { return _dronePointerReticle; } return new WorldReticleRequest { Show = false, Color = ScreenAmber, Size = 30f, FlashUntil = 0f, Label = string.Empty }; } private static bool TryFindHackableTarget(PlayerControllerB player, out TabletHackTarget target) { //IL_003a: 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_004a: Unknown result type (might be due to invalid IL or missing references) target = default(TabletHackTarget); Camera val = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null) { val = Camera.main; } if ((Object)(object)val == (Object)null) { return false; } RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), 28f, -1, (QueryTriggerInteraction)2); if (array == null || array.Length == 0) { return false; } Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num = 0; num < array.Length; num++) { Collider collider = ((RaycastHit)(ref array[num])).collider; if (!((Object)(object)collider == (Object)null)) { Transform transform = ((Component)collider).transform; if ((!((Object)(object)transform != (Object)null) || !((Object)(object)player != (Object)null) || !transform.IsChildOf(((Component)player).transform)) && (!((Object)(object)transform != (Object)null) || ((Object)transform).name.IndexOf("FieldTablet", StringComparison.OrdinalIgnoreCase) < 0) && TryResolveTarget(collider, ((RaycastHit)(ref array[num])).distance, out target)) { return true; } } } return false; } private static bool TryResolveTarget(Collider collider, float distance, out TabletHackTarget target) { target = default(TabletHackTarget); if ((Object)(object)collider == (Object)null) { return false; } Component val = FindComponentByTypeName(collider, "MainframeSupport"); if ((Object)(object)val != (Object)null) { return BuildTarget(TabletHackTargetKind.Mainframe, val, "MAINFRAME", distance, out target); } val = FindComponentByTypeName(collider, "CompanyStashController"); if ((Object)(object)val != (Object)null) { return BuildTarget(TabletHackTargetKind.CompanyStash, val, ResolveDisplayName(val, "COMPANY STASH"), distance, out target); } val = FindComponentByTypeName(collider, "CCTV", "Camera") ?? FindComponentByTypeName(collider, "Cctv", "Camera"); if ((Object)(object)val != (Object)null) { return BuildTarget(TabletHackTargetKind.CctvCamera, val, ResolveDisplayName(val, "CCTV CAMERA"), distance, out target); } DoorLock componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && componentInParent.isLocked) { return BuildTarget(TabletHackTargetKind.LockedDoor, (Component)(object)componentInParent, "LOCKED DOOR", distance, out target); } Turret componentInParent2 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null && TurretHackerUpgrade.CanHackTurrets()) { return BuildTarget(TabletHackTargetKind.Turret, (Component)(object)componentInParent2, "TURRET", distance, out target); } GrabbableObject componentInParent3 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null && CourierDroneUpgrade.IsUnlocked()) { return BuildTarget(TabletHackTargetKind.DronePickup, (Component)(object)componentInParent3, ResolveItemName(componentInParent3), distance, out target); } ScanNodeProperties componentInParent4 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent4 != (Object)null) { string value = (componentInParent4.headerText ?? string.Empty) + " " + (componentInParent4.subText ?? string.Empty); if (Contains(value, "mainframe")) { return BuildTarget(TabletHackTargetKind.Mainframe, (Component)(object)componentInParent4, "MAINFRAME", distance, out target); } if (Contains(value, "camera") || Contains(value, "cctv")) { return BuildTarget(TabletHackTargetKind.CctvCamera, (Component)(object)componentInParent4, "CCTV CAMERA", distance, out target); } if (Contains(value, "locked") || Contains(value, "door")) { return BuildTarget(TabletHackTargetKind.LockedDoor, (Component)(object)componentInParent4, "LOCKED DOOR", distance, out target); } } return false; } private static bool BuildTarget(TabletHackTargetKind kind, Component component, string label, float distance, out TabletHackTarget target) { target = new TabletHackTarget { Kind = kind, Component = component, Root = (((Object)(object)component != (Object)null) ? component.gameObject : null), Label = (string.IsNullOrWhiteSpace(label) ? FormatTargetKind(kind) : label), Distance = distance }; bool isValid = target.IsValid; if (isValid && !_lastTargetWasValid) { _statusLine = "OBJECT DETECTED"; } _lastTargetWasValid = isValid; return isValid; } private static Component FindComponentByTypeName(Collider collider, params string[] fragments) { if ((Object)(object)collider == (Object)null) { return null; } Transform val = ((Component)collider).transform; int num = 0; while ((Object)(object)val != (Object)null && num < 8) { Component val2 = FindComponentOnTransform(val, fragments); if ((Object)(object)val2 != (Object)null) { return val2; } num++; val = val.parent; } return FindComponentOnTransform(((Component)collider).transform.root, fragments); } private static Component FindComponentOnTransform(Transform transform, params string[] fragments) { if ((Object)(object)transform == (Object)null) { return null; } Component[] components = ((Component)transform).GetComponents(); foreach (Component val in components) { if ((Object)(object)val == (Object)null) { continue; } string value = ((object)val).GetType().FullName + " " + ((object)val).GetType().Name + " " + ((Object)val).name; bool flag = true; for (int j = 0; j < fragments.Length; j++) { if (!Contains(value, fragments[j])) { flag = false; break; } } if (flag) { return val; } } return null; } private static bool TryNotifyHackSuccess() { switch (_hackTarget.Kind) { case TabletHackTargetKind.Mainframe: return TryInvokeInstanceMethod(_hackTarget.Component, "MarkHackedServerRpc"); case TabletHackTargetKind.CctvCamera: return TryDisableCctvCamera(_hackTarget.Component); case TabletHackTargetKind.LockedDoor: { Component component = _hackTarget.Component; return TryUnlockDoor((DoorLock)(object)((component is DoorLock) ? component : null)); } case TabletHackTargetKind.Turret: { Component component2 = _hackTarget.Component; return TurretHackerPatch.TryHackFromTablet((Turret)(object)((component2 is Turret) ? component2 : null)); } case TabletHackTargetKind.CompanyStash: if (!TryInvokeInstanceMethod(_hackTarget.Component, "UnlockFromRemoteHackServerRpc") && !TryInvokeInstanceMethod(_hackTarget.Component, "UnlockServerRpc")) { return TryInvokeInstanceMethod(_hackTarget.Component, "MarkUnlockedServerRpc"); } return true; default: return false; } } private static bool TryDisableCctvCamera(Component component) { if ((Object)(object)component == (Object)null) { return false; } if (TryInvokeInstanceMethod(component, "MarkBroken") || TryInvokeInstanceMethod(component, "BreakCamera") || TryInvokeInstanceMethod(component, "DisableCamera")) { return true; } Type type = ResolveType("Y4NGZCompany.Facility.Security.CctvSecurityCameraRegistry"); Type type2 = ResolveType("Y4NGZCompany.Facility.Security.CctvSecurityDirector"); if (type == null || type2 == null) { return false; } try { MethodInfo method = type.GetMethod("Find", BindingFlags.Static | BindingFlags.Public); object obj = ((method != null) ? method.Invoke(null, new object[1] { component }) : null); if (obj == null) { return false; } MethodInfo method2 = type2.GetMethod("OnCameraBroken", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (method2 == null) { return false; } method2.Invoke(null, new object[1] { obj }); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] CCTV disable failed: " + ex.Message)); } return false; } } private static bool TryUnlockDoor(DoorLock door) { if ((Object)(object)door == (Object)null) { return false; } try { door.isLocked = false; } catch { } if (!TryInvokeInstanceMethod((Component)(object)door, "UnlockDoorSyncWithServer") && !TryInvokeInstanceMethod((Component)(object)door, "OpenDoorAsEnemyServerRpc") && !TryInvokeInstanceMethod((Component)(object)door, "OpenDoorServerRpc")) { return !door.isLocked; } return true; } private static bool TryInvokeInstanceMethod(Component component, string methodName, params object[] preferredArgs) { if ((Object)(object)component == (Object)null || string.IsNullOrWhiteSpace(methodName)) { return false; } BindingFlags bindingAttr = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic; MethodInfo method = ((object)component).GetType().GetMethod(methodName, bindingAttr); if (method == null) { return false; } try { object[] parameters = BuildArguments(method.GetParameters(), preferredArgs); method.Invoke(component, parameters); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] invoke " + methodName + " failed: " + ex.Message)); } return false; } } private static object[] BuildArguments(ParameterInfo[] parameters, object[] preferredArgs) { if (parameters == null || parameters.Length == 0) { return Array.Empty(); } object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { Type parameterType = parameters[i].ParameterType; if (preferredArgs != null && i < preferredArgs.Length && preferredArgs[i] != null && parameterType.IsInstanceOfType(preferredArgs[i])) { array[i] = preferredArgs[i]; } else if (parameterType == typeof(float) && preferredArgs != null && preferredArgs.Length != 0 && preferredArgs[0] is float num) { array[i] = num; } else if (parameters[i].HasDefaultValue && parameters[i].DefaultValue != DBNull.Value && parameters[i].DefaultValue != Missing.Value) { object defaultValue = parameters[i].DefaultValue; array[i] = defaultValue ?? (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } else { array[i] = (parameterType.IsValueType ? Activator.CreateInstance(parameterType) : null); } } return array; } private static Type ResolveType(string fullName) { if (string.IsNullOrWhiteSpace(fullName)) { return null; } Type type = Type.GetType(fullName + ", Y4NGZCompany", throwOnError: false) ?? Type.GetType(fullName + ", LethalCCTV", throwOnError: false) ?? Type.GetType(fullName + ", LGUContractHUD", throwOnError: false); if (type != null) { return type; } Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { try { type = assemblies[i].GetType(fullName, throwOnError: false); if (type != null) { return type; } } catch { } } return null; } private static void EnsureScreenOverlay(PlayerControllerB player) { //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0108: 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_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0213: 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_027d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_screenQuad != (Object)null && (Object)(object)_screenCanvasRoot != (Object)null) { ApplyScreenQuadRect(); SetActiveIfChanged(_calibrationRoot, Plugin.GetTabletScreenCalibration()); FieldTabletAudio.BindTo(_screenQuad.transform, ((Object)(object)player != (Object)null) ? player.itemAudio : null); return; } Transform val = FindTabletProp(player); if ((Object)(object)val == (Object)null) { if (!_screenMissingPropDiagnosticsLogged) { _screenMissingPropDiagnosticsLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Field Tablet] screen runtime v5 waiting: visible tablet prop was not found under local player."); } } return; } EnsureScreenRig(); if ((Object)(object)_screenQuad == (Object)null) { float num = ResolveScreenLocalDepth(val); Vector2 val2 = ResolveScreenLocalOffset(); _screenQuad = CreateScreenQuad(val, "Y4NGZ_FieldTablet_ScreenOverlay", new Vector3(val2.x, val2.y, 0f - num), Quaternion.identity); _screenQuadBack = CreateScreenQuad(val, "Y4NGZ_FieldTablet_ScreenOverlayBack", new Vector3(val2.x, val2.y, num), Quaternion.Euler(0f, 180f, 0f)); _measuredScreenLocalDepth = num; _appliedScreenRect = InvalidScreenRect; ApplyScreenQuadRect(); SetActiveIfChanged(_calibrationRoot, Plugin.GetTabletScreenCalibration()); } FieldTabletAudio.BindTo(_screenQuad.transform, ((Object)(object)player != (Object)null) ? player.itemAudio : null); if (!_screenBindingDiagnosticsLogged) { _screenBindingDiagnosticsLogged = true; string text = (((Object)(object)_screenMaterial != (Object)null && (Object)(object)_screenMaterial.shader != (Object)null) ? ((Object)_screenMaterial.shader).name : ""); string text2 = (((Object)(object)_screenRenderTexture != (Object)null) ? $"{((Texture)_screenRenderTexture).width}x{((Texture)_screenRenderTexture).height}" : ""); Vector3 val3 = (((Object)(object)_screenQuad != (Object)null) ? _screenQuad.transform.position : Vector3.zero); Vector3 val4 = (((Object)(object)_screenQuad != (Object)null) ? _screenQuad.transform.lossyScale : Vector3.zero); ManualLogSource log2 = Plugin.Log; if (log2 != null) { object[] obj = new object[9] { GetHierarchyPath(val), ((Component)val).gameObject.layer, null, null, null, null, null, null, null }; GameObject screenQuad = _screenQuad; obj[2] = ((screenQuad != null) ? screenQuad.layer : (-1)); obj[3] = text; obj[4] = _screenMaterialSource; obj[5] = text2; obj[6] = val3; obj[7] = val4; obj[8] = _measuredScreenLocalDepth; log2.LogInfo((object)string.Format("[Field Tablet] screen runtime v5 bound prop='{0}' propLayer={1} quadLayer={2} shader='{3}' materialSource='{4}' rt={5} quadWorld={6} quadScale={7} measuredDepth={8:0.0000}", obj)); } } } private static void RefreshCalibrationReadout(Vector2 offset, Vector2 size) { SetTextIfChanged((TMP_Text)(object)_calibrationOffsetReadout, "X " + offset.x.ToString("0.0000") + " Y " + offset.y.ToString("0.0000")); SetTextIfChanged((TMP_Text)(object)_calibrationSizeReadout, "W " + size.x.ToString("0.0000") + " H " + size.y.ToString("0.0000")); } private static Vector2 ResolveScreenLocalOffset() { //IL_0022: 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) if (Plugin.TabletScreenOffsetX == null || Plugin.TabletScreenOffsetY == null) { return new Vector2(ScreenLocalPosition.x, ScreenLocalPosition.y); } return new Vector2(Plugin.GetTabletScreenOffsetX(), Plugin.GetTabletScreenOffsetY()); } private static Vector2 ResolveScreenLocalSize() { //IL_0022: 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) if (Plugin.TabletScreenWidth == null || Plugin.TabletScreenHeight == null) { return new Vector2(ScreenLocalScale.x, ScreenLocalScale.y); } return new Vector2(Plugin.GetTabletScreenWidth(), Plugin.GetTabletScreenHeight()); } private static void ApplyScreenQuadRect() { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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) //IL_001c: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_006f: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: 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_010b: 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_0127: 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) if ((Object)(object)_screenQuad == (Object)null) { return; } Vector2 val = ResolveScreenLocalOffset(); Vector2 val2 = ResolveScreenLocalSize(); Vector4 val3 = default(Vector4); ((Vector4)(ref val3))..ctor(val.x, val.y, val2.x, val2.y); if (!(val3 == _appliedScreenRect)) { _appliedScreenRect = val3; Vector3 localScale = default(Vector3); ((Vector3)(ref localScale))..ctor(val2.x, val2.y, 1f); _screenQuad.transform.localPosition = new Vector3(val.x, val.y, 0f - _measuredScreenLocalDepth); _screenQuad.transform.localScale = localScale; if ((Object)(object)_screenQuadBack != (Object)null) { _screenQuadBack.transform.localPosition = new Vector3(val.x, val.y, _measuredScreenLocalDepth); _screenQuadBack.transform.localScale = localScale; } _screenRtMeasured = false; _nextScreenRtMeasureAt = 0f; RefreshCalibrationReadout(val, val2); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Field Tablet] screen aperture rect offset=({val.x:0.0000}, {val.y:0.0000}) size=({val2.x:0.0000} x {val2.y:0.0000}) depth={_measuredScreenLocalDepth:0.0000}"); } } } private static float ResolveScreenLocalDepth(Transform prop) { float num = MeasurePropLocalHalfDepth(prop); if (num > 0.0005f && Mathf.Abs(num - 0.013924f) <= 0.0015f) { return 0.00681f; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)($"[Field Tablet] screen prop half-depth {num:0.0000} does not match the mesh the " + $"aperture was measured from ({0.013924f:0.0000}); falling back to its front face. " + "Re-measure the aperture if the prop prefab was rebuilt.")); } if (!(num > 0.0005f)) { return 0.0176f; } return num + 0.0008f; } private static float MeasurePropLocalHalfDepth(Transform prop) { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_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) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_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_00d0: Unknown result type (might be due to invalid IL or missing references) float num = 0f; try { MeshFilter[] componentsInChildren = ((Component)prop).GetComponentsInChildren(true); Vector3 val2 = default(Vector3); foreach (MeshFilter val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && ((Object)val).name.IndexOf("ScreenOverlay", StringComparison.OrdinalIgnoreCase) < 0) { Bounds bounds = val.sharedMesh.bounds; Vector3 min = ((Bounds)(ref bounds)).min; Vector3 max = ((Bounds)(ref bounds)).max; for (int j = 0; j < 8; j++) { ((Vector3)(ref val2))..ctor(((j & 1) == 0) ? min.x : max.x, ((j & 2) == 0) ? min.y : max.y, ((j & 4) == 0) ? min.z : max.z); Vector3 val3 = prop.InverseTransformPoint(((Component)val).transform.TransformPoint(val2)); num = Mathf.Max(num, Mathf.Abs(val3.z)); } } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] screen depth measurement failed: " + ex.Message)); } } return num; } private static GameObject CreateScreenQuad(Transform prop, string name, Vector3 localPosition, Quaternion localRotation) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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) GameObject obj = GameObject.CreatePrimitive((PrimitiveType)5); ((Object)obj).name = name; obj.layer = ((Component)prop).gameObject.layer; Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { DestroyObject((Object)(object)component); } obj.transform.SetParent(prop, false); obj.transform.localPosition = localPosition; obj.transform.localRotation = localRotation; Vector2 val = ResolveScreenLocalSize(); obj.transform.localScale = new Vector3(val.x, val.y, 1f); Renderer component2 = obj.GetComponent(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = EnsureScreenMaterial(); component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; } return obj; } private static Transform FindTabletProp(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return null; } Transform val = FindChildByName(((Component)player).transform, "Y4NGZ_Y4NGZ_FPSTabletProp_Instance"); if ((Object)(object)val != (Object)null) { return val; } if ((Object)(object)player.thisPlayerModelArms != (Object)null) { val = FindChildByName(((Component)player.thisPlayerModelArms).transform.root, "Y4NGZ_Y4NGZ_FPSTabletProp_Instance"); if ((Object)(object)val != (Object)null) { return val; } } return FindChildByName(((Component)player).transform, "Y4NGZ_FPSTabletProp"); } private static Transform FindChildByName(Transform root, string namePart) { if ((Object)(object)root == (Object)null || string.IsNullOrWhiteSpace(namePart)) { return null; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if ((Object)(object)val != (Object)null && ((Object)val).name.IndexOf(namePart, StringComparison.OrdinalIgnoreCase) >= 0) { return val; } } return null; } private static void EnsureScreenRig() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Expected O, but got Unknown //IL_0097: 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_00ab: 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_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_020b: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0215: Unknown result type (might be due to invalid IL or missing references) //IL_021a: 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) if (!((Object)(object)_screenRigRoot != (Object)null) || !((Object)(object)_screenRenderTexture != (Object)null) || !_screenRenderTexture.IsCreated() || !((Object)(object)_screenCanvasRoot != (Object)null)) { if ((Object)(object)_screenRenderTexture == (Object)null || !_screenRenderTexture.IsCreated()) { _screenRenderTexture = CreateScreenRenderTexture(_screenRtWidth, ScreenRtHeightFor(_screenRtWidth)); } if (!((Object)(object)_screenRigRoot != (Object)null)) { _screenRigRoot = new GameObject("Y4NGZ_FieldTablet_ScreenRig"); Object.DontDestroyOnLoad((Object)(object)_screenRigRoot); _screenRigRoot.transform.position = ScreenRenderRigPosition; GameObject val = new GameObject("Y4NGZ_FieldTablet_ScreenCamera"); val.transform.SetParent(_screenRigRoot.transform, false); val.transform.localPosition = new Vector3(0f, 0f, -10f); _screenCamera = val.AddComponent(); _screenCamera.clearFlags = (CameraClearFlags)2; _screenCamera.backgroundColor = ScreenPanel; _screenCamera.cullingMask = 32; _screenCamera.targetTexture = _screenRenderTexture; ((Behaviour)_screenCamera).enabled = false; _screenCamera.allowHDR = false; _screenCamera.allowMSAA = false; _screenCamera.orthographic = true; _screenCamera.orthographicSize = 640f; _screenCamera.aspect = 1.440625f; _screenCamera.nearClipPlane = 0.1f; _screenCamera.farClipPlane = 30f; _screenCanvasRoot = new GameObject("Y4NGZ_FieldTablet_ScreenCanvas", new Type[1] { typeof(RectTransform) }); _screenCanvasRoot.transform.SetParent(_screenRigRoot.transform, false); Canvas obj = _screenCanvasRoot.AddComponent(); obj.renderMode = (RenderMode)2; obj.worldCamera = _screenCamera; obj.sortingOrder = 0; RectTransform component = _screenCanvasRoot.GetComponent(); component.sizeDelta = new Vector2(1844f, 1280f); ((Component)CreateImage("ScreenBackground", (Transform)(object)component, Vector2.zero, Vector2.one, Vector2.zero, Vector2.zero, ScreenPanel)).transform.SetAsFirstSibling(); _bootGroup = CreateGroup("Boot", (Transform)(object)component); _scanGroup = CreateGroup("Scan", (Transform)(object)component); _radarGroup = CreateGroup("Radar", (Transform)(object)component); _droneGroup = CreateGroup("Drone", (Transform)(object)component); _commandGroup = CreateGroup("Command", (Transform)(object)component); _hackGroup = CreateGroup("Hack", (Transform)(object)component); _mainframeGroup = CreateGroup("Mainframe", (Transform)(object)component); _tabBarGroup = CreateGroup("TabBar", (Transform)(object)component); BuildBootUi(((Component)_bootGroup).transform); BuildScanUi(((Component)_scanGroup).transform); BuildRadarUi(((Component)_radarGroup).transform); BuildDroneUi(((Component)_droneGroup).transform); BuildCommandUi(((Component)_commandGroup).transform); BuildHackUi(((Component)_hackGroup).transform); BuildMainframeUi(((Component)_mainframeGroup).transform); BuildTabBar(((Component)_tabBarGroup).transform); BuildCrtOverlay(component); BuildCalibrationOverlay(component); SetLayerRecursive(_screenRigRoot, 5); } } } private static int ScreenRtHeightFor(int width) { return Mathf.Max(1, Mathf.RoundToInt((float)width * 0.6941432f)); } private static RenderTexture CreateScreenRenderTexture(int width, int height) { //IL_0004: 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_0014: 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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_003e: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown RenderTexture val = new RenderTexture(width, height, 0, (RenderTextureFormat)0) { name = "Y4NGZ_FieldTablet_ScreenRT", wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)2, anisoLevel = 8, useMipMap = true, autoGenerateMips = true }; val.Create(); ((Texture)val).mipMapBias = -0.5f; return val; } private static void UpdateScreenRenderTextureSize(PlayerControllerB player) { if ((Object)(object)_screenQuad == (Object)null || (Object)(object)_screenRenderTexture == (Object)null) { return; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _nextScreenRtMeasureAt) { return; } _nextScreenRtMeasureAt = unscaledTime + 0.5f; Camera val = (((Object)(object)player != (Object)null) ? player.gameplayCamera : null); if ((Object)(object)val == (Object)null || !TryMeasureScreenQuadPixelSpan(val, out var spanX, out var spanY)) { return; } float num = Mathf.Max(spanX, spanY * 1.440625f); int num2 = BucketScreenRtWidth(num); int width = num2; if (_screenRtMeasured && num2 < _screenRtWidth) { if (num > (float)(num2 - 8) || _pendingShrinkWidth != num2) { _pendingShrinkWidth = ((!(num > (float)(num2 - 8))) ? num2 : 0); width = _screenRtWidth; } } else { _pendingShrinkWidth = 0; } _screenRtMeasured = true; ApplyScreenRenderTextureSize(width); LogScreenRenderTextureOnce(val, spanX, spanY, width); } private static bool TryMeasureScreenQuadPixelSpan(Camera camera, out float spanX, out float spanY) { //IL_0087: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: 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_00c2: 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) spanX = 0f; spanY = 0f; Transform val = (((Object)(object)_screenQuad != (Object)null) ? _screenQuad.transform : null); if ((Object)(object)val == (Object)null) { return false; } float num = float.MaxValue; float num2 = float.MaxValue; float num3 = float.MinValue; float num4 = float.MinValue; Vector3 val2 = default(Vector3); for (int i = 0; i < 4; i++) { ((Vector3)(ref val2))..ctor(((i & 1) == 0) ? (-0.5f) : 0.5f, ((i & 2) == 0) ? (-0.5f) : 0.5f, 0f); Vector3 val3 = camera.WorldToScreenPoint(val.TransformPoint(val2)); if (val3.z <= 0.001f) { return false; } num = Mathf.Min(num, val3.x); num3 = Mathf.Max(num3, val3.x); num2 = Mathf.Min(num2, val3.y); num4 = Mathf.Max(num4, val3.y); } spanX = num3 - num; spanY = num4 - num2; if (spanX > 1f) { return spanY > 1f; } return false; } private static int BucketScreenRtWidth(float needed) { return Mathf.Clamp(Mathf.CeilToInt(Mathf.Max(1f, needed) / 64f) * 64, 256, 1024); } private static void ApplyScreenRenderTextureSize(int width) { int num = ScreenRtHeightFor(width); _screenRtWidth = width; if (!((Object)(object)_screenRenderTexture != (Object)null) || ((Texture)_screenRenderTexture).width != width || ((Texture)_screenRenderTexture).height != num) { RenderTexture screenRenderTexture = _screenRenderTexture; _screenRenderTexture = CreateScreenRenderTexture(width, num); if ((Object)(object)_screenCamera != (Object)null) { _screenCamera.targetTexture = _screenRenderTexture; } ConfigureTabletScreenMaterial(); if ((Object)(object)screenRenderTexture != (Object)null) { screenRenderTexture.Release(); DestroyObject((Object)(object)screenRenderTexture); } _hasRenderedScreenTexture = false; _nextScreenRenderAt = 0f; _screenRtLoggedThisOpen = false; } } private static void LogScreenRenderTextureOnce(Camera camera, float spanX, float spanY, int width) { if (!_screenRtLoggedThisOpen) { _screenRtLoggedThisOpen = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Field Tablet] screen RT bucket={width}x{ScreenRtHeightFor(width)} measuredSpan={spanX:0}x{spanY:0}px camera={camera.pixelWidth}x{camera.pixelHeight}"); } } } private static Material EnsureScreenMaterial() { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Expected O, but got Unknown if ((Object)(object)_screenMaterial != (Object)null) { return _screenMaterial; } EnsureScreenRig(); _screenMaterial = CloneVanillaScreenMaterial(); if ((Object)(object)_screenMaterial != (Object)null) { _screenMaterialSource = "vanilla map screen clone"; } else { Shader val = Shader.Find("HDRP/Unlit") ?? Shader.Find("Unlit/Texture") ?? Shader.Find("Sprites/Default"); _screenMaterial = new Material(val); _screenMaterialSource = "runtime " + (((Object)(object)val != (Object)null) ? ((Object)val).name : ""); } ((Object)_screenMaterial).name = "Y4NGZ_FieldTablet_ScreenMaterial"; ConfigureTabletScreenMaterial(); return _screenMaterial; } private static Material CloneVanillaScreenMaterial() { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) try { ManualCameraRenderer val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.mapScreen : null); if ((Object)(object)val == (Object)null) { return null; } if ((Object)(object)val.onScreenMat != (Object)null) { return new Material(val.onScreenMat); } MeshRenderer mesh = val.mesh; Material[] array = (((Object)(object)mesh != (Object)null) ? ((Renderer)mesh).sharedMaterials : null); if (array == null || val.materialIndex < 0 || val.materialIndex >= array.Length) { return null; } Material val2 = array[val.materialIndex]; return (!((Object)(object)val2 != (Object)null)) ? ((Material)null) : new Material(val2); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] vanilla screen material clone failed: " + ex.Message)); } return null; } } private static void ConfigureTabletScreenMaterial() { //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_screenMaterial == (Object)null) && !((Object)(object)_screenRenderTexture == (Object)null)) { try { _screenMaterial.mainTexture = (Texture)(object)_screenRenderTexture; } catch { } SetTexture(_screenMaterial, "_UnlitColorMap", (Texture)(object)_screenRenderTexture); SetTexture(_screenMaterial, "_BaseColorMap", (Texture)(object)_screenRenderTexture); SetTexture(_screenMaterial, "_BaseMap", (Texture)(object)_screenRenderTexture); SetTexture(_screenMaterial, "_MainTex", (Texture)(object)_screenRenderTexture); SetTexture(_screenMaterial, "_EmissiveColorMap", (Texture)(object)_screenRenderTexture); SetTexture(_screenMaterial, "_EmissionMap", (Texture)(object)_screenRenderTexture); SetColor(_screenMaterial, "_BaseColor", Color.white); SetColor(_screenMaterial, "_UnlitColor", Color.white); SetColor(_screenMaterial, "_Color", Color.white); SetColor(_screenMaterial, "_EmissiveColor", Color.white * 1.05f); SetColor(_screenMaterial, "_EmissiveColorLDR", Color.white); _screenMaterial.EnableKeyword("_EMISSION"); _screenMaterial.EnableKeyword("_EMISSIVE_COLOR_MAP"); } } private static void BuildBootUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_007b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) _bootTitle = CreateText("BootTitle", parent, "Y4NGZ INDUSTRIES", 132f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.58f), new Vector2(1700f, 180f), ScreenGreen); ((TMP_Text)_bootTitle).characterSpacing = 8f; Image obj = CreateImage("BootBarBack", parent, new Vector2(0.3f, 0.405f), new Vector2(0.7f, 0.45f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.22f)); _bootFill = ((Graphic)CreateImage("BootBarFill", parent, new Vector2(0.3f, 0.405f), new Vector2(0.3f, 0.45f), Vector2.zero, Vector2.zero, ScreenGreen)).rectTransform; CreateImage("BootBaseline", parent, new Vector2(0.3f, 0.353f), new Vector2(0.7f, 0.36549997f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.35f)); ((Graphic)obj).raycastTarget = false; } private static void BuildScanUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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_00d2: 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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01c9: Unknown result type (might be due to invalid IL or missing references) //IL_01ce: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) _scanStatus = CreateText("ScanStatus", parent, "SCAN READY", 104f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.815f), ScreenLineSize, ScreenGreen); GameObject val = new GameObject("ScanReticle"); val.transform.SetParent(parent, false); _scanReticleRoot = val.AddComponent(); _scanReticleRoot.anchorMin = new Vector2(0.5f, 0.55f); _scanReticleRoot.anchorMax = new Vector2(0.5f, 0.55f); _scanReticleRoot.pivot = new Vector2(0.5f, 0.5f); _scanReticleRoot.sizeDelta = new Vector2(220f, 220f); _scanPulse = CreateImage("ScanPulse", (Transform)(object)_scanReticleRoot, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-116f, -116f), new Vector2(116f, 116f), new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.1f)); BuildSquareReticle(_scanReticleRoot, ScanReticleLines, 16f, 92f, ScreenDim); _scanCenterDot = CreateImage("ScanCenterDot", (Transform)(object)_scanReticleRoot, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-20f, -20f), new Vector2(20f, 20f), ScreenGreen); _scanTarget = CreateText("ScanTarget", parent, string.Empty, 104f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.3f), ScreenLineSize, ScreenGreen); _scanLinkReady = CreateText("ScanLinkReady", parent, "SPLICE READY", 104f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.195f), ScreenLineSize, ScreenAmber); ((TMP_Text)_scanLinkReady).characterSpacing = 4f; _scanLinkGlyph = BuildLinkGlyph(parent, new Vector2(0.5f, 0.095f)); ((Component)_scanLinkReady).gameObject.SetActive(false); _scanLinkGlyph.SetActive(false); } private static void BuildRadarUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_013b: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) _radarStatus = CreateText("RadarStatus", parent, "ZOOM 1.0X", 88f, (FontStyles)0, (TextAlignmentOptions)516, new Vector2(0.955f, 0.845f), new Vector2(810f, 112f), ScreenDim); CreateText("RadarZoomHint", parent, "[+/-] ZOOM", 80f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.05f), new Vector2(1080f, 112f), ScreenDim); GameObject val = new GameObject("InteriorMapTexture"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0.045f, 0.125f); val2.anchorMax = new Vector2(0.955f, 0.795f); val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; _radarImage = val.AddComponent(); ((Graphic)_radarImage).raycastTarget = false; GameObject val3 = new GameObject("RadarMarkers"); val3.transform.SetParent(parent, false); _radarMarkerLayer = val3.AddComponent(); _radarMarkerLayer.anchorMin = val2.anchorMin; _radarMarkerLayer.anchorMax = val2.anchorMax; _radarMarkerLayer.offsetMin = Vector2.zero; _radarMarkerLayer.offsetMax = Vector2.zero; } private static void BuildDroneUi(Transform parent) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00c6: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: 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_013a: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_020a: Unknown result type (might be due to invalid IL or missing references) //IL_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02bc: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("DroneFeed"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(0.045f, 0.3f); val2.anchorMax = new Vector2(0.6f, 0.86f); val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; _droneFeedImage = val.AddComponent(); ((Graphic)_droneFeedImage).raycastTarget = false; _droneFeedFallback = CreateText("DroneFeedFallback", (Transform)(object)val2, "NO LINK", 104f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.5f), new Vector2(900f, 132f), ScreenDim); _droneMarker = CreateImage("DroneMarker", (Transform)(object)val2, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-16f, -16f), new Vector2(16f, 16f), ScreenCyan); ((Transform)((Graphic)_droneMarker).rectTransform).localEulerAngles = new Vector3(0f, 0f, 45f); CreateImage("DroneColumnDivider", parent, new Vector2(0.615f, 0.3f), new Vector2(0.6275f, 0.86f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.55f)); CreateText("DroneHpLabel", parent, "HP", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.66f, 0.82f), new Vector2(540f, 112f), ScreenDim); BuildSegmentRow(parent, "DroneHpSegments", 0.66f, 0.955f, 0.7f, 0.775f, 5, DroneHpSegments); CreateText("DroneCargoLabel", parent, "CARGO", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.66f, 0.64f), new Vector2(540f, 112f), ScreenDim); BuildSegmentRow(parent, "DroneCargoSegments", 0.66f, 0.955f, 0.52f, 0.595f, 5, DroneCargoSegments); CreateText("DroneStatusLabel", parent, "STATUS", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.185f), new Vector2(450f, 112f), ScreenDim); _droneStatusValue = CreateText("DroneStatusValue", parent, "OK", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.22f, 0.185f), new Vector2(1306f, 112f), ScreenGreen); } private static void BuildCommandUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_0194: 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_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) _commandStatusLine = CreateText("CommandStatus", parent, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.815f), ScreenValueLineSize, ScreenDim); for (int i = 0; i < 5; i++) { float num = 0.7f - (float)i * 0.128f; Image val = CreateImage("CommandSelector" + i, parent, new Vector2(0.045f, num - 0.062f), new Vector2(0.955f, num + 0.062f), Vector2.zero, Vector2.zero, Color.clear); TextMeshProUGUI val2 = CreateText("CommandLabel" + i, parent, "COMMAND", 104f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.065f, num), ScreenRowLabelSize, ScreenGreen); TextMeshProUGUI val3 = CreateText("CommandReason" + i, parent, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)516, new Vector2(0.935f, num), ScreenRowDetailSize, ScreenRed); ((Component)val).gameObject.SetActive(false); ((Component)val2).gameObject.SetActive(false); ((Component)val3).gameObject.SetActive(false); CommandSelectors.Add(val); CommandLabels.Add(val2); CommandReasons.Add(val3); } _commandTelemetryLine = CreateText("CommandTelemetry", parent, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.05f), new Vector2(1261f, 112f), ScreenDim); _commandPageText = CreateText("CommandPage", parent, string.Empty, 80f, (FontStyles)0, (TextAlignmentOptions)516, new Vector2(0.955f, 0.05f), new Vector2(378f, 112f), ScreenDim); } private static void BuildSegmentRow(Transform parent, string name, float anchorMinX, float anchorMaxX, float anchorMinY, float anchorMaxY, int count, List output) { //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_0024: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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) output.Clear(); GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = new Vector2(anchorMinX, anchorMinY); val2.anchorMax = new Vector2(anchorMaxX, anchorMaxY); val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; for (int i = 0; i < count; i++) { Image item = CreateImage("Segment" + i, (Transform)(object)val2, new Vector2((float)i / (float)count, 0f), new Vector2((float)(i + 1) / (float)count, 1f), new Vector2(8f, 0f), new Vector2(-8f, 0f), ScreenGreen); output.Add(item); } } private static GameObject BuildLinkGlyph(Transform parent, Vector2 anchor) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0066: 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_007f: 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_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Expected O, but got Unknown GameObject val = new GameObject("LinkGlyph"); val.transform.SetParent(parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = anchor; val2.anchorMax = anchor; val2.pivot = new Vector2(0.5f, 0.5f); val2.sizeDelta = new Vector2(140f, 52f); BuildBoxOutline(val2, "LoopL", new Vector2(0f, 0f), new Vector2(0.42f, 1f), 10f, ScreenAmber); BuildBoxOutline(val2, "LoopR", new Vector2(0.58f, 0f), new Vector2(1f, 1f), 10f, ScreenAmber); CreateImage("LinkBar", (Transform)(object)val2, new Vector2(0.34f, 0.4f), new Vector2(0.66f, 0.6f), Vector2.zero, Vector2.zero, ScreenAmber); return val; } private static void BuildBoxOutline(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, float thickness, Color color) { //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_001a: 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_0033: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_0069: 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_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_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent((Transform)(object)parent, false); RectTransform val2 = val.AddComponent(); val2.anchorMin = anchorMin; val2.anchorMax = anchorMax; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; CreateImage("Top", (Transform)(object)val2, new Vector2(0f, 1f), Vector2.one, new Vector2(0f, 0f - thickness), Vector2.zero, color); CreateImage("Bottom", (Transform)(object)val2, Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, thickness), color); CreateImage("Left", (Transform)(object)val2, Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(thickness, 0f), color); CreateImage("Right", (Transform)(object)val2, new Vector2(1f, 0f), Vector2.one, new Vector2(0f - thickness, 0f), Vector2.zero, color); } private static void BuildHackUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012d: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_019f: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01b3: Unknown result type (might be due to invalid IL or missing references) //IL_0207: Unknown result type (might be due to invalid IL or missing references) //IL_0216: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) _hackStatusText = CreateText("HackStatus", parent, "SPLICING", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.815f), ScreenValueLineSize, ScreenAmber); _hackTargetText = CreateText("HackTarget", parent, "FIELD TARGET", 104f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.6f), ScreenLineSize, ScreenGreen); ((TMP_Text)_hackTargetText).characterSpacing = 3f; Image obj = CreateImage("HackBarBack", parent, new Vector2(0.16f, 0.42f), new Vector2(0.84f, 0.47f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.22f)); BuildBoxOutline(((Graphic)obj).rectTransform, "HackBarFrame", new Vector2(-0.01f, -0.35f), new Vector2(1.01f, 1.35f), 16f, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.55f)); _hackProgressFill = ((Graphic)CreateImage("HackBarFill", parent, new Vector2(0.16f, 0.42f), new Vector2(0.16f, 0.47f), Vector2.zero, Vector2.zero, ScreenAmber)).rectTransform; ((Graphic)obj).raycastTarget = false; _hackPercentText = CreateText("HackPercent", parent, "00%", 140f, (FontStyles)1, (TextAlignmentOptions)514, new Vector2(0.5f, 0.27f), new Vector2(1000f, 190f), ScreenAmber); _hackHintText = CreateText("HackHint", parent, "[" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.TabletBack, "BKSP") + "] ABORT", 80f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.105f), new Vector2(1170f, 112f), ScreenDim); } private static void BuildMainframeUi(Transform parent) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: 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_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Expected O, but got Unknown //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01bd: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02ab: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) _mainframeStatusText = CreateText("MainframeStatus", parent, "MAINFRAME", 88f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.045f, 0.815f), ScreenValueLineSize, ScreenAmber); for (int i = 0; i < 5; i++) { float num = 0.7f - (float)i * 0.128f; Image val = CreateImage("MainframeSelector" + i, parent, new Vector2(0.045f, num - 0.062f), new Vector2(0.955f, num + 0.062f), Vector2.zero, Vector2.zero, Color.clear); TextMeshProUGUI val2 = CreateText("MainframeLabel" + i, parent, string.Empty, 104f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(0.065f, num), ScreenRowLabelSize, ScreenGreen); TextMeshProUGUI val3 = CreateText("MainframeDetail" + i, parent, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)516, new Vector2(0.935f, num), ScreenRowDetailSize, ScreenDim); ((Component)val).gameObject.SetActive(false); ((Component)val2).gameObject.SetActive(false); ((Component)val3).gameObject.SetActive(false); MainframeSelectors.Add(val); MainframeLabels.Add(val2); MainframeDetails.Add(val3); } _uplinkProgressRoot = new GameObject("UplinkProgress", new Type[1] { typeof(RectTransform) }); _uplinkProgressRoot.transform.SetParent(parent, false); RectTransform component = _uplinkProgressRoot.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; BuildBoxOutline(((Graphic)CreateImage("UplinkBarBack", (Transform)(object)component, new Vector2(0.16f, 0.035f), new Vector2(0.72f, 0.075f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.22f))).rectTransform, "UplinkBarFrame", new Vector2(-0.01f, -0.35f), new Vector2(1.01f, 1.35f), 16f, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.55f)); _uplinkProgressFill = ((Graphic)CreateImage("UplinkBarFill", (Transform)(object)component, new Vector2(0.16f, 0.035f), new Vector2(0.16f, 0.075f), Vector2.zero, Vector2.zero, ScreenAmber)).rectTransform; _uplinkProgressRoot.SetActive(false); _mainframePageText = CreateText("MainframePage", parent, string.Empty, 80f, (FontStyles)0, (TextAlignmentOptions)516, new Vector2(0.955f, 0.05f), new Vector2(378f, 112f), ScreenDim); } private static void BuildTabBar(Transform parent) { //IL_0056: 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) //IL_009e: 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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) TabLabels.Clear(); float[] array = new float[4] { 0.045f, 0.28f, 0.48f, 0.76f }; for (int i = 0; i < TabNames.Length; i++) { TextMeshProUGUI item = CreateText("Tab_" + TabNames[i], parent, " " + TabNames[i], 112f, (FontStyles)0, (TextAlignmentOptions)513, new Vector2(array[i], 0.945f), new Vector2(432f, 132f), ScreenDim); TabLabels.Add(item); } CreateImage("TabBarDivider", parent, new Vector2(0.03f, 0.895f), new Vector2(0.97f, 0.90749997f), Vector2.zero, Vector2.zero, new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.55f)); } private static void BuildCrtOverlay(RectTransform root) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_008b: 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_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) for (int i = 1; i < 9; i++) { float num = (float)i / 9f; CreateImage("Scanline" + i, (Transform)(object)root, new Vector2(0f, num), new Vector2(1f, num), new Vector2(0f, -4f), new Vector2(0f, 4f), new Color(0f, 0f, 0f, 0.22f)); } _rollingScanline = CreateImage("RollingScanline", (Transform)(object)root, new Vector2(0f, 0.5f), new Vector2(1f, 0.5f), new Vector2(0f, -8f), new Vector2(0f, 8f), new Color(ScreenGreen.r, ScreenGreen.g, ScreenGreen.b, 0.2f)); } private static void BuildCalibrationOverlay(RectTransform root) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected O, but got Unknown //IL_003f: 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_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_007a: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d1: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_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_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: 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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_021b: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0268: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_0297: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0308: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Unknown result type (might be due to invalid IL or missing references) //IL_0342: Unknown result type (might be due to invalid IL or missing references) //IL_0347: Unknown result type (might be due to invalid IL or missing references) //IL_0376: Unknown result type (might be due to invalid IL or missing references) //IL_0385: Unknown result type (might be due to invalid IL or missing references) //IL_038a: Unknown result type (might be due to invalid IL or missing references) //IL_0399: Unknown result type (might be due to invalid IL or missing references) //IL_039e: Unknown result type (might be due to invalid IL or missing references) _calibrationRoot = new GameObject("Calibration", new Type[1] { typeof(RectTransform) }); _calibrationRoot.transform.SetParent((Transform)(object)root, false); RectTransform component = _calibrationRoot.GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; CreateImage("CalEdgeTop", (Transform)(object)component, new Vector2(0f, 1f), Vector2.one, new Vector2(0f, -16f), Vector2.zero, ScreenAmber); CreateImage("CalEdgeBottom", (Transform)(object)component, Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 16f), ScreenAmber); CreateImage("CalEdgeLeft", (Transform)(object)component, Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(16f, 0f), ScreenAmber); CreateImage("CalEdgeRight", (Transform)(object)component, new Vector2(1f, 0f), Vector2.one, new Vector2(-16f, 0f), Vector2.zero, ScreenAmber); BuildCalibrationCorner(component, "CalCornerBL", new Vector2(0f, 0f), 1f, 1f); BuildCalibrationCorner(component, "CalCornerBR", new Vector2(1f, 0f), -1f, 1f); BuildCalibrationCorner(component, "CalCornerTL", new Vector2(0f, 1f), 1f, -1f); BuildCalibrationCorner(component, "CalCornerTR", new Vector2(1f, 1f), -1f, -1f); CreateImage("CalCrossH", (Transform)(object)component, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-220f, -8f), new Vector2(220f, 8f), ScreenCyan); CreateImage("CalCrossV", (Transform)(object)component, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-8f, -220f), new Vector2(8f, 220f), ScreenCyan); CreateImage("CalReadoutPanel", (Transform)(object)component, new Vector2(0.16f, 0.06f), new Vector2(0.84f, 0.31f), Vector2.zero, Vector2.zero, new Color(ScreenPanel.r, ScreenPanel.g, ScreenPanel.b, 0.92f)); CreateText("CalTitle", (Transform)(object)component, "APERTURE CAL", 88f, (FontStyles)1, (TextAlignmentOptions)514, new Vector2(0.5f, 0.265f), new Vector2(1200f, 110f), ScreenAmber); _calibrationOffsetReadout = CreateText("CalOffset", (Transform)(object)component, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.185f), new Vector2(1200f, 110f), ScreenGreen); _calibrationSizeReadout = CreateText("CalSize", (Transform)(object)component, string.Empty, 88f, (FontStyles)0, (TextAlignmentOptions)514, new Vector2(0.5f, 0.105f), new Vector2(1200f, 110f), ScreenGreen); RefreshCalibrationReadout(ResolveScreenLocalOffset(), ResolveScreenLocalSize()); _calibrationRoot.SetActive(false); } private static void BuildCalibrationCorner(RectTransform parent, string name, Vector2 corner, float signX, float signY) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) float num = 34f * signX; float num2 = 294f * signX; float num3 = 34f * signY; float num4 = 294f * signY; float num5 = 62f * signX; float num6 = 62f * signY; CreateImage(name + "H", (Transform)(object)parent, corner, corner, new Vector2(Mathf.Min(num, num2), Mathf.Min(num3, num6)), new Vector2(Mathf.Max(num, num2), Mathf.Max(num3, num6)), ScreenGreen); CreateImage(name + "V", (Transform)(object)parent, corner, corner, new Vector2(Mathf.Min(num, num5), Mathf.Min(num3, num4)), new Vector2(Mathf.Max(num, num5), Mathf.Max(num3, num4)), ScreenGreen); } private static CanvasGroup CreateGroup(string name, Transform parent) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; CanvasGroup obj2 = val.AddComponent(); obj2.blocksRaycasts = false; obj2.interactable = false; return obj2; } private static TextMeshProUGUI CreateText(string name, Transform parent, string text, float size, FontStyles style, TextAlignmentOptions alignment, Vector2 anchor, Vector2 boxSize, Color color) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Invalid comparison between Unknown and I4 //IL_0054: 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_0069: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = anchor; obj.anchorMax = anchor; obj.pivot = new Vector2(((int)alignment == 516) ? 1f : (((int)alignment == 514) ? 0.5f : 0f), 0.5f); obj.anchoredPosition = Vector2.zero; obj.sizeDelta = boxSize; TextMeshProUGUI val2 = val.AddComponent(); ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = size; ((TMP_Text)val2).fontStyle = style; ((TMP_Text)val2).alignment = alignment; ((Graphic)val2).color = color; ((Graphic)val2).raycastTarget = false; ((TMP_Text)val2).enableWordWrapping = false; TMP_FontAsset val3 = ResolveFont(); if ((Object)(object)val3 != (Object)null) { ((TMP_Text)val2).font = val3; } return val2; } private static TextMeshProUGUI CreateWorldReticleText(string name, Transform parent, float size, Vector2 boxSize) { //IL_0018: 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_001e: Unknown result type (might be due to invalid IL or missing references) return CreateText(name, parent, string.Empty, size, (FontStyles)1, (TextAlignmentOptions)514, new Vector2(0.5f, 0f), boxSize, ScreenAmber); } private static Image CreateImage(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color) { //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_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_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_002f: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = anchorMin; obj.anchorMax = anchorMax; obj.offsetMin = offsetMin; obj.offsetMax = offsetMax; Image obj2 = val.AddComponent(); obj2.sprite = GetPixelSprite(); ((Graphic)obj2).color = color; ((Graphic)obj2).raycastTarget = false; return obj2; } private static void BuildSquareReticle(RectTransform root, List output, float thickness, float length, Color color) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0042: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_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_00a7: 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_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00ff: 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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019e: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_020f: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) output.Clear(); output.Add(CreateReticleLine(root, "TopLeftH", new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f - thickness), new Vector2(length, 0f), color)); output.Add(CreateReticleLine(root, "TopLeftV", new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f - length), new Vector2(thickness, 0f), color)); output.Add(CreateReticleLine(root, "TopRightH", new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(0f - length, 0f - thickness), new Vector2(0f, 0f), color)); output.Add(CreateReticleLine(root, "TopRightV", new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(0f - thickness, 0f - length), new Vector2(0f, 0f), color)); output.Add(CreateReticleLine(root, "BottomLeftH", new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(length, thickness), color)); output.Add(CreateReticleLine(root, "BottomLeftV", new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(thickness, length), color)); output.Add(CreateReticleLine(root, "BottomRightH", new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f - length, 0f), new Vector2(0f, thickness), color)); output.Add(CreateReticleLine(root, "BottomRightV", new Vector2(1f, 0f), new Vector2(1f, 0f), new Vector2(0f - thickness, 0f), new Vector2(0f, length), color)); } private static Image CreateReticleLine(RectTransform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: 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) return CreateImage(name, (Transform)(object)parent, anchorMin, anchorMax, offsetMin, offsetMax, color); } private static void EnsurePlayerCrosshair(Camera camera) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_0047: 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_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_playerReticleRoot != (Object)null) && !((Object)(object)camera == (Object)null)) { _playerReticleRoot = new GameObject("Y4NGZ_FieldTablet_PlayerWorldReticle"); Object.DontDestroyOnLoad((Object)(object)_playerReticleRoot); RectTransform val = _playerReticleRoot.AddComponent(); val.pivot = new Vector2(0.5f, 0.5f); val.sizeDelta = new Vector2(58f, 58f); Canvas obj = _playerReticleRoot.AddComponent(); obj.renderMode = (RenderMode)2; obj.worldCamera = camera; obj.sortingOrder = 0; CanvasGroup obj2 = _playerReticleRoot.AddComponent(); obj2.alpha = 0f; obj2.blocksRaycasts = false; obj2.interactable = false; SetLayerRecursively(_playerReticleRoot, 0); BuildSquareReticle(val, PlayerReticleLines, 2.2f, 13f, ScreenAmber); _worldReticleLabel = CreateWorldReticleText("WorldReticleLabel", (Transform)(object)val, 10f, new Vector2(150f, 18f)); ((TMP_Text)_worldReticleLabel).rectTransform.anchoredPosition = new Vector2(0f, -18f); SetActiveIfChanged(((Component)_worldReticleLabel).gameObject, active: false); } } private static void SetLayerRecursively(GameObject root, int layer) { if (!((Object)(object)root == (Object)null)) { root.layer = layer; for (int i = 0; i < root.transform.childCount; i++) { SetLayerRecursively(((Component)root.transform.GetChild(i)).gameObject, layer); } } } private static bool TryRenderRadarTextureThrottled(PlayerControllerB player, Vector3 focus, bool insideFactory, bool inShipRoom, bool updateMarkers) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) float unscaledTime = Time.unscaledTime; if (_mode == _lastRadarRenderedMode && unscaledTime < _nextRadarRenderAt) { return _radarRendered; } _nextRadarRenderAt = unscaledTime + 1f / 15f; _lastRadarRenderedMode = _mode; _radarRendered = RenderRadarTexture(player, focus, insideFactory, inShipRoom); if (_radarRendered && updateMarkers) { UpdateRadarMarkers(player); } return _radarRendered; } private static bool RenderRadarTexture(PlayerControllerB player, Vector3 focus, bool insideFactory, bool inShipRoom) { //IL_013c: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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_00c9: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) ManualCameraRenderer val = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.mapScreen : null); Camera val2 = (((Object)(object)val != (Object)null) ? val.mapCamera : null); if ((Object)(object)player == (Object)null || (Object)(object)val2 == (Object)null) { return false; } EnsureRadarTexture(); EnsureRadarCamera(val2); if ((Object)(object)_radarCamera == (Object)null || (Object)(object)_radarTexture == (Object)null) { return false; } ConfigureRadarCamera(val, val2, focus, insideFactory, inShipRoom); _vanillaMapUiState = HideVanillaMapUi(val); GameObject val3 = ResolveContourMap(val); bool flag = false; bool active = false; Vector3 val4 = Vector3.zero; if ((Object)(object)val3 != (Object)null) { flag = true; active = val3.activeSelf; val4 = val3.transform.position; bool flag2 = !insideFactory; val3.SetActive(flag2); if (flag2) { val3.transform.position = new Vector3(val4.x, focus.y - 1.5f, val4.z); } } try { _radarCamera.Render(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Field Tablet] radar render skipped: " + ex.Message)); } return false; } finally { if (flag && (Object)(object)val3 != (Object)null) { val3.SetActive(active); val3.transform.position = val4; } RestoreVanillaMapUi(val); } return true; } private static void EnsureRadarTexture() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0069: 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_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_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Expected O, but got Unknown if ((Object)(object)_radarTexture != (Object)null && _radarTexture.IsCreated()) { if ((Object)(object)_radarImage != (Object)null && (Object)(object)_radarImage.texture != (Object)(object)_radarTexture) { _radarImage.texture = (Texture)(object)_radarTexture; } return; } _radarTexture = new RenderTexture(1024, 1024, 16, (RenderTextureFormat)0) { name = "Y4NGZ_FieldTablet_RadarTexture", hideFlags = (HideFlags)61, filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, useMipMap = false, autoGenerateMips = false }; _radarTexture.Create(); if ((Object)(object)_radarImage != (Object)null) { _radarImage.texture = (Texture)(object)_radarTexture; } } private static void EnsureRadarCamera(Camera sourceCamera) { //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_0084: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)sourceCamera == (Object)null)) { if ((Object)(object)_radarCamera == (Object)null) { _radarCamera = new GameObject("Y4NGZ_FieldTablet_RadarCamera") { hideFlags = (HideFlags)61 }.AddComponent(); } if ((Object)(object)_radarSourceCamera != (Object)(object)sourceCamera) { _radarCamera.CopyFrom(sourceCamera); _radarSourceCamera = sourceCamera; } ((Behaviour)_radarCamera).enabled = false; _radarCamera.targetTexture = _radarTexture; _radarCamera.rect = new Rect(0f, 0f, 1f, 1f); _radarCamera.aspect = 1f; } } private static void ConfigureRadarCamera(ManualCameraRenderer mapScreen, Camera sourceCamera, Vector3 focus, bool insideFactory, bool inShipRoom) { //IL_000a: 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_001c: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) ((Component)_radarCamera).transform.SetPositionAndRotation(new Vector3(focus.x, focus.y + 3.636f, focus.z), ((Component)sourceCamera).transform.rotation); _radarCamera.cullingMask = sourceCamera.cullingMask; _radarCamera.clearFlags = sourceCamera.clearFlags; _radarCamera.backgroundColor = sourceCamera.backgroundColor; _radarCamera.orthographic = sourceCamera.orthographic; _radarCamera.orthographicSize = Mathf.Max(1f, sourceCamera.orthographicSize / Mathf.Max(0.1f, _radarZoom)); _radarCamera.fieldOfView = sourceCamera.fieldOfView; if (inShipRoom) { _radarCamera.nearClipPlane = -0.96f; _radarCamera.farClipPlane = 7.52f; } else if (!insideFactory) { float num = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraNearPlane : sourceCamera.nearClipPlane); float num2 = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraFarPlane : sourceCamera.farClipPlane); _radarCamera.nearClipPlane = num - 18f; _radarCamera.farClipPlane = num2 + 18f; } else { _radarCamera.nearClipPlane = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraNearPlane : sourceCamera.nearClipPlane); _radarCamera.farClipPlane = (((Object)(object)mapScreen != (Object)null) ? mapScreen.cameraFarPlane : sourceCamera.farClipPlane); } } private static Vector3 ResolveRadarFocus(PlayerControllerB player) { //IL_0006: 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_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_005d: 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_006c: 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) Vector3 result = ((Component)player).transform.position; int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMask : (-1)); RaycastHit val = default(RaycastHit); if (Physics.Raycast(((Component)player).transform.position + Vector3.up * 0.1f, Vector3.down, ref val, 5f, num, (QueryTriggerInteraction)1)) { result = ((RaycastHit)(ref val)).point + Vector3.up * 0.06f; } return result; } private static GameObject ResolveContourMap(ManualCameraRenderer mapScreen) { if ((Object)(object)mapScreen == (Object)null) { return null; } if ((Object)(object)mapScreen.contourMap != (Object)null) { return mapScreen.contourMap; } try { GameObject val = GameObject.FindGameObjectWithTag("TerrainContourMap"); if ((Object)(object)val != (Object)null) { mapScreen.contourMap = val; } return val; } catch { return null; } } private static VanillaMapUiState HideVanillaMapUi(ManualCameraRenderer mapScreen) { VanillaMapUiState result = default(VanillaMapUiState); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.mapScreenPlayerName != (Object)null) { result.MapScreenPlayerNameEnabled = ((Behaviour)instance.mapScreenPlayerName).enabled; ((Behaviour)instance.mapScreenPlayerName).enabled = false; } if ((Object)(object)instance.mapScreenPlayerNameBG != (Object)null) { result.MapScreenPlayerNameBgEnabled = ((Behaviour)instance.mapScreenPlayerNameBG).enabled; ((Behaviour)instance.mapScreenPlayerNameBG).enabled = false; } } if ((Object)(object)mapScreen == (Object)null) { return result; } if ((Object)(object)mapScreen.headMountedCamUI != (Object)null) { result.HeadMountedCamUiEnabled = ((Behaviour)mapScreen.headMountedCamUI).enabled; ((Behaviour)mapScreen.headMountedCamUI).enabled = false; } if ((Object)(object)mapScreen.localPlayerPlaceholder != (Object)null) { result.LocalPlayerPlaceholderEnabled = ((Behaviour)mapScreen.localPlayerPlaceholder).enabled; ((Behaviour)mapScreen.localPlayerPlaceholder).enabled = false; } if ((Object)(object)mapScreen.compassRose != (Object)null) { result.CompassRoseEnabled = ((Behaviour)mapScreen.compassRose).enabled; ((Behaviour)mapScreen.compassRose).enabled = false; } if ((Object)(object)mapScreen.shipArrowUI != (Object)null) { result.ShipArrowUiActive = mapScreen.shipArrowUI.activeSelf; mapScreen.shipArrowUI.SetActive(false); } if ((Object)(object)mapScreen.shipIcon != (Object)null) { result.ShipIconActive = mapScreen.shipIcon.activeSelf; mapScreen.shipIcon.SetActive(false); } if ((Object)(object)mapScreen.LostSignalUI != (Object)null) { result.LostSignalUiActive = mapScreen.LostSignalUI.activeSelf; mapScreen.LostSignalUI.SetActive(false); } if ((Object)(object)mapScreen.lineFromRadarTargetToExit != (Object)null) { result.ExitLineEnabled = ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled; ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled = false; } return result; } private static void RestoreVanillaMapUi(ManualCameraRenderer mapScreen) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.mapScreenPlayerName != (Object)null) { ((Behaviour)instance.mapScreenPlayerName).enabled = _vanillaMapUiState.MapScreenPlayerNameEnabled; } if ((Object)(object)instance.mapScreenPlayerNameBG != (Object)null) { ((Behaviour)instance.mapScreenPlayerNameBG).enabled = _vanillaMapUiState.MapScreenPlayerNameBgEnabled; } } if (!((Object)(object)mapScreen == (Object)null)) { if ((Object)(object)mapScreen.headMountedCamUI != (Object)null) { ((Behaviour)mapScreen.headMountedCamUI).enabled = _vanillaMapUiState.HeadMountedCamUiEnabled; } if ((Object)(object)mapScreen.localPlayerPlaceholder != (Object)null) { ((Behaviour)mapScreen.localPlayerPlaceholder).enabled = _vanillaMapUiState.LocalPlayerPlaceholderEnabled; } if ((Object)(object)mapScreen.compassRose != (Object)null) { ((Behaviour)mapScreen.compassRose).enabled = _vanillaMapUiState.CompassRoseEnabled; } if ((Object)(object)mapScreen.shipArrowUI != (Object)null) { mapScreen.shipArrowUI.SetActive(_vanillaMapUiState.ShipArrowUiActive); } if ((Object)(object)mapScreen.shipIcon != (Object)null) { mapScreen.shipIcon.SetActive(_vanillaMapUiState.ShipIconActive); } if ((Object)(object)mapScreen.LostSignalUI != (Object)null) { mapScreen.LostSignalUI.SetActive(_vanillaMapUiState.LostSignalUiActive); } if ((Object)(object)mapScreen.lineFromRadarTargetToExit != (Object)null) { ((Renderer)mapScreen.lineFromRadarTargetToExit).enabled = _vanillaMapUiState.ExitLineEnabled; } } } private static void UpdateRadarMarkers(PlayerControllerB player) { //IL_002e: 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_0043: 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_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_radarMarkerLayer == (Object)null || (Object)(object)_radarCamera == (Object)null || (Object)(object)player == (Object)null) { return; } int used = 0; AddRadarMarker(ref used, ((Component)player).transform.position, ScreenGreen, 16f, ((Component)player).transform.eulerAngles.y); StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && instance.allPlayerScripts != null) { for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)player) && !val.isPlayerDead && val.isPlayerControlled && val.isInsideFactory == player.isInsideFactory) { AddRadarMarker(ref used, ((Component)val).transform.position, ScreenAmber, 12f, float.NaN); } } } EntranceTeleport[] array = Object.FindObjectsOfType(); bool flag = !player.isInsideFactory; foreach (EntranceTeleport val2 in array) { if (!((Object)(object)val2 == (Object)null) && val2.isEntranceToBuilding == flag) { Vector3 worldPosition = (((Object)(object)val2.entrancePoint != (Object)null) ? val2.entrancePoint.position : ((Component)val2).transform.position); AddRadarMarker(ref used, worldPosition, (val2.entranceId == 0) ? ScreenCyan : ScreenAmber, (val2.entranceId == 0) ? 12f : 9f, float.NaN); } } for (int k = used; k < RadarMarkers.Count; k++) { if ((Object)(object)RadarMarkers[k] != (Object)null) { SetActiveIfChanged(((Component)RadarMarkers[k]).gameObject, active: false); } } } private static void AddRadarMarker(ref int used, Vector3 worldPosition, Color color, float size, float headingDegrees) { //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_0034: 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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (TryWorldToRadarPosition(worldPosition + Vector3.up * 0.25f, out var anchoredPosition)) { Image radarMarker = GetRadarMarker(used++); RectTransform rectTransform = ((Graphic)radarMarker).rectTransform; rectTransform.anchoredPosition = anchoredPosition; rectTransform.sizeDelta = new Vector2(size, size); ((Transform)rectTransform).localEulerAngles = (float.IsNaN(headingDegrees) ? new Vector3(0f, 0f, 45f) : new Vector3(0f, 0f, 0f - headingDegrees)); SetColorIfChanged((Graphic)(object)radarMarker, color); SetActiveIfChanged(((Component)radarMarker).gameObject, active: true); } } private static bool TryWorldToRadarPosition(Vector3 worldPosition, out Vector2 anchoredPosition) { //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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: 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_004d: 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_0067: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: 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) anchoredPosition = Vector2.zero; if ((Object)(object)_radarCamera == (Object)null || (Object)(object)_radarMarkerLayer == (Object)null) { return false; } Vector3 val = _radarCamera.WorldToViewportPoint(worldPosition); if (val.z < 0f || val.x < 0f || val.x > 1f || val.y < 0f || val.y > 1f) { return false; } Rect rect = _radarMarkerLayer.rect; anchoredPosition = new Vector2((val.x - 0.5f) * ((Rect)(ref rect)).width, (val.y - 0.5f) * ((Rect)(ref rect)).height); return true; } private static Image GetRadarMarker(int index) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) while (RadarMarkers.Count <= index) { Image val = CreateImage("RadarMarker", (Transform)(object)_radarMarkerLayer, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(-6f, -6f), new Vector2(6f, 6f), ScreenGreen); ((Component)val).gameObject.SetActive(false); RadarMarkers.Add(val); } return RadarMarkers[index]; } private static void SetGroup(CanvasGroup group, bool active, float alpha) { if (!((Object)(object)group == (Object)null)) { SetActiveIfChanged(((Component)group).gameObject, active); if (!Mathf.Approximately(group.alpha, alpha)) { group.alpha = alpha; } } } private static string ResolveDisplayName(Component component, string fallback) { if ((Object)(object)component == (Object)null) { return fallback; } PropertyInfo property = ((object)component).GetType().GetProperty("DisplayName", BindingFlags.Instance | BindingFlags.Public); string text = ((property != null) ? property.GetValue(component) : null) as string; if (!string.IsNullOrWhiteSpace(text)) { return text; } return fallback; } private static string ResolveItemName(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return "ITEM"; } if ((Object)(object)item.itemProperties != (Object)null && !string.IsNullOrWhiteSpace(item.itemProperties.itemName)) { return item.itemProperties.itemName.ToUpperInvariant(); } if (!string.IsNullOrWhiteSpace(((Object)item).name)) { return ((Object)item).name.ToUpperInvariant(); } return "ITEM"; } private static string FormatTargetKind(TabletHackTargetKind kind) { return kind switch { TabletHackTargetKind.Mainframe => "MAINFRAME", TabletHackTargetKind.CompanyStash => "COMPANY STASH", TabletHackTargetKind.CctvCamera => "CCTV CAMERA", TabletHackTargetKind.Turret => "TURRET", TabletHackTargetKind.LockedDoor => "LOCKED DOOR", TabletHackTargetKind.DronePickup => "DRONE PICKUP", _ => "SIGNAL", }; } private static TMP_FontAsset ResolveFont() { if ((Object)(object)_font != (Object)null) { return _font; } try { if ((Object)(object)HUDManager.Instance != (Object)null && HUDManager.Instance.controlTipLines != null) { for (int i = 0; i < HUDManager.Instance.controlTipLines.Length; i++) { TextMeshProUGUI val = HUDManager.Instance.controlTipLines[i]; if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)val).font != (Object)null) { _font = ((TMP_Text)val).font; return _font; } } } } catch { return null; } return null; } private static Sprite GetPixelSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_004d: 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_0066: Expected O, but got Unknown if ((Object)(object)_pixelSprite != (Object)null) { return _pixelSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, Color.white); val.Apply(false, true); _pixelSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); ((Object)_pixelSprite).hideFlags = (HideFlags)61; return _pixelSprite; } private static void SetTexture(Material material, string property, Texture texture) { if ((Object)(object)material != (Object)null && (Object)(object)texture != (Object)null && material.HasProperty(property)) { material.SetTexture(property, texture); } } private static void SetColor(Material material, string property, Color value) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)material != (Object)null && material.HasProperty(property)) { material.SetColor(property, value); } } private static void SetFloat(Material material, string property, float value) { if ((Object)(object)material != (Object)null && material.HasProperty(property)) { material.SetFloat(property, value); } } private static string GetHierarchyPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return ""; } List list = new List(); Transform val = transform; while ((Object)(object)val != (Object)null && list.Count < 12) { list.Add(((Object)val).name); val = val.parent; } list.Reverse(); return string.Join("/", list); } private static void SetLayerRecursive(GameObject root, int layer) { if ((Object)(object)root == (Object)null) { return; } Transform[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { if ((Object)(object)componentsInChildren[i] != (Object)null) { ((Component)componentsInChildren[i]).gameObject.layer = layer; } } } private static bool Contains(string value, string fragment) { if (!string.IsNullOrEmpty(value) && !string.IsNullOrEmpty(fragment)) { return value.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0; } return false; } private static void DestroyObject(Object obj) { if (obj != (Object)null) { Object.Destroy(obj); } } } internal static class FistSurfaceClassifier { internal const int UnknownSurface = -1; internal static int ResolveSurfaceIndex(Collider collider) { if ((Object)(object)collider == (Object)null) { return -1; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.footstepSurfaces == null) { return -1; } GameObject gameObject = ((Component)collider).gameObject; if ((Object)(object)gameObject == (Object)null) { return -1; } string tag = gameObject.tag; if (string.IsNullOrEmpty(tag) || tag == "Untagged") { return -1; } FootstepSurface[] footstepSurfaces = instance.footstepSurfaces; for (int i = 0; i < footstepSurfaces.Length; i++) { if (footstepSurfaces[i] != null && footstepSurfaces[i].surfaceTag == tag) { return i; } } return -1; } internal static string SurfaceTag(int surfaceIndex) { FootstepSurface val = SurfaceAt(surfaceIndex); if (val == null || val.surfaceTag == null) { return string.Empty; } return val.surfaceTag; } internal static AudioClip HitSurfaceClip(int surfaceIndex) { return SurfaceAt(surfaceIndex)?.hitSurfaceSFX; } private static FootstepSurface SurfaceAt(int surfaceIndex) { if (surfaceIndex < 0) { return null; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.footstepSurfaces == null) { return null; } if (surfaceIndex >= instance.footstepSurfaces.Length) { return null; } return instance.footstepSurfaces[surfaceIndex]; } } [HarmonyPatch] internal static class ForemanPingPatch { private enum MarkKind { Location, Enemy, Player, Item, Interactable, Trap, Entrance } private enum InspireResult : byte { Success, NoResponse, AlreadyUsed, InvalidTarget, OutOfRange } private struct PingTarget { internal MarkKind Kind; internal GameObject Root; internal ulong NetworkObjectId; internal int PlayerId; internal Vector3 Position; internal string Label; } private struct PingCandidate { internal PingTarget Target; internal Collider Collider; internal float Distance; internal float Angle; internal float Score; internal string Source; } private struct RemotePointState { internal float Until; internal float Weight; internal HeldItemStowHandle Stow; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveMark; public static HandleNamedMessageDelegate <1>__OnReceiveReviveRequest; public static HandleNamedMessageDelegate <2>__OnReceiveReviveResult; public static HandleNamedMessageDelegate <3>__OnReceiveRevive; public static HandleNamedMessageDelegate <4>__OnReceivePointing; } private const string MSG_MARK_SYNC = "ForemanPing_Mark"; private const string MSG_REVIVE_REQUEST = "ForemanPing_InspireRequest"; private const string MSG_REVIVE_RESULT = "ForemanPing_InspireResult"; private const string MSG_REVIVE_SYNC = "ForemanPing_Revive"; private const string MSG_POINT_SYNC = "ForemanPing_Point"; private const string PROMPT_KEY = "foreman_ping"; private const int POINT_EMOTE_ID = 2; private const float POINT_DURATION = 1f; private const float POINT_FADE_SECONDS = 0.08f; private const string STOW_REASON = "foreman-ping-point"; private const float POINT_STOW_TIMEOUT_SECONDS = 4f; private const float TARGET_SPHERE_RADIUS = 0.75f; private const float TARGET_MAX_ANGLE = 22f; private const float TARGET_NETWORK_FALLBACK_RADIUS = 4f; private static readonly Dictionary MarkedEnemies = new Dictionary(); private static readonly Dictionary MarkedPlayers = new Dictionary(); private static readonly Dictionary RemotePointStates = new Dictionary(); private static HeldItemStowHandle _localPointStow; private static readonly HashSet InspireUsedThisRoundByClient = new HashSet(); private static float _nextPingTime; private static float _nextInspireTime; private static bool _handlersRegistered; private static bool _pointingLayerActive; private static float _localPointUntil; private static float _localPointWeight; private static EnemyAI _recentContactEnemy; private static float _recentContactExpiresAt; private static string _cachedPromptText; private static string _cachedPromptPath; internal static void OnRoundStarted() { RegisterNetworkHandlers(); _nextPingTime = 0f; _nextInspireTime = 0f; ClearServerInspireUses(); _pointingLayerActive = false; _localPointUntil = 0f; _localPointWeight = 0f; _localPointStow.Dispose(); _localPointStow = default(HeldItemStowHandle); RemotePointStates.Clear(); MarkedEnemies.Clear(); MarkedPlayers.Clear(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { _nextInspireTime = 0f; ClearServerInspireUses(); _pointingLayerActive = false; _localPointUntil = 0f; _localPointWeight = 0f; _localPointStow.Dispose(); _localPointStow = default(HeldItemStowHandle); RemotePointStates.Clear(); MarkedEnemies.Clear(); MarkedPlayers.Clear(); Y4ngzPromptOverlay.ClearPersistentPrompt("foreman_ping"); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _nextInspireTime = 0f; InspireUsedThisRoundByClient.Clear(); _handlersRegistered = false; } private static void ClearServerInspireUses() { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer) { InspireUsedThisRoundByClient.Clear(); } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { try { if ((Object)(object)__instance == (Object)null) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)__instance != (Object)(object)val) { UpdateRemotePointingLayer(__instance, advanceWeight: true); return; } UpdatePrompt(val); UpdateLocalPointingLayer(val, advanceWeight: true); if (UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.ForemanPing) && CanUsePingInput(val) && HasAnyPingFeature() && !TryHandleInspire(val) && !(Time.time < _nextPingTime)) { _nextPingTime = Time.time + 3f; PulsePointing(val); TryHandlePing(val); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"ForemanPingPatch: PostPlayerUpdate failed: {arg}"); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)__instance == (Object)(object)val) { UpdateLocalPointingLayer(val, advanceWeight: false); } else { UpdateRemotePointingLayer(__instance, advanceWeight: false); } } } [HarmonyPatch(typeof(EnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static void PreEnemyCollideWithPlayer(EnemyAI __instance, Collider other) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)other == (Object)null)) { PlayerControllerB component = ((Component)other).GetComponent(); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)val)) { _recentContactEnemy = __instance; _recentContactExpiresAt = Time.time + 0.4f; } } } internal static float GetMarkedTeammateDamageReduction(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0f; } int key = (int)player.playerClientId; if (!MarkedPlayers.TryGetValue(key, out var value)) { return 0f; } if (Time.time >= value) { MarkedPlayers.Remove(key); return 0f; } return 0.2f; } internal static float GetRecentMarkedEnemyDamageReduction() { if ((Object)(object)_recentContactEnemy == (Object)null || Time.time >= _recentContactExpiresAt) { return 0f; } if (!IsEnemyMarked(_recentContactEnemy)) { return 0f; } return 0.2f; } private static bool IsEnemyMarked(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return false; } ulong networkObjectId = ((NetworkBehaviour)enemy).NetworkObjectId; if (!MarkedEnemies.TryGetValue(networkObjectId, out var value)) { return false; } if (Time.time >= value) { MarkedEnemies.Remove(networkObjectId); return false; } return true; } private static bool CanUsePingInput(PlayerControllerB player) { if ((Object)(object)player != (Object)null && ((NetworkBehaviour)player).IsOwner && player.isPlayerControlled && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu) { if (!((Object)(object)player.quickMenuManager == (Object)null)) { return !player.quickMenuManager.isMenuOpen; } return true; } return false; } private static bool HasAnyPingFeature() { if (!PingUpgrade.IsUnlocked()) { return InspireUpgrade.IsUnlocked(); } return true; } private static void TryHandlePing(PlayerControllerB player) { if (!PingUpgrade.IsUnlocked()) { return; } if (TryFindPingTarget(player, out var target)) { ApplyMark(target, PingUpgrade.GetTier(), fromNetwork: false); BroadcastMark(target, PingUpgrade.GetTier()); return; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)"ForemanPingPatch: no valid ping target; ignoring ping without location marker."); } } private static bool TryHandleInspire(PlayerControllerB player) { if (!InspireUpgrade.IsUnlocked()) { return false; } DeadBodyInfo val = FindLookedAtDeadBody(player); if ((Object)(object)val == (Object)null || (Object)(object)val.playerScript == (Object)null) { return false; } if (Time.time < _nextInspireTime) { int num = Mathf.CeilToInt(_nextInspireTime - Time.time); HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("INSPIRE", $"Ready in {num}s.", true, false, "LC_Tip1"); } return true; } RequestRevive((int)val.playerScript.playerClientId); return true; } private static DeadBodyInfo FindLookedAtDeadBody(PlayerControllerB player) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0149: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return null; } RaycastHit[] array = Physics.RaycastAll(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), 7f, -1, (QueryTriggerInteraction)2); Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); for (int num = 0; num < array.Length; num++) { DeadBodyInfo val2 = (((Object)(object)((RaycastHit)(ref array[num])).collider != (Object)null) ? ((Component)((RaycastHit)(ref array[num])).collider).GetComponentInParent() : null); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.playerScript != (Object)null && val2.playerScript.isPlayerDead) { return val2; } } DeadBodyInfo result = null; float num2 = 6f; DeadBodyInfo[] array2 = Object.FindObjectsOfType(); foreach (DeadBodyInfo val3 in array2) { if ((Object)(object)val3 == (Object)null || (Object)(object)val3.playerScript == (Object)null || !val3.playerScript.isPlayerDead) { continue; } Vector3 val4 = ResolveBodyCenter(val3); if (!(Vector3.Distance(((Component)player).transform.position, val4) > 7f)) { float num4 = Vector3.Angle(((Component)val).transform.forward, val4 - ((Component)val).transform.position); if (num4 < num2) { result = val3; num2 = num4; } } } return result; } private static bool TryFindPingTarget(PlayerControllerB player, out PingTarget target) { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007b: 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) target = default(PingTarget); Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return false; } Ray val2 = default(Ray); ((Ray)(ref val2))..ctor(((Component)val).transform.position, ((Component)val).transform.forward); RaycastHit[] array = Physics.RaycastAll(val2, 80f, -1, (QueryTriggerInteraction)2); RaycastHit[] array2 = Physics.SphereCastAll(val2, 0.75f, 80f, -1, (QueryTriggerInteraction)2); List list = new List(array.Length + array2.Length); AddPingCandidates(player, val2, array, "ray", list); AddPingCandidates(player, val2, array2, "sphere", list); if (list.Count <= 0) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)$"ForemanPingPatch: target resolution missed. rayHits={array.Length}, sphereHits={array2.Length}"); } return false; } list.Sort((PingCandidate a, PingCandidate b) => a.Score.CompareTo(b.Score)); PingCandidate pingCandidate = list[0]; target = pingCandidate.Target; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogDebug((object)string.Format("ForemanPingPatch: target={0}:{1} source={2} collider={3} distance={4:F1} angle={5:F1} root={6} net={7}", target.Kind, target.Label, pingCandidate.Source, DescribeCollider(pingCandidate.Collider), pingCandidate.Distance, pingCandidate.Angle, ((Object)(object)target.Root != (Object)null) ? ((Object)target.Root).name : "null", target.NetworkObjectId)); } return true; } private static void AddPingCandidates(PlayerControllerB player, Ray ray, RaycastHit[] hits, string source, List candidates) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: 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_00df: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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_011f: Unknown result type (might be due to invalid IL or missing references) Array.Sort(hits, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); HashSet hashSet = new HashSet(); for (int num = 0; num < hits.Length; num++) { Collider collider = ((RaycastHit)(ref hits[num])).collider; if ((Object)(object)collider == (Object)null || (Object)(object)((Component)collider).GetComponentInParent() == (Object)(object)player || !TryResolveTarget(collider, ((RaycastHit)(ref hits[num])).point, out var target)) { continue; } GameObject val = (((Object)(object)target.Root != (Object)null) ? target.Root : ((Component)collider).gameObject); if (!((Object)(object)val != (Object)null) || !hashSet.Contains(val)) { if ((Object)(object)val != (Object)null) { hashSet.Add(val); } Vector3 val2 = target.Position; if (val2 == Vector3.zero) { val2 = ((RaycastHit)(ref hits[num])).point; } Vector3 val3 = val2 - ((Ray)(ref ray)).origin; float num2 = Mathf.Max(0f, ((Vector3)(ref val3)).magnitude); float num3 = ((num2 > 0.01f) ? Vector3.Angle(((Ray)(ref ray)).direction, val3 / num2) : 0f); if (!(num3 > 22f)) { float num4 = ((source == "ray") ? 0f : 3f); float score = num2 + num3 * 1.75f + KindScorePenalty(target.Kind) + num4; candidates.Add(new PingCandidate { Target = target, Collider = collider, Distance = num2, Angle = num3, Score = score, Source = source }); } } } } private static bool TryResolveTarget(Collider collider, Vector3 hitPoint, out PingTarget target) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_014c: 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) target = default(PingTarget); EnemyAI componentInParent = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null && !componentInParent.isEnemyDead) { target = BuildTarget(MarkKind.Enemy, ((Component)componentInParent).gameObject, ((NetworkBehaviour)componentInParent).NetworkObjectId, -1, ResolveEnemyCenter(componentInParent), "enemy"); return true; } PlayerControllerB componentInParent2 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent2 != (Object)null && componentInParent2.isPlayerControlled && !componentInParent2.isPlayerDead && PingUpgrade.CanMarkTeammates()) { target = BuildTarget(MarkKind.Player, ((Component)componentInParent2).gameObject, ((NetworkBehaviour)componentInParent2).NetworkObjectId, (int)componentInParent2.playerClientId, ResolvePlayerCenter(componentInParent2), componentInParent2.playerUsername); return true; } GrabbableObject componentInParent3 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null) { GameObject root = ResolveRenderableRoot(((Component)componentInParent3).gameObject, ((Component)componentInParent3).gameObject); target = BuildTarget(MarkKind.Item, root, ((NetworkBehaviour)componentInParent3).NetworkObjectId, -1, ResolveRendererCenter(root, ((Component)componentInParent3).transform.position), ((Object)(object)componentInParent3.itemProperties != (Object)null) ? componentInParent3.itemProperties.itemName : "item"); return true; } EntranceTeleport componentInParent4 = ((Component)collider).GetComponentInParent(); if ((Object)(object)componentInParent4 != (Object)null) { GameObject root2 = ResolveRenderableRoot(((Component)componentInParent4).gameObject, ((Component)componentInParent4).gameObject); string label = ((componentInParent4.entranceId == 0) ? "main entrance" : "fire exit"); target = BuildTarget(MarkKind.Entrance, root2, ((NetworkBehaviour)componentInParent4).NetworkObjectId, -1, ResolveRendererCenter(root2, ResolveEntranceCenter(componentInParent4)), label); return true; } return false; } private static float KindScorePenalty(MarkKind kind) { switch (kind) { case MarkKind.Enemy: case MarkKind.Player: return 0f; case MarkKind.Trap: return 2f; case MarkKind.Entrance: return 4f; case MarkKind.Item: return 5f; case MarkKind.Interactable: return 8f; default: return 12f; } } private static PingTarget BuildTarget(MarkKind kind, GameObject root, ulong networkObjectId, int playerId, Vector3 position, string label) { //IL_002a: 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) return new PingTarget { Kind = kind, Root = root, NetworkObjectId = networkObjectId, PlayerId = playerId, Position = position, Label = (string.IsNullOrWhiteSpace(label) ? kind.ToString().ToLowerInvariant() : label) }; } private static ulong ResolveNetworkObjectId(GameObject root) { NetworkObject val = (((Object)(object)root != (Object)null) ? root.GetComponentInParent() : null); if (!((Object)(object)val != (Object)null)) { return 0uL; } return val.NetworkObjectId; } private static void ApplyMark(PingTarget target, int pingTier, bool fromNetwork) { float value = Time.time + 5f; if (target.Kind == MarkKind.Enemy && target.NetworkObjectId != 0L && pingTier >= 2) { MarkedEnemies[target.NetworkObjectId] = value; } if (target.Kind == MarkKind.Player && target.PlayerId >= 0 && pingTier >= 3) { MarkedPlayers[target.PlayerId] = value; } if ((Object)(object)target.Root != (Object)null) { bool flag = OutlineEffectBridge.Show(target.Root, OutlineChannelFor(target.Kind), 5f, UpgradeOutlineSource.Ping); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)string.Format("ForemanPingPatch: mark {0} kind={1} label={2} root={3} shown={4} net={5} player={6}", fromNetwork ? "recv" : "local", target.Kind, target.Label, ((Object)target.Root).name, flag, target.NetworkObjectId, target.PlayerId)); } } else { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)string.Format("ForemanPingPatch: mark {0} kind={1} label={2} had no root; no marker spawned.", fromNetwork ? "recv" : "local", target.Kind, target.Label)); } } } internal static void MarkTeammateFromCommandNet(PlayerControllerB player) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { PingTarget target = BuildTarget(MarkKind.Player, ((Component)player).gameObject, ResolveNetworkObjectId(((Component)player).gameObject), (int)player.playerClientId, ResolvePlayerCenter(player), "damaged teammate"); ApplyMark(target, 2, fromNetwork: true); BroadcastMark(target, 2); } } private static void UpdatePrompt(PlayerControllerB player) { if (!PingUpgrade.IsUnlocked()) { Y4ngzPromptOverlay.ClearPersistentPrompt("foreman_ping"); return; } if ((Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat || player.inTerminalMenu || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { Y4ngzPromptOverlay.ClearPersistentPrompt("foreman_ping"); return; } string text = UpgradeInput.EffectivePath(Y4NGZUpgrades.Gui.Plugin.Keybinds?.ForemanPing); if (_cachedPromptText == null || !string.Equals(_cachedPromptPath, text, StringComparison.Ordinal)) { _cachedPromptPath = text; string text2 = UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.ForemanPing, "Q"); _cachedPromptText = "[" + text2 + "] to ping"; } Y4ngzPromptOverlay.SetPersistentPrompt("foreman_ping", _cachedPromptText); } private static void PulsePointing(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player.playerBodyAnimator == (Object)null)) { if (!_localPointStow.IsActive) { _localPointStow = HeldItemStowService.Begin(player, "foreman-ping-point", 4f, disableItemActions: false, force: true); } _localPointUntil = Time.time + 1f; _pointingLayerActive = true; _localPointWeight = 1f; Animator playerBodyAnimator = player.playerBodyAnimator; playerBodyAnimator.SetInteger("emoteNumber", 2); ApplyPointingLayer(player, playerBodyAnimator, _localPointWeight); BroadcastPointing(player, 1f); } } private static void UpdateLocalPointingLayer(PlayerControllerB player, bool advanceWeight) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerBodyAnimator == (Object)null) { return; } Animator playerBodyAnimator = player.playerBodyAnimator; bool flag = Time.time < _localPointUntil; if (flag) { playerBodyAnimator.SetInteger("emoteNumber", 2); _pointingLayerActive = true; } if (_pointingLayerActive || !(_localPointWeight <= 0f)) { if (advanceWeight) { _localPointWeight = (flag ? 1f : MovePointWeight(_localPointWeight, 0f)); } ApplyPointingLayer(player, playerBodyAnimator, _localPointWeight); if (advanceWeight && !flag && _localPointWeight <= 0.001f) { _localPointWeight = 0f; _pointingLayerActive = false; playerBodyAnimator.SetInteger("emoteNumber", 0); ApplyPointingLayer(player, playerBodyAnimator, 0f); _localPointStow.Dispose(); _localPointStow = default(HeldItemStowHandle); } } } private static void StartRemotePointing(int playerId, float duration) { if (playerId >= 0) { RemotePointStates.TryGetValue(playerId, out var value); value.Until = Time.time + Mathf.Clamp(duration, 0.1f, 1.25f); if (value.Weight < 1f) { value.Weight = 1f; } if (!value.Stow.IsActive) { value.Stow = HeldItemStowService.Begin(ResolvePlayerById(playerId), "foreman-ping-point", 4f, disableItemActions: false, force: true); } RemotePointStates[playerId] = value; } } private static void UpdateRemotePointingLayer(PlayerControllerB player, bool advanceWeight) { if ((Object)(object)player == (Object)null || (Object)(object)player.playerBodyAnimator == (Object)null) { return; } int key = (int)player.playerClientId; if (RemotePointStates.TryGetValue(key, out var value)) { Animator playerBodyAnimator = player.playerBodyAnimator; bool flag = Time.time < value.Until; if (flag) { playerBodyAnimator.SetInteger("emoteNumber", 2); } if (advanceWeight) { value.Weight = (flag ? 1f : MovePointWeight(value.Weight, 0f)); } ApplyPointingLayer(player, playerBodyAnimator, value.Weight); if (advanceWeight && !flag && value.Weight <= 0.001f) { playerBodyAnimator.SetInteger("emoteNumber", 0); ApplyPointingLayer(player, playerBodyAnimator, 0f); value.Stow.Dispose(); RemotePointStates.Remove(key); } else { RemotePointStates[key] = value; } } } private static PlayerControllerB ResolvePlayerById(int playerId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null || playerId < 0 || playerId >= array.Length) { return null; } return array[playerId]; } private static float MovePointWeight(float current, float target) { float num = Time.deltaTime / 0.08f; return Mathf.MoveTowards(current, target, Mathf.Clamp01(num)); } private static void ApplyPointingLayer(PlayerControllerB player, Animator animator, float weight) { if (!((Object)(object)player == (Object)null) && !((Object)(object)animator == (Object)null)) { weight = Mathf.Clamp01(weight); player.emoteLayerWeight = weight; SetLayerWeight(animator, "EmotesNoArms", weight); } } private static void SetLayerWeight(Animator animator, string layerName, float weight) { if (!((Object)(object)animator == (Object)null) && !string.IsNullOrWhiteSpace(layerName)) { int layerIndex = animator.GetLayerIndex(layerName); if (layerIndex >= 0) { animator.SetLayerWeight(layerIndex, weight); } } } private static UpgradeOutlineChannel OutlineChannelFor(MarkKind kind) { switch (kind) { case MarkKind.Enemy: case MarkKind.Trap: return UpgradeOutlineChannel.Danger; case MarkKind.Player: return UpgradeOutlineChannel.Friendly; default: return UpgradeOutlineChannel.Utility; } } private static Vector3 ResolveEnemyCenter(EnemyAI enemy) { //IL_0009: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return Vector3.zero; } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position; } Renderer val = null; if (enemy.skinnedMeshRenderers != null) { for (int i = 0; i < enemy.skinnedMeshRenderers.Length; i++) { if (!((Object)(object)enemy.skinnedMeshRenderers[i] == (Object)null)) { val = (Renderer)(object)enemy.skinnedMeshRenderers[i]; break; } } } if ((Object)(object)val == (Object)null && enemy.meshRenderers != null) { for (int j = 0; j < enemy.meshRenderers.Length; j++) { if (!((Object)(object)enemy.meshRenderers[j] == (Object)null)) { val = (Renderer)(object)enemy.meshRenderers[j]; break; } } } if (!((Object)(object)val != (Object)null)) { return ((Component)enemy).transform.position + Vector3.up * 1.2f; } Bounds bounds = val.bounds; return ((Bounds)(ref bounds)).center; } private static GameObject ResolveRenderableRoot(GameObject preferredRoot, GameObject fallbackRoot) { if (HasUsableRenderer(preferredRoot)) { return preferredRoot; } if (HasUsableRenderer(fallbackRoot)) { return fallbackRoot; } Transform val = (((Object)(object)preferredRoot != (Object)null) ? preferredRoot.transform.parent : null); while ((Object)(object)val != (Object)null) { if (HasUsableRenderer(((Component)val).gameObject)) { return ((Component)val).gameObject; } if ((Object)(object)((Component)val).GetComponent() != (Object)null) { return ((Component)val).gameObject; } val = val.parent; } if (!((Object)(object)preferredRoot != (Object)null)) { return fallbackRoot; } return preferredRoot; } private static bool HasUsableRenderer(GameObject root) { if ((Object)(object)root == (Object)null) { return false; } Renderer[] componentsInChildren = root.GetComponentsInChildren(false); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !(val is ParticleSystemRenderer) && !(val is LineRenderer) && !(val is TrailRenderer)) { return true; } } return false; } private static Vector3 ResolveRendererCenter(GameObject root, Vector3 fallback) { //IL_0015: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return fallback; } Renderer[] componentsInChildren = root.GetComponentsInChildren(false); Bounds val = default(Bounds); bool flag = false; foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2.enabled && !(val2 is ParticleSystemRenderer) && !(val2 is LineRenderer) && !(val2 is TrailRenderer)) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { return fallback; } return ((Bounds)(ref val)).center; } private static Vector3 ResolvePlayerCenter(PlayerControllerB player) { //IL_0009: 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_005d: 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_006c: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } if ((Object)(object)player.playerGlobalHead != (Object)null) { return player.playerGlobalHead.position; } if ((Object)(object)player.thisPlayerBody != (Object)null) { return player.thisPlayerBody.position + Vector3.up * 1.4f; } return ((Component)player).transform.position + Vector3.up * 1.4f; } private static Vector3 ResolveEntranceCenter(EntranceTeleport entrance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_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) if ((Object)(object)entrance == (Object)null) { return Vector3.zero; } if ((Object)(object)entrance.entrancePoint != (Object)null) { return entrance.entrancePoint.position + Vector3.up * 1.2f; } return ((Component)entrance).transform.position + Vector3.up * 1.2f; } private static Vector3 ResolveBodyCenter(DeadBodyInfo body) { //IL_0009: 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_004b: 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_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)body == (Object)null) { return Vector3.zero; } if (body.bodyParts != null && body.bodyParts.Length > 5 && (Object)(object)body.bodyParts[5] != (Object)null) { return body.bodyParts[5].position; } return ((Component)body).transform.position + Vector3.up * 0.8f; } private static void RevivePlayerLocal(int playerId, Vector3 revivePosition) { //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_010c: 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) //IL_011c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)StartOfRound.Instance == (Object)null || playerId < 0 || playerId >= StartOfRound.Instance.allPlayerScripts.Length) { return; } PlayerControllerB val = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val == (Object)null || !val.isPlayerDead) { return; } val.isPlayerDead = false; val.isPlayerControlled = true; val.health = 100; val.criticallyInjured = false; val.hasBeenCriticallyInjured = false; val.bleedingHeavily = false; val.disableMoveInput = false; val.disableLookInput = false; val.disableInteract = false; val.inSpecialInteractAnimation = false; val.isClimbingLadder = false; val.isHoldingObject = false; val.currentlyHeldObjectServer = null; val.carryWeight = 1f; val.externalForceAutoFade = Vector3.zero; val.spectatedPlayerScript = null; val.overrideGameOverSpectatePivot = null; val.hasBegunSpectating = false; val.setPositionOfDeadPlayer = false; val.isInElevator = false; val.isInHangarShipRoom = false; if ((Object)(object)val.thisController != (Object)null) { ((Collider)val.thisController).enabled = true; } val.DisablePlayerModel(((Component)val).gameObject, true, true); val.Crouch(false); val.TeleportPlayer(revivePosition + Vector3.up * 0.25f, false, 0f, false, true); if ((Object)(object)val.playerBodyAnimator != (Object)null) { val.playerBodyAnimator.SetBool("Limp", false); val.playerBodyAnimator.SetBool("crouching", false); } if ((Object)(object)val.mapRadarDotAnimator != (Object)null) { val.mapRadarDotAnimator.SetBool("dead", false); } DeadBodyInfo deadBody = val.deadBody; val.deadBody = null; if ((Object)(object)deadBody != (Object)null) { Object.Destroy((Object)(object)((Component)deadBody).gameObject); } StartOfRound.Instance.livingPlayers = Mathf.Min(StartOfRound.Instance.connectedPlayersAmount + 1, StartOfRound.Instance.livingPlayers + 1); StartOfRound.Instance.allPlayersDead = false; StartOfRound.Instance.SendChangedWeightEvent(); StartOfRound.Instance.UpdatePlayerVoiceEffects(); if (((NetworkBehaviour)val).IsOwner) { HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null) { instance.RemoveSpectateUI(); instance.gameOverAnimator.SetTrigger("revive"); instance.UpdateHealthUI(val.health, false); instance.SetCracksOnVisor(100f); } } else if ((Object)(object)GameNetworkManager.Instance?.localPlayerController != (Object)null && GameNetworkManager.Instance.localPlayerController.isPlayerDead) { HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.UpdateBoxesSpectateUI(); } } } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Expected O, but got Unknown //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Expected O, but got Unknown //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveMark; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveMark; <>O.<0>__OnReceiveMark = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("ForemanPing_Mark", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceiveReviveRequest; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveReviveRequest; <>O.<1>__OnReceiveReviveRequest = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("ForemanPing_InspireRequest", (HandleNamedMessageDelegate)obj2); CustomMessagingManager customMessagingManager3 = NetworkManager.Singleton.CustomMessagingManager; object obj3 = <>O.<2>__OnReceiveReviveResult; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnReceiveReviveResult; <>O.<2>__OnReceiveReviveResult = val3; obj3 = (object)val3; } customMessagingManager3.RegisterNamedMessageHandler("ForemanPing_InspireResult", (HandleNamedMessageDelegate)obj3); CustomMessagingManager customMessagingManager4 = NetworkManager.Singleton.CustomMessagingManager; object obj4 = <>O.<3>__OnReceiveRevive; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnReceiveRevive; <>O.<3>__OnReceiveRevive = val4; obj4 = (object)val4; } customMessagingManager4.RegisterNamedMessageHandler("ForemanPing_Revive", (HandleNamedMessageDelegate)obj4); CustomMessagingManager customMessagingManager5 = NetworkManager.Singleton.CustomMessagingManager; object obj5 = <>O.<4>__OnReceivePointing; if (obj5 == null) { HandleNamedMessageDelegate val5 = OnReceivePointing; <>O.<4>__OnReceivePointing = val5; obj5 = (object)val5; } customMessagingManager5.RegisterNamedMessageHandler("ForemanPing_Point", (HandleNamedMessageDelegate)obj5); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanPingPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void RequestRevive(int playerId) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) RegisterNetworkHandlers(); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null) { return; } if (singleton.IsServer) { HandleReviveRequestOnServer(singleton.LocalClientId, playerId); } else if (singleton.IsClient) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("ForemanPing_InspireRequest", 0uL, val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } } private static void BroadcastPointing(PlayerControllerB player, float duration) { RegisterNetworkHandlers(); if ((Object)(object)player == (Object)null) { return; } NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { int playerId = (int)player.playerClientId; if (singleton.IsServer) { SendPointMessage(playerId, duration, null); } else { SendPointMessage(playerId, duration, 0uL); } } } private static void SendPointMessage(int playerId, float duration, ulong? clientId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref duration, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("ForemanPing_Point", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("ForemanPing_Point", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceivePointing(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float duration = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref duration, default(ForPrimitives)); PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val != (Object)null) || (int)val.playerClientId != num) { StartRemotePointing(num, duration); } if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && senderClientId != NetworkManager.Singleton.LocalClientId) { SendPointMessage(num, duration, null); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("ForemanPingPatch: malformed point sync: " + ex.Message)); } } } private static void BroadcastMark(PingTarget target, int pingTier) { RegisterNetworkHandlers(); NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendMarkMessageToAll(target, pingTier); } else { SendMarkMessage(target, pingTier, 0uL); } } } private static void SendMarkMessageToAll(PingTarget target, int pingTier) { if (!((Object)(object)NetworkManager.Singleton == (Object)null) && NetworkManager.Singleton.CustomMessagingManager != null) { SendMarkMessage(target, pingTier, null); } } private static void SendMarkMessage(PingTarget target, int pingTier, ulong? clientId) { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1); try { int kind = (int)target.Kind; ((FastBufferWriter)(ref val)).WriteValueSafe(ref kind, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref target.NetworkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref target.PlayerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref target.Position.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref target.Position.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref target.Position.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pingTier, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("ForemanPing_Mark", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("ForemanPing_Mark", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveMark(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: 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_0087: 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_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { int kind = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref kind, default(ForPrimitives)); ulong netId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref netId, default(ForPrimitives)); int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); int pingTier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref pingTier, default(ForPrimitives)); PingTarget target = ResolveNetworkTarget((MarkKind)kind, netId, playerId, new Vector3(num, num2, num3)); ApplyMark(target, pingTier, fromNetwork: true); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && senderClientId != NetworkManager.Singleton.LocalClientId) { BroadcastMark(target, pingTier); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanPingPatch: malformed mark sync: " + ex.Message)); } } } private static PingTarget ResolveNetworkTarget(MarkKind kind, ulong netId, int playerId, Vector3 position) { //IL_00c0: 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_008f: Unknown result type (might be due to invalid IL or missing references) GameObject val = null; if (kind == MarkKind.Player && (Object)(object)StartOfRound.Instance != (Object)null && playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length) { PlayerControllerB val2 = StartOfRound.Instance.allPlayerScripts[playerId]; if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).gameObject; } } if ((Object)(object)val == (Object)null && netId != 0L && (Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(netId, out var value) && (Object)(object)value != (Object)null) { val = ((Component)value).gameObject; } if ((Object)(object)val == (Object)null) { val = FindTargetNear(kind, position); } return new PingTarget { Kind = kind, Root = val, NetworkObjectId = netId, PlayerId = playerId, Position = position, Label = kind.ToString().ToLowerInvariant() }; } private static GameObject FindTargetNear(MarkKind kind, 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_0025: 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_003d: Unknown result type (might be due to invalid IL or missing references) if (position == Vector3.zero) { return null; } GameObject best = null; float bestSqr = 16f; switch (kind) { case MarkKind.Enemy: FindClosestEnemy(position, ref best, ref bestSqr); break; case MarkKind.Item: FindClosestComponent(position, ref best, ref bestSqr); break; case MarkKind.Entrance: FindClosestComponent(position, ref best, ref bestSqr); break; } return best; } private static void FindClosestEnemy(Vector3 position, ref GameObject best, ref float bestSqr) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) EnemyAI[] array = Object.FindObjectsOfType(); foreach (EnemyAI val in array) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { ConsiderClosest(((Component)val).gameObject, ResolveEnemyCenter(val), position, ref best, ref bestSqr); } } } private static void FindClosestComponent(Vector3 position, ref GameObject best, ref float bestSqr) where T : Component { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) T[] array = Object.FindObjectsOfType(); foreach (T val in array) { if (!((Object)(object)val == (Object)null)) { GameObject root = ResolveRenderableRoot(((Component)val).gameObject, ((Component)val).gameObject); ConsiderClosest(root, ResolveRendererCenter(root, ((Component)val).transform.position), position, ref best, ref bestSqr); } } } private static void ConsiderClosest(GameObject root, Vector3 center, Vector3 position, ref GameObject best, ref float bestSqr) { //IL_000a: 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_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) if (!((Object)(object)root == (Object)null)) { Vector3 val = center - position; float sqrMagnitude = ((Vector3)(ref val)).sqrMagnitude; if (!(sqrMagnitude >= bestSqr)) { best = root; bestSqr = sqrMagnitude; } } } private static string DescribeCollider(Collider collider) { if ((Object)(object)collider == (Object)null) { return "null"; } return ((Object)((Component)collider).gameObject).name + "/" + ((object)collider).GetType().Name; } private static void OnReceiveReviveRequest(ulong senderClientId, FastBufferReader reader) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); HandleReviveRequestOnServer(senderClientId, playerId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanPingPatch: malformed revive request: " + ex.Message)); } } } private static void HandleReviveRequestOnServer(ulong requesterClientId, int playerId) { //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_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_0111: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } if (InspireUsedThisRoundByClient.Contains(requesterClientId)) { SendReviveResult(requesterClientId, InspireResult.AlreadyUsed); return; } PlayerControllerB val = FindPlayerByClientId(requesterClientId); if ((Object)(object)val == (Object)null || val.isPlayerDead || !val.isPlayerControlled) { SendReviveResult(requesterClientId, InspireResult.InvalidTarget); return; } PlayerControllerB val2 = null; if ((Object)(object)StartOfRound.Instance != (Object)null && playerId >= 0 && playerId < StartOfRound.Instance.allPlayerScripts.Length) { val2 = StartOfRound.Instance.allPlayerScripts[playerId]; } DeadBodyInfo val3 = (((Object)(object)val2 != (Object)null) ? val2.deadBody : null); if ((Object)(object)val2 == (Object)null || !val2.isPlayerDead || (Object)(object)val3 == (Object)null || (Object)(object)val3.playerScript != (Object)(object)val2) { SendReviveResult(requesterClientId, InspireResult.InvalidTarget); return; } Vector3 val4 = ResolveBodyCenter(val3); if (Vector3.Distance(((Component)val).transform.position, val4) > 7f) { SendReviveResult(requesterClientId, InspireResult.OutOfRange); return; } if (Random.value > 0.5f) { SendReviveResult(requesterClientId, InspireResult.NoResponse); return; } InspireUsedThisRoundByClient.Add(requesterClientId); RevivePlayerLocal(playerId, val4); BroadcastRevive(playerId, val4); SendReviveResult(requesterClientId, InspireResult.Success); } private static PlayerControllerB FindPlayerByClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.actualClientId == clientId) { return val; } } return null; } private static void SendReviveResult(ulong requesterClientId, InspireResult result) { //IL_004a: 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_0062: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null) { return; } if (singleton.IsClient && requesterClientId == singleton.LocalClientId) { ShowReviveResult(result); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); try { byte b = (byte)result; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("ForemanPing_InspireResult", requesterClientId, val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveReviveResult(ulong senderClientId, FastBufferReader reader) { //IL_000b: 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) if (senderClientId != 0L) { return; } try { byte result = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref result, default(ForPrimitives)); ShowReviveResult((InspireResult)result); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanPingPatch: malformed revive result: " + ex.Message)); } } } private static void ShowReviveResult(InspireResult result) { switch (result) { case InspireResult.Success: _nextInspireTime = Time.time + 75f; break; case InspireResult.NoResponse: { HUDManager instance3 = HUDManager.Instance; if (instance3 != null) { instance3.DisplayTip("INSPIRE", "No response...", true, false, "LC_Tip1"); } break; } case InspireResult.AlreadyUsed: { HUDManager instance4 = HUDManager.Instance; if (instance4 != null) { instance4.DisplayTip("INSPIRE", "Already used this round.", true, false, "LC_Tip1"); } break; } case InspireResult.OutOfRange: { HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("INSPIRE", "Move closer to the body.", true, false, "LC_Tip1"); } break; } case InspireResult.InvalidTarget: { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("INSPIRE", "Target is no longer available.", true, false, "LC_Tip1"); } break; } } } private static void BroadcastRevive(int playerId, Vector3 revivePosition) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0048: 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_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_0076: 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_008d: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref revivePosition.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref revivePosition.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref revivePosition.z, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessageToAll("ForemanPing_Revive", val, (NetworkDelivery)3); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveRevive(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L) { return; } try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); RevivePlayerLocal(playerId, new Vector3(num, num2, num3)); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanPingPatch: malformed revive sync: " + ex.Message)); } } } } [HarmonyPatch] internal static class ForemanSupportPatch { private sealed class SupportState { internal int BuddyTier; internal int RallyTier; internal float RallyExpiresAt; internal float ExpiresAt; internal Vector3 Position; } private sealed class AppliedSupportBonus { internal float MovementSpeedBonus; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveSupportState; } private const string MSG_SUPPORT_STATE = "ForemanSupport_State"; private const float STATE_BROADCAST_INTERVAL = 0.75f; private const float STATE_EXPIRY_SECONDS = 2.5f; private const string RALLY_HUD_KEY = "rally_call"; private const int RALLY_HUD_STACK_POSITION = 4; private static readonly Dictionary SupportStates = new Dictionary(); private static readonly Dictionary AppliedBonuses = new Dictionary(); private static bool _handlersRegistered; private static float _nextStateBroadcastTime; private static float _localRallyExpiresAt; private static float _localRallyCooldownEnd; private const int SUPPORT_STATE_BYTES = 28; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; SupportStates.Clear(); AppliedBonuses.Clear(); } internal static void OnRoundStarted() { SupportStates.Clear(); AppliedBonuses.Clear(); _nextStateBroadcastTime = 0f; _localRallyExpiresAt = 0f; _localRallyCooldownEnd = 0f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { SupportStates.Clear(); AppliedBonuses.Clear(); UpgradeHUDManager.DestroyHUDElement("rally_call"); ForemanAuraStatusHud.Destroy(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { RegisterNetworkHandlers(); PollRallyKey(__instance); UpdateRallyHUD(__instance); BroadcastLocalStateIfNeeded(__instance, force: false); } } private static void UpdateRallyHUD(PlayerControllerB player) { if (!RallyCallUpgrade.IsUnlocked()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement("rally_call"); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } if ((Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat || player.inTerminalMenu || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement("rally_call"); if ((Object)(object)hUDElement2 != (Object)null) { hUDElement2.SetActive(false); } return; } EnsureRallyHUD(); GameObject hUDElement3 = UpgradeHUDManager.GetHUDElement("rally_call"); if (!((Object)(object)hUDElement3 == (Object)null)) { hUDElement3.SetActive(true); UpgradeHUDManager.SetHUDElementLabel("rally_call", "RALLY [" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.RallyCall, "R") + "]"); if (Time.time < _localRallyCooldownEnd) { float num = 68f; UpgradeHUDManager.SetCooldownActive("rally_call", active: true); UpgradeHUDManager.UpdateFillBar("rally_call", (_localRallyCooldownEnd - Time.time) / Mathf.Max(0.01f, num)); } else { UpgradeHUDManager.SetCooldownActive("rally_call", active: false); } } } private static void EnsureRallyHUD() { if (!((Object)(object)UpgradeHUDManager.GetHUDElement("rally_call") != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { UpgradeHUDManager.CreateIconKeyHUDElement("rally_call", "rally_call", "RALLY [" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.RallyCall, "R") + "]", 4, ((Component)canvas).transform); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { ApplySpeedBuff(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] private static void DamagePlayerPrefix(PlayerControllerB __instance, ref int damageNumber) { if (IsLocalPlayer(__instance) && damageNumber > 0) { float num = Mathf.Max(new float[3] { GetSupportDamageReduction(__instance), ForemanPingPatch.GetMarkedTeammateDamageReduction(__instance), ForemanPingPatch.GetRecentMarkedEnemyDamageReduction() }); if (!(num <= 0f)) { damageNumber = Mathf.Max(0, Mathf.RoundToInt((float)damageNumber * (1f - Mathf.Clamp01(num)))); } } } private static void PollRallyKey(PlayerControllerB player) { if (RallyCallUpgrade.IsUnlocked() && UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.RallyCall)) { TryActivateRally(player); } } private static void TryActivateRally(PlayerControllerB player) { if (!RallyCallUpgrade.IsUnlocked() || !CanUseActiveAbility(player)) { return; } if (Time.time < _localRallyCooldownEnd) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("RALLY CALL", $"Cooldown: {_localRallyCooldownEnd - Time.time:F0}s", true, false, "LC_Tip1"); } return; } int tier = RallyCallUpgrade.GetTier(); _localRallyExpiresAt = Time.time + 8f; _localRallyCooldownEnd = _localRallyExpiresAt + 60f; UpdateLocalSupportState(player); BroadcastLocalStateIfNeeded(player, force: true); BreakGhostGirlHaunting(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Rally Call] Activated tier {tier}."); } } private static bool CanUseActiveAbility(PlayerControllerB player) { if ((Object)(object)player != (Object)null && !player.isPlayerDead && !player.isTypingChat && !player.inTerminalMenu && !player.inSpecialInteractAnimation) { if (!((Object)(object)player.quickMenuManager == (Object)null)) { return !player.quickMenuManager.isMenuOpen; } return true; } return false; } private static void BroadcastLocalStateIfNeeded(PlayerControllerB player, bool force) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } UpdateLocalSupportState(player); if (force || !(Time.time < _nextStateBroadcastTime)) { int localBuddyTier = GetLocalBuddyTier(player); int num = ((Time.time < _localRallyExpiresAt) ? RallyCallUpgrade.GetTier() : 0); if (localBuddyTier > 0 || num > 0) { _nextStateBroadcastTime = Time.time + 0.75f; BroadcastSupportState((int)player.playerClientId, localBuddyTier, num, _localRallyExpiresAt, ((Component)player).transform.position); } } } private static void UpdateLocalSupportState(PlayerControllerB player) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { SupportState state = GetState((int)player.playerClientId); state.BuddyTier = GetLocalBuddyTier(player); state.RallyTier = ((Time.time < _localRallyExpiresAt) ? RallyCallUpgrade.GetTier() : 0); state.RallyExpiresAt = _localRallyExpiresAt; state.ExpiresAt = Time.time + 2.5f; state.Position = ((Component)player).transform.position; } } private static int GetLocalBuddyTier(PlayerControllerB player) { if (!CanSupplyBuddyAura(player)) { return 0; } return BuddySystemUpgrade.GetTier(); } private static bool CanSupplyBuddyAura(PlayerControllerB player) { if ((Object)(object)player != (Object)null && player.isPlayerControlled) { return !player.isPlayerDead; } return false; } private static float GetSupportSpeedBonus(PlayerControllerB localPlayer) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = 0f; int num3 = (int)localPlayer.playerClientId; foreach (KeyValuePair supportState in SupportStates) { SupportState value = supportState.Value; if (IsStateFresh(value)) { Vector3 val = ResolveProviderPosition(supportState.Key, value); float num4 = Vector3.Distance(((Component)localPlayer).transform.position, val); if (supportState.Key != num3 && value.BuddyTier > 0 && CanUseProviderStateForBuddy(supportState.Key) && num4 <= BuddySystemUpgrade.GetRange(value.BuddyTier)) { num = Mathf.Max(num, BuddySystemUpgrade.GetBuff(value.BuddyTier)); } if (value.RallyTier > 0 && Time.time < value.RallyExpiresAt && num4 <= 20f) { num2 = Mathf.Max(num2, RallyCallUpgrade.GetSpeedBonus(value.RallyTier)); } } } return num + num2; } private static float GetSupportDamageReduction(PlayerControllerB localPlayer) { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) float num = 0f; float num2 = 0f; int num3 = (int)localPlayer.playerClientId; foreach (KeyValuePair supportState in SupportStates) { SupportState value = supportState.Value; if (IsStateFresh(value)) { Vector3 val = ResolveProviderPosition(supportState.Key, value); float num4 = Vector3.Distance(((Component)localPlayer).transform.position, val); if (supportState.Key != num3 && value.BuddyTier > 0 && CanUseProviderStateForBuddy(supportState.Key) && num4 <= BuddySystemUpgrade.GetRange(value.BuddyTier)) { num = Mathf.Max(num, BuddySystemUpgrade.GetBuff(value.BuddyTier)); } if (value.RallyTier > 0 && Time.time < value.RallyExpiresAt && num4 <= 20f) { num2 = Mathf.Max(num2, RallyCallUpgrade.GetDamageReduction(value.RallyTier)); } } } return Mathf.Clamp01(num + num2); } private static void ApplySpeedBuff(PlayerControllerB player) { AppliedSupportBonus appliedBonus = GetAppliedBonus(player); float num = player.movementSpeed - appliedBonus.MovementSpeedBonus; float supportSpeedBonus = GetSupportSpeedBonus(player); float num2 = Mathf.Max(0f, num) * supportSpeedBonus; player.movementSpeed = Mathf.Max(0.1f, num + num2); appliedBonus.MovementSpeedBonus = num2; ForemanAuraStatusHud.SetAuraActive(IsReceivingBuddyAura(player)); } private static bool IsReceivingBuddyAura(PlayerControllerB localPlayer) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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) if ((Object)(object)localPlayer == (Object)null || localPlayer.isPlayerDead) { return false; } int num = (int)localPlayer.playerClientId; Vector3 position = ((Component)localPlayer).transform.position; foreach (KeyValuePair supportState in SupportStates) { if (supportState.Key == num) { continue; } SupportState value = supportState.Value; if (IsStateFresh(value) && value.BuddyTier > 0 && CanUseProviderStateForBuddy(supportState.Key)) { Vector3 val = ResolveProviderPosition(supportState.Key, value); if (Vector3.Distance(position, val) <= BuddySystemUpgrade.GetRange(value.BuddyTier)) { return true; } } } return false; } private static AppliedSupportBonus GetAppliedBonus(PlayerControllerB player) { int instanceID = ((Object)player).GetInstanceID(); if (!AppliedBonuses.TryGetValue(instanceID, out var value)) { value = new AppliedSupportBonus(); AppliedBonuses[instanceID] = value; } return value; } private static SupportState GetState(int playerId) { if (!SupportStates.TryGetValue(playerId, out var value)) { value = new SupportState(); SupportStates[playerId] = value; } return value; } private static bool IsStateFresh(SupportState state) { if (state != null) { return Time.time < state.ExpiresAt; } return false; } private static bool CanUseProviderStateForBuddy(int playerId) { if (!TryResolveProviderPlayer(playerId, out var player)) { return true; } if (player.isPlayerControlled) { return !player.isPlayerDead; } return false; } private static Vector3 ResolveProviderPosition(int playerId, SupportState state) { //IL_0017: 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) if (TryResolveProviderPlayer(playerId, out var player)) { return ((Component)player).transform.position; } return state.Position; } private static bool TryResolveProviderPlayer(int playerId, out PlayerControllerB player) { player = null; if ((Object)(object)StartOfRound.Instance == (Object)null || StartOfRound.Instance.allPlayerScripts == null || playerId < 0 || playerId >= StartOfRound.Instance.allPlayerScripts.Length) { return false; } player = StartOfRound.Instance.allPlayerScripts[playerId]; return (Object)(object)player != (Object)null; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void BreakGhostGirlHaunting() { DressGirlAI[] array = Object.FindObjectsOfType(); foreach (DressGirlAI val in array) { if ((Object)(object)val == (Object)null || ((EnemyAI)val).isEnemyDead || (Object)(object)val.hauntingPlayer == (Object)null) { continue; } try { val.staringInHaunt = false; val.disappearingFromStare = true; ((EnemyAI)val).moveTowardsDestination = false; ((EnemyAI)val).targetPlayer = null; ((EnemyAI)val).SwitchToBehaviourStateOnLocalClient(0); ((EnemyAI)val).EnableEnemyMesh(false, true, true); if ((Object)(object)((EnemyAI)val).creatureVoice != (Object)null) { ((EnemyAI)val).creatureVoice.Stop(); } if ((Object)(object)((EnemyAI)val).creatureSFX != (Object)null) { ((EnemyAI)val).creatureSFX.Stop(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Rally Call] Failed to break Ghost Girl haunting: " + ex.Message)); } } } } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveSupportState; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveSupportState; <>O.<0>__OnReceiveSupportState = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("ForemanSupport_State", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanSupportPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void WriteSupportState(FastBufferWriter writer, int playerId, int buddyTier, int rallyTier, float rallyExpiresAt, Vector3 position) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006a: 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_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref buddyTier, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref rallyTier, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref rallyExpiresAt, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.x, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.y, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.z, default(ForPrimitives)); } private static void BroadcastSupportState(int playerId, int buddyTier, int rallyTier, float rallyExpiresAt, Vector3 position) { //IL_002e: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(28, (Allocator)2, -1); try { WriteSupportState(val, playerId, buddyTier, rallyTier, rallyExpiresAt, position); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("ForemanSupport_State", val, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("ForemanSupport_State", 0uL, val, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanSupportPatch: support state send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RelaySupportState(ulong excludeClientId, int playerId, int buddyTier, int rallyTier, float rallyExpiresAt, Vector3 position) { //IL_0055: 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_006a: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref val2))..ctor(28, (Allocator)2, -1); try { WriteSupportState(val2, playerId, buddyTier, rallyTier, rallyExpiresAt, position); val.SendNamedMessage("ForemanSupport_State", connectedClientsId, val2, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"ForemanSupportPatch: support state relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref val2)).Dispose(); } } } private static PlayerControllerB ResolvePlayerByActualClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].actualClientId == clientId) { return array[i]; } } return null; } private static void OnReceiveSupportState(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_003f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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) try { int playerId = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); int buddyTier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref buddyTier, default(ForPrimitives)); int rallyTier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref rallyTier, default(ForPrimitives)); float rallyExpiresAt = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref rallyExpiresAt, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); NetworkManager singleton = NetworkManager.Singleton; bool flag = (Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId; if (flag) { PlayerControllerB val = ResolvePlayerByActualClientId(senderClientId); if ((Object)(object)val == (Object)null) { return; } playerId = (int)val.playerClientId; } SupportState state = GetState(playerId); state.BuddyTier = buddyTier; state.RallyTier = rallyTier; state.RallyExpiresAt = rallyExpiresAt; state.ExpiresAt = Time.time + 2.5f; state.Position = new Vector3(num, num2, num3); if (flag) { RelaySupportState(senderClientId, playerId, buddyTier, rallyTier, rallyExpiresAt, new Vector3(num, num2, num3)); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("ForemanSupportPatch: malformed support sync: " + ex.Message)); } } } } [HarmonyPatch] internal static class GlowInTheDarkPatch { private static GameObject _glowLight; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { if (!GlowInTheDarkUpgrade.IsUnlocked()) { DestroyGlow(); } else if (__instance.isPlayerDead) { DestroyGlow(); } else if (!__instance.isInsideFactory) { DestroyGlow(); } else { EnsureGlow(__instance); } } } private static void EnsureGlow(PlayerControllerB player) { //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_glowLight != (Object)null) { Light component = _glowLight.GetComponent(); if ((Object)(object)component != (Object)null) { component.range = GlowInTheDarkUpgrade.GetRange(); component.intensity = GlowInTheDarkUpgrade.GetIntensity(); } return; } try { _glowLight = new GameObject("Y4NGZ_GlowInTheDark"); _glowLight.transform.SetParent(((Component)player).transform, false); _glowLight.transform.localPosition = new Vector3(0f, 1.5f, 0f); Light obj = _glowLight.AddComponent(); obj.type = (LightType)2; obj.range = GlowInTheDarkUpgrade.GetRange(); obj.intensity = GlowInTheDarkUpgrade.GetIntensity(); obj.color = new Color(0.8f, 0.9f, 1f); obj.shadows = (LightShadows)0; obj.bounceIntensity = 0f; Plugin.Log.LogInfo((object)"[Y4NGZUpgrades] Glow in the Dark light attached to local player."); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Y4NGZUpgrades] Failed to create Glow in the Dark light: {arg}"); if ((Object)(object)_glowLight != (Object)null) { Object.Destroy((Object)(object)_glowLight); _glowLight = null; } } } private static void DestroyGlow() { if (!((Object)(object)_glowLight == (Object)null)) { Object.Destroy((Object)(object)_glowLight); _glowLight = null; } } internal static void OnRoundStarted() { DestroyGlow(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { DestroyGlow(); } } [HarmonyPatch(typeof(Landmine))] internal static class LandminePatch { [HarmonyPrefix] [HarmonyPatch("TriggerMineOnLocalClientByExiting")] private static bool PreventMineExplosion() { try { if (LightFeetUpgrade.HasTier(1)) { Plugin.Log.LogDebug((object)"Light Feet T1: Prevented landmine explosion for local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"LandminePatch.PreventMineExplosion failed: {arg}"); } return true; } } [HarmonyPatch] internal static class LastWillPatch { private class BeaconPulse : MonoBehaviour { private Light _light; private float _min; private float _max; private float _period; private float _startTime; public void Init(Light light, float min, float max, float period) { _light = light; _min = min; _max = max; _period = Mathf.Max(0.05f, period); _startTime = Time.time; } private void Update() { if (!((Object)(object)_light == (Object)null)) { float num = (Time.time - _startTime) / _period; float num2 = 0.5f + 0.5f * Mathf.Sin(num * 2f * MathF.PI); _light.intensity = Mathf.Lerp(_min, _max, num2); } } } private class HudMarkerDriver : MonoBehaviour { private Vector3 _worldPos; private string _glyph; private GUIStyle _style; public void Init(Vector3 worldPos, string glyph) { //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) _worldPos = worldPos; _glyph = glyph; } private void OnGUI() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) if (_style == null) { _style = new GUIStyle(GUI.skin.label); _style.fontSize = 22; _style.fontStyle = (FontStyle)1; _style.alignment = (TextAnchor)4; _style.normal.textColor = new Color(1f, 0.25f, 0.25f, 0.9f); } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; Camera val2 = (((Object)(object)val != (Object)null && (Object)(object)val.gameplayCamera != (Object)null) ? val.gameplayCamera : Camera.main); if (!((Object)(object)val2 == (Object)null)) { Vector3 val3 = val2.WorldToScreenPoint(_worldPos); if (!(val3.z <= 0f)) { float num = val3.x - 16f; float num2 = (float)Screen.height - val3.y - 16f; GUI.Label(new Rect(num, num2, 32f, 32f), _glyph, _style); } } } } private class TrailDriver : MonoBehaviour { private Vector3 _start; private Vector3 _end; private LineRenderer _line; private float _nextRepathAt; private bool _repathed; public void Init(Vector3 start, Vector3 end) { //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_0008: 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) _start = start; _end = end; BuildLine(); Repath(); _nextRepathAt = Time.time + 30f; } private void BuildLine() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Expected O, but got Unknown //IL_0089: 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) GameObject val = new GameObject("Y4NGZ_LastWill_Trail"); val.transform.SetParent(((Component)this).transform, false); _line = val.AddComponent(); _line.startWidth = 0.18f; _line.endWidth = 0.18f; _line.useWorldSpace = true; ((Renderer)_line).material = new Material(Shader.Find("Sprites/Default")); _line.startColor = new Color(0.3f, 0.5f, 1f, 0.9f); _line.endColor = new Color(0.3f, 0.5f, 1f, 0.4f); _line.numCornerVertices = 2; } private void Update() { if (!_repathed && !(Time.time < _nextRepathAt)) { Repath(); _repathed = true; } } private void Repath() { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Expected O, but got Unknown //IL_0016: 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_004f: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_line == (Object)null) { return; } NavMeshPath val = new NavMeshPath(); NavMeshHit val2 = default(NavMeshHit); if (!NavMesh.SamplePosition(_start, ref val2, 5f, -1)) { Fallback(); return; } NavMeshHit val3 = default(NavMeshHit); if (!NavMesh.SamplePosition(_end, ref val3, 5f, -1)) { Fallback(); return; } if (!NavMesh.CalculatePath(((NavMeshHit)(ref val2)).position, ((NavMeshHit)(ref val3)).position, -1, val) || (int)val.status != 0) { Fallback(); return; } Vector3[] corners = val.corners; _line.positionCount = corners.Length; for (int i = 0; i < corners.Length; i++) { _line.SetPosition(i, corners[i] + Vector3.up * 0.1f); } } private void Fallback() { //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) //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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //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) _line.positionCount = 2; _line.SetPosition(0, _start + Vector3.up * 0.1f); _line.SetPosition(1, _end + Vector3.up * 0.1f); } } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveBeacon; } private const string MSG_LAST_WILL_BEACON = "Y4NGZ_LastWill_Beacon"; private static GameObject _activeBeacon; private static bool _handlersRegistered; private const float BEACON_PULSE_PERIOD = 1.4f; private const float BEACON_INTENSITY_MIN = 2f; private const float BEACON_INTENSITY_MAX = 9f; private const float BEACON_RANGE = 14f; private const float TRAIL_REFRESH_AFTER = 30f; private const float TRAIL_WIDTH = 0.18f; private const int BEACON_PAYLOAD_BYTES = 16; [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { //IL_0054: 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) try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && SalvagerUpgrade.HasTier(2) && !__instance.isInHangarShipRoom && __instance.isInsideFactory) { Vector3 position = ((Component)__instance).transform.position; int tier = SalvagerUpgrade.GetTier(); SpawnBeacon(position, tier); BroadcastBeacon(position, tier); } } catch (Exception arg) { Plugin.Log.LogError((object)$"LastWillPatch.PostKillPlayer failed: {arg}"); } } private static void SpawnBeacon(Vector3 pos, int tier) { //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_0027: 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_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_0041: 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_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_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Expected O, but got Unknown //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_00c1: 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) //IL_00d9: 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) if ((Object)(object)_activeBeacon != (Object)null) { Object.Destroy((Object)(object)_activeBeacon); } GameObject val = new GameObject("Y4NGZ_LastWill_Beacon"); val.transform.position = pos + Vector3.up * 0.4f; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.2f, 0.2f); val2.intensity = 2f; val2.range = 14f; val2.shadows = (LightShadows)0; val.AddComponent().Init(val2, 2f, 9f, 1.4f); val.AddComponent().Init(pos, "X"); _activeBeacon = val; if (tier >= 3) { Vector3 val3 = ResolveEntrancePosition(pos); if (val3 != Vector3.zero) { _activeBeacon.AddComponent().Init(val3, pos); } } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveBeacon; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveBeacon; <>O.<0>__OnReceiveBeacon = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZ_LastWill_Beacon", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("LastWillPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void BroadcastBeacon(Vector3 pos, int tier) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref pos.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("Y4NGZ_LastWill_Beacon", val, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("Y4NGZ_LastWill_Beacon", 0uL, val, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("LastWillPatch: beacon send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RelayBeacon(ulong excludeClientId, Vector3 pos, int tier) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: 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) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref val2))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref pos.x, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref pos.y, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref pos.z, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref tier, default(ForPrimitives)); val.SendNamedMessage("Y4NGZ_LastWill_Beacon", connectedClientsId, val2, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"LastWillPatch: beacon relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref val2)).Dispose(); } } } private static void OnReceiveBeacon(ulong senderClientId, FastBufferReader reader) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004f: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) try { NetworkManager singleton = NetworkManager.Singleton; ulong num = (((Object)(object)singleton != (Object)null) ? singleton.LocalClientId : ulong.MaxValue); if (senderClientId != num) { float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); float num4 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); int tier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref tier, default(ForPrimitives)); if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { RelayBeacon(senderClientId, new Vector3(num2, num3, num4), tier); } SpawnBeacon(new Vector3(num2, num3, num4), tier); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("LastWillPatch: malformed beacon sync: " + ex.Message)); } } } private static Vector3 ResolveEntrancePosition(Vector3 deathPos) { //IL_000d: 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_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) EntranceTeleport[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return Vector3.zero; } EntranceTeleport val = null; float num = float.MaxValue; foreach (EntranceTeleport val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.isEntranceToBuilding) { float num2 = Vector3.Distance(((Object)(object)val2.entrancePoint != (Object)null) ? val2.entrancePoint.position : ((Component)val2).transform.position, deathPos); if (num2 < num) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null) { return Vector3.zero; } if (!((Object)(object)val.entrancePoint != (Object)null)) { return ((Component)val).transform.position; } return val.entrancePoint.position; } } [HarmonyPatch] internal static class LedgeMantlePatch { private sealed class RemoteMantlePresentation { private const float GrabEaseFraction = 0.18f; private bool _bodyArmBonesResolved; private string _lastBodyGrabGate; internal PlayerControllerB Player { get; } internal float StartedAt { get; } internal float Duration { get; } internal Vector3 LedgeGripCenter { get; } internal Vector3 WallNormal { get; } internal Transform BodyArmUpperL { get; private set; } internal Transform BodyArmLowerL { get; private set; } internal Transform BodyHandL { get; private set; } internal Transform BodyArmUpperR { get; private set; } internal Transform BodyArmLowerR { get; private set; } internal Transform BodyHandR { get; private set; } internal bool HasBodyArmBones { get { if ((Object)(object)BodyArmUpperL != (Object)null && (Object)(object)BodyArmLowerL != (Object)null && (Object)(object)BodyHandL != (Object)null && (Object)(object)BodyArmUpperR != (Object)null && (Object)(object)BodyArmLowerR != (Object)null) { return (Object)(object)BodyHandR != (Object)null; } return false; } } internal RemoteMantlePresentation(PlayerControllerB player, float duration, Vector3 ledgeGripCenter, Vector3 wallNormal) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: 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) Player = player; StartedAt = Time.time; Duration = Mathf.Max(0.001f, duration); LedgeGripCenter = ledgeGripCenter; WallNormal = wallNormal; } internal float CalculateGrabEnvelope() { float num = Mathf.Clamp(Time.time - StartedAt, 0f, Duration); float num2 = Mathf.Max(0f, Duration - num); float num3 = Mathf.Max(0.001f, Duration * 0.18f); float num4 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(num / num3)); float num5 = Mathf.SmoothStep(0f, 1f, Mathf.Clamp01(num2 / num3)); return Mathf.Min(num4, num5); } internal void LogBodyGrabGate(string result, float weight) { if (!string.Equals(_lastBodyGrabGate, result, StringComparison.Ordinal)) { _lastBodyGrabGate = result; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-mantle] body_grab_gate: playerClientId=" + (Player?.playerClientId.ToString() ?? "") + " " + $"result='{result}' weight={weight:0.######}.")); } } } internal void ResolveBodyArmBones() { if (_bodyArmBonesResolved) { return; } _bodyArmBonesResolved = true; if ((Object)(object)Player == (Object)null) { return; } Transform val = null; Transform[] componentsInChildren = ((Component)Player).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (string.Equals(((Object)val2).name, "metarig", StringComparison.Ordinal) && (Object)(object)val2.parent != (Object)null && string.Equals(((Object)val2.parent).name, "ScavengerModel", StringComparison.Ordinal)) { val = val2; break; } } if (!((Object)(object)val == (Object)null)) { BodyArmUpperL = FindDeep(val, "arm.L_upper"); BodyArmLowerL = FindDeep(val, "arm.L_lower"); BodyHandL = FindDeep(val, "hand.L"); BodyArmUpperR = FindDeep(val, "arm.R_upper"); BodyArmLowerR = FindDeep(val, "arm.R_lower"); BodyHandR = FindDeep(val, "hand.R"); } } } private readonly struct MantleProbe { internal readonly Vector3 StartPosition; internal readonly Vector3 LiftPosition; internal readonly Vector3 EndPosition; internal readonly Vector3 WallNormal; internal readonly float LedgeHeight; internal readonly bool Tall; internal readonly Vector3 LedgeGripCenter; internal MantleProbe(Vector3 startPosition, Vector3 liftPosition, Vector3 endPosition, Vector3 wallNormal, float ledgeHeight, bool tall, Vector3 ledgeGripCenter) { //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_0008: 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_000f: 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_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) StartPosition = startPosition; LiftPosition = liftPosition; EndPosition = endPosition; WallNormal = wallNormal; LedgeHeight = ledgeHeight; Tall = tall; LedgeGripCenter = ledgeGripCenter; } } [CompilerGenerated] private static class <>O { public static Action <0>__OnMantleBeginCameraRendering; public static HandleNamedMessageDelegate <1>__OnReceiveMantleStart; public static HandleNamedMessageDelegate <2>__OnReceiveMantleStop; } private const string MSG_MANTLE_START = "Y4NGZ_MantleStart"; private const string MSG_MANTLE_STOP = "Y4NGZ_MantleStop"; private const int MANTLE_START_EXTENSION_BYTES = 28; private const float WALL_MAX_UP_DOT = 0.35f; private const float WALKABLE_MIN_UP_DOT = 0.7f; private const float WALL_TO_LEDGE_FORWARD_OFFSET = 0.15f; private const float DESTINATION_FORWARD_PADDING = 0.35f; private const float CAPSULE_SKIN = 0.05f; private const float LIFT_SEGMENT_FRACTION = 0.6f; private const float MANTLE_FINISH_T = 0.9f; private const float MANTLE_LIFT_CLEARANCE = 0.28f; private const float MANTLE_WALL_SCAN_START_HEIGHT = 0.45f; private const float MANTLE_WALL_SCAN_STEP = 0.3f; private const float MANTLE_LEDGE_SCAN_STEP = 0.25f; private const float MANTLE_INTERIOR_CEILING_CHECK_DISTANCE = 12f; private const float MANTLE_PATH_RADIUS_INSET = 0.08f; private static bool _handlersRegistered; private static float _nextRetryTime; private static float _cooldownEnd; private static readonly Dictionary RemoteMantles = new Dictionary(); private static bool _mantleActive; private static PlayerControllerB _mantlePlayer; private static Vector3 _mantleStartPosition; private static Vector3 _mantleLiftPosition; private static Vector3 _mantleEndPosition; private static Vector3 _mantleLastSafePosition; private static float _mantleStartedAt; private static float _mantleDuration; private static bool _mantleAnimStarted; private static bool _mantleInputSaved; private static bool _savedDisableMoveInput; private static float _nextMantleArmsDiagnosticAt; private static bool _mantleArmsHandBonesResolved; private static Transform _mantleArmsHandLeft; private static Transform _mantleArmsHandRight; private static Transform _mantleArmsSpine003; private static Transform _mantleArmsShoulderLeft; private static Transform _mantleArmsShoulderRight; private static Transform _mantleArmsTargetLeft; private static Transform _mantleArmsTargetRight; private static bool _mantleOccluderDumpDone; private static bool _mantleHideResolved; private static Renderer[] _mantleBodyLods = Array.Empty(); private static int[] _mantleBodyLodSavedLayers = Array.Empty(); private static int _mantleFpHiddenLayer = -1; private static Renderer[] _mantleHeadCosmetics = Array.Empty(); private static bool[] _mantleHeadCosmeticSavedEnabled = Array.Empty(); private static bool _mantleBodyForceHidden; private static bool _mantleFpArmRenderersResolved; private static Renderer[] _mantleFpArmRenderers = Array.Empty(); private static bool _mantleFpArmsHidden; private static bool _renderDiagSubscribed; private static int _renderDiagSnapshotFrame = -1; private static bool _renderDiagLogThisFrame; private static Vector3 _renderDiagCamPos; private static Quaternion _renderDiagCamRot; private static Vector3 _renderDiagHandLCam; private static Vector3 _renderDiagHandRCam; private static Vector3 _renderDiagArmsRootCam; private static Vector3 _renderDiagArmsRootWorld; private static Vector3 _renderDiagSpine003Cam; private static bool _patchOwnerDumpDone; private static Vector3 _mantleLedgeGripCenter; private static Vector3 _mantleWallNormal; private static bool _mantleBodyArmBonesResolved; private static Transform _bodyArmUpperL; private static Transform _bodyArmLowerL; private static Transform _bodyHandL; private static Transform _bodyArmUpperR; private static Transform _bodyArmLowerR; private static Transform _bodyHandR; private static bool _mantleFpArmBonesResolved; private static Transform _fpArmUpperL; private static Transform _fpArmLowerL; private static Transform _fpHandL; private static Transform _fpArmUpperR; private static Transform _fpArmLowerR; private static Transform _fpHandR; private static readonly List _mantleTempCulled = new List(); private static readonly HashSet _mantleOccluderLogged = new HashSet(); private const float MANTLE_OCCLUDER_CULL_RADIUS = 0.32f; private const float MANTLE_GRAB_HAND_SPREAD = 0.28f; private const float REMOTE_MANTLE_MAX_REACH_FRACTION = 0.92f; private const float MANTLE_FP_GRAB_DEPTH = 0.5f; private static bool _fallFieldsResolved; private static FieldInfo _fallValueField; private static FieldInfo _fallValueUncappedField; private static bool _externalForcesResolved; private static FieldInfo _externalForcesField; private static bool _vehicleMembersResolved; private static FieldInfo[] _vehicleBoolFields = Array.Empty(); private static PropertyInfo[] _vehicleBoolProperties = Array.Empty(); private static bool _debugThirdPersonResolved; private static FieldInfo _debugThirdPersonField; private static FieldInfo _debugStaticCamField; internal static bool IsMantleActive => _mantleActive; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } internal static void OnRoundStarted() { RegisterNetworkHandlers(); _nextRetryTime = 0f; _cooldownEnd = 0f; AbortMantle("start-game"); ClearRemoteMantlePresentations("start-game"); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { AbortMantle("end-of-game"); ClearRemoteMantlePresentations("end-of-game"); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { RegisterNetworkHandlers(); DumpMovementPatchOwnersOnce(__instance); if (_mantleActive) { UpdateMantle(__instance); } else { TryStartMantle(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] [HarmonyPriority(-100)] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return; } if (!IsLocalPlayer(__instance)) { ApplyRemoteMantleBodyGrabIK(__instance); } else if (_mantleActive && !((Object)(object)__instance != (Object)(object)_mantlePlayer)) { PanicSlidePatch.ReapplyFirstPersonMovementPresentation(__instance); float num = CalculateMantleCameraEnvelope(); PanicSlidePatch.ApplyFirstPersonMovementCamera(__instance, 0.25f * num, 0f); PanicSlidePatch.ApplyMovementLookLimit(__instance); if (IsDebugThirdPersonCamActive()) { RestoreLocalMantleBody(); SetMantleFirstPersonArmsHidden(__instance, hidden: true); RestoreMantleViewOccluders(); } else { HideLocalMantleBody(__instance); SetMantleFirstPersonArmsHidden(__instance, hidden: false); CullMantleViewOccluders(__instance); } ReanchorMantleFirstPersonArms(__instance); ApplyMantleBodyGrabIK(__instance, num); ApplyMantleFpArmGrabIK(__instance, num); LogMantleArmsDiagnostics(__instance); CaptureMantleRenderTruthSnapshot(__instance); LogMantleOccluderDumpOnce(__instance); } } private static void TryStartMantle(PlayerControllerB player) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (CanTryMantle(player, out var forward)) { if (!TryProbeMantle(player, forward, out var probe)) { _nextRetryTime = Time.time + 0.05f; } else { BeginMantle(player, probe); } } } private static bool CanTryMantle(PlayerControllerB player, out Vector3 forward) { //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_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) forward = Vector3.zero; if (Time.time < _cooldownEnd || Time.time < _nextRetryTime) { return false; } if (PanicSlideUpgrade.GetTier() < 2) { return false; } if ((Object)(object)player == (Object)null || (Object)(object)player.thisController == (Object)null || (Object)(object)((Component)player).transform == (Object)null) { return false; } if (player.isPlayerDead || player.inSpecialInteractAnimation || player.isClimbingLadder) { return false; } if (player.isTypingChat || player.inTerminalMenu) { return false; } if ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) { return false; } if (IsPlayerInVehicle(player)) { return false; } if ((player.isInElevator || player.isInHangarShipRoom) && (Object)(object)StartOfRound.Instance != (Object)null && !StartOfRound.Instance.shipHasLanded) { return false; } if (player.thisController.isGrounded) { return false; } if (PanicSlidePatch.IsSlideActive()) { return false; } forward = ResolveCameraForward(player); return ((Vector3)(ref forward)).sqrMagnitude > 0.01f; } private static bool TryProbeMantle(PlayerControllerB player, Vector3 forward, out MantleProbe probe) { //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0122: 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_013e: 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_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_019f: 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_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_01b6: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01de: 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_01ea: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_01f6: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: 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_0219: Unknown result type (might be due to invalid IL or missing references) //IL_021e: Unknown result type (might be due to invalid IL or missing references) //IL_0229: 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_0236: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_025e: Unknown result type (might be due to invalid IL or missing references) //IL_026a: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_0288: Unknown result type (might be due to invalid IL or missing references) //IL_028a: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) probe = default(MantleProbe); CharacterController thisController = player.thisController; if ((Object)(object)thisController == (Object)null || ((Vector3)(ref forward)).sqrMagnitude < 0.01f) { return false; } int mask = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); float num = Mathf.Max(0.1f, thisController.radius); float num2 = ResolveFeetY(player, thisController); float castRadius = Mathf.Clamp(num * 0.55f, 0.12f, 0.35f); if (!TryFindWallAnchor(player, forward, castRadius, num2, mask, out var wallHit, out var wallAnchor)) { return false; } if (!HasMantleIntent(player, forward, ((RaycastHit)(ref wallHit)).normal)) { return false; } if (!TryFindLedgeTop(wallAnchor, forward, wallHit, castRadius, num2, mask, out var topHit)) { return false; } if ((Object)(object)((RaycastHit)(ref topHit)).collider == (Object)null || Vector3.Dot(((RaycastHit)(ref topHit)).normal, Vector3.up) <= 0.7f) { return false; } if (IsRejectedMantleSurface(((RaycastHit)(ref topHit)).collider)) { return false; } float num3 = ((RaycastHit)(ref topHit)).point.y - num2; if (num3 < 0.95f || num3 > 3f) { return false; } Vector3 val = ((RaycastHit)(ref topHit)).point + forward * (num + 0.35f); val.y = ((RaycastHit)(ref topHit)).point.y + 0.05f; if (!HasDestinationClearance(thisController, val, mask)) { return false; } float num4 = ((Component)player).transform.position.y - num2; Vector3 normal = ((RaycastHit)(ref wallHit)).normal; Vector3 val2 = ((RaycastHit)(ref wallHit)).point + normal * (thisController.radius + 0.02f); val2.y = ((Component)player).transform.position.y; Vector3 val3 = val2; Vector3 val4 = default(Vector3); ((Vector3)(ref val4))..ctor(val.x, val.y + num4, val.z); Vector3 val5 = default(Vector3); ((Vector3)(ref val5))..ctor(val3.x, val4.y, val3.z); Vector3 val6 = val5 + Vector3.up * 0.28f; Vector3 destinationFeet = val6; destinationFeet.y -= num4; if (!HasDestinationClearance(thisController, destinationFeet, mask) || !HasSweptCapsuleClearance(thisController, ((Component)player).transform.position, val3, mask) || !HasSweptCapsuleClearance(thisController, val3, val6, mask) || !HasSweptCapsuleClearance(thisController, val6, val4, mask) || !HasInteriorContainment(player, val, mask)) { return false; } bool tall = num3 > 1.35f; Vector3 ledgeGripCenter = default(Vector3); ((Vector3)(ref ledgeGripCenter))..ctor(((RaycastHit)(ref wallHit)).point.x, ((RaycastHit)(ref topHit)).point.y, ((RaycastHit)(ref wallHit)).point.z); probe = new MantleProbe(val3, val5, val4, normal, num3, tall, ledgeGripCenter); return true; } private static bool TryFindWallAnchor(PlayerControllerB player, Vector3 forward, float castRadius, float feetY, int mask, out RaycastHit wallHit, out Vector3 wallAnchor) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0051: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_00aa: Unknown result type (might be due to invalid IL or missing references) wallHit = default(RaycastHit); wallAnchor = default(Vector3); if ((Object)(object)player == (Object)null || (Object)(object)((Component)player).transform == (Object)null) { return false; } Vector3 position = ((Component)player).transform.position; float num = feetY + 3f; RaycastHit val = default(RaycastHit); for (float num2 = feetY + 0.45f; num2 <= num + 0.001f; num2 += 0.3f) { position.y = num2; if (Physics.SphereCast(new Ray(position, forward), castRadius, ref val, 1.35f, mask, (QueryTriggerInteraction)1) && !((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)) { if (IsRejectedMantleSurface(((RaycastHit)(ref val)).collider)) { return false; } if (!(Vector3.Dot(((RaycastHit)(ref val)).normal, Vector3.up) >= 0.35f)) { wallHit = val; wallAnchor = position; return true; } } } return false; } private static bool TryFindLedgeTop(Vector3 wallAnchor, Vector3 forward, RaycastHit wallHit, float castRadius, float feetY, int mask, out RaycastHit topHit) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_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_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) topHit = default(RaycastHit); float num = feetY + 3f + 0.3f; RaycastHit val2 = default(RaycastHit); for (float num2 = wallAnchor.y; num2 <= num + 0.001f; num2 += 0.25f) { Vector3 val = wallAnchor; val.y = num2; if (!Physics.SphereCast(new Ray(val, forward), castRadius, ref val2, 1.35f, mask, (QueryTriggerInteraction)1)) { Vector3 val3 = ((RaycastHit)(ref wallHit)).point + forward * 0.15f; val3.y = num2; if (!Physics.Raycast(val3, Vector3.down, ref topHit, 0.75f, mask, (QueryTriggerInteraction)1)) { return false; } return true; } } return false; } private static float ResolveMantleDuration(MantleProbe probe) { if (!probe.Tall) { return 0.667f; } float num = Mathf.Clamp(probe.LedgeHeight / 2f, 0.9f, 1.4f); return 1.3f * num; } private static void FaceMantleWall(PlayerControllerB player, Vector3 wallNormal) { //IL_0018: 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_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_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //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_004c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0070: 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) if (!((Object)(object)player == (Object)null) && !((Object)(object)((Component)player).transform == (Object)null)) { Vector3 val = Vector3.ProjectOnPlane(-wallNormal, Vector3.up); if (!(((Vector3)(ref val)).sqrMagnitude < 0.001f)) { Quaternion val2 = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); float y = ((Quaternion)(ref val2)).eulerAngles.y; Vector3 eulerAngles = ((Component)player).transform.eulerAngles; ((Component)player).transform.rotation = Quaternion.Euler(eulerAngles.x, y, eulerAngles.z); } } } private static void BeginMantle(PlayerControllerB player, MantleProbe probe) { //IL_000b: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: 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_0139: Unknown result type (might be due to invalid IL or missing references) //IL_013f: Unknown result type (might be due to invalid IL or missing references) InteractionAnimationHandle val = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val)) { LCInteractionAnimationAPI.TryStopInteraction(val, (InteractionAnimationStopReason)2); } InteractionAnimationHandle val2 = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)0, ref val2)) { LCInteractionAnimationAPI.TryStopInteraction(val2, (InteractionAnimationStopReason)2); } InteractionAnimationHandle val3 = default(InteractionAnimationHandle); if (!LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val3) && !LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)0, ref val3) && SlideAnimationBridge.BeginMantle(player, probe.Tall)) { _mantlePlayer = player; _mantleStartPosition = probe.StartPosition; _mantleLiftPosition = probe.LiftPosition; _mantleEndPosition = probe.EndPosition; _mantleLastSafePosition = probe.StartPosition; _mantleLedgeGripCenter = probe.LedgeGripCenter; _mantleWallNormal = probe.WallNormal; _mantleDuration = ResolveMantleDuration(probe); _mantleStartedAt = Time.time; _mantleActive = true; _nextMantleArmsDiagnosticAt = 0f; _mantleOccluderDumpDone = false; SubscribeMantleRenderTruth(); SetPlayerPosition(player, _mantleStartPosition); FaceMantleWall(player, probe.WallNormal); _mantleAnimStarted = true; PanicSlidePatch.BeginMovementLookLimit(player); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Panic Slide] Mantle FP arms diagnostics enabled for active mantle."); } SaveAndLockInput(player); ZeroMovementForces(player); ZeroFallValues(player); ApplyStaminaCost(player); PanicSlidePatch.BeginFirstPersonMovementPresentation(player, showBody: false); float sessionSeconds = _mantleDuration * 0.9f; SendMantleStart(player.playerClientId, probe.Tall ? ((byte)1) : ((byte)0), sessionSeconds, probe.LedgeGripCenter, probe.WallNormal); } } private static void UpdateMantle(PlayerControllerB player) { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_009d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)_mantlePlayer) { AbortMantle("player-changed"); return; } if (ShouldAbortMantle(player)) { AbortMantle("aborted"); return; } float num = Time.time - _mantleStartedAt; float num2 = ((_mantleDuration > 0.001f) ? Mathf.Clamp01(num / _mantleDuration) : 1f); Vector3 val = EvaluateMantlePosition(num2); int mask = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); if (!HasSweptCapsuleClearance(player.thisController, ((Component)player).transform.position, val, mask)) { SetPlayerPosition(player, _mantleLastSafePosition); AbortMantle("path-blocked"); return; } SetPlayerPosition(player, val); _mantleLastSafePosition = val; ZeroMovementForces(player); ZeroFallValues(player); ReanchorMantleFirstPersonArms(player); if (num2 >= 0.9f) { FinishMantle(); } } private static bool ShouldAbortMantle(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || player.criticallyInjured) { return true; } if (player.inSpecialInteractAnimation || player.isClimbingLadder) { return true; } return IsPlayerInVehicle(player); } private static Vector3 EvaluateMantlePosition(float t) { //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) //IL_000f: 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) //IL_0082: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = _mantleLiftPosition + Vector3.up * 0.28f; Vector3 result; if (t <= 0.6f) { float num = Mathf.Clamp01(t / 0.6f); num = Mathf.SmoothStep(0f, 1f, num); result = Vector3.Lerp(_mantleStartPosition, val, num); } else { float num2 = Mathf.Max(0.0001f, 0.29999995f); float num3 = Mathf.Clamp01((t - 0.6f) / num2); num3 = Mathf.SmoothStep(0f, 1f, num3); result = Vector3.Lerp(val, _mantleEndPosition, num3); } result.y -= 0.25f * EvaluateMantleBodyLowerWeight(t); return result; } private static float EvaluateMantleBodyLowerWeight(float t) { float num = Mathf.Clamp01(0.25f); if (num <= 0.0001f) { if (!(t >= 1f)) { return 1f; } return 0f; } float num2 = 1f - num; if (t <= num2) { return 1f; } float num3 = Mathf.Clamp01((t - num2) / num); return 1f - Mathf.SmoothStep(0f, 1f, num3); } private static void LogMantleArmsDiagnostics(PlayerControllerB player) { //IL_006a: 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_00aa: 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) if (!((Object)(object)player == (Object)null) && !(Time.time < _nextMantleArmsDiagnosticAt)) { _nextMantleArmsDiagnosticAt = Time.time + 0.2f; _renderDiagLogThisFrame = true; Transform localArmsTransform = player.localArmsTransform; Transform val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : null); string text = (((Object)(object)localArmsTransform != (Object)null && (Object)(object)val != (Object)null) ? Vector3.Distance(localArmsTransform.position, val.position).ToString("F4") : ""); ResolveMantleArmsHandBones(player); object obj; if (!((Object)(object)player.playerModelArmsMetarig != (Object)null)) { obj = ""; } else { Vector3 lossyScale = player.playerModelArmsMetarig.lossyScale; obj = ((Vector3)(ref lossyScale)).ToString("F3"); } string text2 = (string)obj; string text3 = FormatNullablePosition(player.cameraContainerTransform); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide] Mantle FP arms diagnostics: " + $"frame={Time.frameCount}, " + "localArmsTransform.position=" + FormatNullablePosition(localArmsTransform) + ", camera.position=" + FormatNullablePosition(val) + ", cameraContainer.position=" + text3 + ", armsToCameraMeters=" + text + ", handL(cam-local)=" + FormatCameraLocal(val, _mantleArmsHandLeft) + ", handR(cam-local)=" + FormatCameraLocal(val, _mantleArmsHandRight) + ", armsMetarigScale=" + text2 + ", " + $"fpvBodyView={SlideAnimationBridge.IsFirstPersonViewLocalBodyShown()}.")); } Transform playerModelArmsMetarig = player.playerModelArmsMetarig; Transform localArmsRotationTarget = player.localArmsRotationTarget; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide] Mantle FP arms rig anchors: " + $"frame={Time.frameCount}, " + "metarig(cam-local)=" + FormatCameraLocal(val, playerModelArmsMetarig) + ", metarigLocalPos=" + FormatNullableLocalPosition(playerModelArmsMetarig) + ", metarigLocalEuler=" + FormatNullableLocalEuler(playerModelArmsMetarig) + ", metarigRotDeltaVsCam=" + FormatRotationDelta(val, playerModelArmsMetarig) + ", rotTargetDeltaVsCam=" + FormatRotationDelta(val, localArmsRotationTarget) + ", armsRootLocalEuler=" + FormatNullableLocalEuler(localArmsTransform) + ", armsRoot(cam-local)=" + FormatCameraLocal(val, localArmsTransform) + ", spine003(cam-local)=" + FormatCameraLocal(val, _mantleArmsSpine003) + ", spine003LocalPos=" + FormatNullableLocalPosition(_mantleArmsSpine003) + ", spine003LocalEuler=" + FormatNullableLocalEuler(_mantleArmsSpine003) + ", shoulderL(cam-local)=" + FormatCameraLocal(val, _mantleArmsShoulderLeft) + ", shoulderR(cam-local)=" + FormatCameraLocal(val, _mantleArmsShoulderRight) + ", targetL(cam-local)=" + FormatCameraLocal(val, _mantleArmsTargetLeft) + ", targetR(cam-local)=" + FormatCameraLocal(val, _mantleArmsTargetRight) + ".")); } } } private static string FormatNullableLocalPosition(Transform transform) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)transform == (Object)null)) { Vector3 localPosition = transform.localPosition; return ((Vector3)(ref localPosition)).ToString("F4"); } return ""; } private static string FormatNullableLocalEuler(Transform transform) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)transform == (Object)null)) { Vector3 localEulerAngles = transform.localEulerAngles; return ((Vector3)(ref localEulerAngles)).ToString("F2"); } return ""; } private static string FormatRotationDelta(Transform cameraTransform, Transform bone) { //IL_0019: 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_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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) if ((Object)(object)cameraTransform == (Object)null || (Object)(object)bone == (Object)null) { return ""; } Quaternion val = Quaternion.Inverse(cameraTransform.rotation) * bone.rotation; Vector3 eulerAngles = ((Quaternion)(ref val)).eulerAngles; return ((Vector3)(ref eulerAngles)).ToString("F2"); } private static string FormatCameraLocal(Transform cameraTransform, Transform bone) { //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_0024: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cameraTransform == (Object)null || (Object)(object)bone == (Object)null) { return ""; } Vector3 val = cameraTransform.InverseTransformPoint(bone.position); return ((Vector3)(ref val)).ToString("F3"); } private static void SubscribeMantleRenderTruth() { if (!_renderDiagSubscribed) { _renderDiagSubscribed = true; _renderDiagSnapshotFrame = -1; _renderDiagLogThisFrame = false; RenderPipelineManager.beginCameraRendering += OnMantleBeginCameraRendering; } } private static void UnsubscribeMantleRenderTruth() { if (_renderDiagSubscribed) { _renderDiagSubscribed = false; _renderDiagSnapshotFrame = -1; _renderDiagLogThisFrame = false; RenderPipelineManager.beginCameraRendering -= OnMantleBeginCameraRendering; } } private static void CaptureMantleRenderTruthSnapshot(PlayerControllerB player) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_009c: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : null); if (!((Object)(object)val == (Object)null)) { _renderDiagSnapshotFrame = Time.frameCount; _renderDiagCamPos = val.position; _renderDiagCamRot = val.rotation; _renderDiagHandLCam = CameraLocalOrZero(val, _mantleArmsHandLeft); _renderDiagHandRCam = CameraLocalOrZero(val, _mantleArmsHandRight); _renderDiagArmsRootCam = CameraLocalOrZero(val, player.localArmsTransform); _renderDiagArmsRootWorld = (((Object)(object)player.localArmsTransform != (Object)null) ? player.localArmsTransform.position : Vector3.zero); _renderDiagSpine003Cam = CameraLocalOrZero(val, _mantleArmsSpine003); } } private static Vector3 CameraLocalOrZero(Transform cameraTransform, Transform bone) { //IL_0016: 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) if (!((Object)(object)bone == (Object)null)) { return cameraTransform.InverseTransformPoint(bone.position); } return Vector3.zero; } private static void OnMantleBeginCameraRendering(ScriptableRenderContext context, Camera camera) { //IL_0051: 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_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: 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_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_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_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: 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_00ba: 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_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0160: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_016c: 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) //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) //IL_01ac: 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_01e2: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_0207: 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_0213: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_024e: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) if (!_mantleActive || !_renderDiagLogThisFrame) { return; } PlayerControllerB mantlePlayer = _mantlePlayer; if (!((Object)(object)mantlePlayer == (Object)null) && !((Object)(object)camera == (Object)null) && !((Object)(object)mantlePlayer.gameplayCamera != (Object)(object)camera) && Time.frameCount == _renderDiagSnapshotFrame) { _renderDiagLogThisFrame = false; Transform transform = ((Component)camera).transform; Vector3 val = transform.position - _renderDiagCamPos; float num = Quaternion.Angle(_renderDiagCamRot, transform.rotation); Vector3 val2 = CameraLocalOrZero(transform, _mantleArmsHandLeft); Vector3 val3 = CameraLocalOrZero(transform, _mantleArmsHandRight); Vector3 val4 = CameraLocalOrZero(transform, mantlePlayer.localArmsTransform); Vector3 val5 = (((Object)(object)mantlePlayer.localArmsTransform != (Object)null) ? mantlePlayer.localArmsTransform.position : Vector3.zero); Vector3 val6 = CameraLocalOrZero(transform, _mantleArmsSpine003); ManualLogSource log = Plugin.Log; if (log != null) { string[] obj = new string[27] { "[Panic Slide] Mantle render-truth diff: ", $"frame={Time.frameCount}, ", "camera=", ((Object)camera).name, ", camPosDelta=", ((Vector3)(ref val)).ToString("F4"), ", ", $"camRotDeltaDeg={num:F2}, ", "handL(cam-local render)=", ((Vector3)(ref val2)).ToString("F3"), ", handLDelta=", null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null }; Vector3 val7 = val2 - _renderDiagHandLCam; obj[11] = ((Vector3)(ref val7)).ToString("F3"); obj[12] = ", handR(cam-local render)="; obj[13] = ((Vector3)(ref val3)).ToString("F3"); obj[14] = ", handRDelta="; val7 = val3 - _renderDiagHandRCam; obj[15] = ((Vector3)(ref val7)).ToString("F3"); obj[16] = ", armsRoot(cam-local render)="; obj[17] = ((Vector3)(ref val4)).ToString("F3"); obj[18] = ", armsRootDelta="; val7 = val4 - _renderDiagArmsRootCam; obj[19] = ((Vector3)(ref val7)).ToString("F3"); obj[20] = ", armsRootWorldDelta="; val7 = val5 - _renderDiagArmsRootWorld; obj[21] = ((Vector3)(ref val7)).ToString("F4"); obj[22] = ", spine003(cam-local render)="; obj[23] = ((Vector3)(ref val6)).ToString("F3"); obj[24] = ", spine003Delta="; val7 = val6 - _renderDiagSpine003Cam; obj[25] = ((Vector3)(ref val7)).ToString("F3"); obj[26] = "."; log.LogInfo((object)string.Concat(obj)); } } } private static void DumpMovementPatchOwnersOnce(PlayerControllerB player) { if (_patchOwnerDumpDone || (Object)(object)player == (Object)null) { return; } _patchOwnerDumpDone = true; try { DumpPatchOwners(typeof(PlayerControllerB), "Update"); DumpPatchOwners(typeof(PlayerControllerB), "LateUpdate"); DumpForeignPlayerComponents(player); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[Panic Slide] Patch-owner dump failed: {arg}"); } } } private static void DumpPatchOwners(Type declaringType, string methodName) { MethodBase methodBase = AccessTools.Method(declaringType, methodName, (Type[])null, (Type[])null); Patches val = ((methodBase != null) ? Harmony.GetPatchInfo(methodBase) : null); if (val == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide] Patch owners " + declaringType.Name + "." + methodName + ": none.")); } return; } StringBuilder stringBuilder = new StringBuilder(); AppendPatchList(stringBuilder, "prefix", val.Prefixes); AppendPatchList(stringBuilder, "postfix", val.Postfixes); AppendPatchList(stringBuilder, "transpiler", val.Transpilers); AppendPatchList(stringBuilder, "finalizer", val.Finalizers); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide] Patch owners " + declaringType.Name + "." + methodName + ": " + ((stringBuilder.Length > 0) ? stringBuilder.ToString() : "none") + ".")); } } private static void AppendPatchList(StringBuilder builder, string kind, ReadOnlyCollection patchList) { if (patchList == null) { return; } foreach (Patch patch in patchList) { if (patch != null && !(patch.PatchMethod == null)) { if (builder.Length > 0) { builder.Append("; "); } builder.Append(kind).Append(' ').Append(patch.owner) .Append("(prio ") .Append(patch.priority) .Append(") ") .Append((patch.PatchMethod.DeclaringType != null) ? patch.PatchMethod.DeclaringType.FullName : "") .Append('.') .Append(patch.PatchMethod.Name); } } } private static void DumpForeignPlayerComponents(PlayerControllerB player) { HashSet seen = new HashSet(); StringBuilder stringBuilder = new StringBuilder(); int count = 0; AppendForeignComponents(((Component)player).transform.root, seen, stringBuilder, ref count); Transform val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.root : null); if ((Object)(object)val != (Object)null && (Object)(object)val != (Object)(object)((Component)player).transform.root) { AppendForeignComponents(val, seen, stringBuilder, ref count); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)($"[Panic Slide] Foreign components on player/camera hierarchy ({count}): " + ((count > 0) ? stringBuilder.ToString() : "none") + ".")); } } private static void AppendForeignComponents(Transform root, HashSet seen, StringBuilder builder, ref int count) { Component[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Component val in componentsInChildren) { if ((Object)(object)val == (Object)null) { continue; } Type type = ((object)val).GetType(); string name = type.Assembly.GetName().Name; if (IsVanillaAssembly(name)) { continue; } string text = name + "!" + type.FullName + " @ " + GetTransformPath(val.transform); if (seen.Add(text)) { count++; if (builder.Length > 0) { builder.Append("; "); } builder.Append(text); } } } private static bool IsVanillaAssembly(string assemblyName) { if (string.IsNullOrEmpty(assemblyName)) { return true; } switch (assemblyName) { default: if (!assemblyName.StartsWith("System", StringComparison.Ordinal) && !assemblyName.StartsWith("Unity", StringComparison.Ordinal) && !assemblyName.StartsWith("Dissonance", StringComparison.Ordinal) && !assemblyName.StartsWith("Facepunch", StringComparison.Ordinal)) { return assemblyName.StartsWith("Y4NGZ", StringComparison.Ordinal); } break; case "Assembly-CSharp": case "mscorlib": case "netstandard": break; } return true; } private static string GetTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return ""; } StringBuilder stringBuilder = new StringBuilder(((Object)transform).name); Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { stringBuilder.Insert(0, '/').Insert(0, ((Object)parent).name); parent = parent.parent; } return stringBuilder.ToString(); } private static void ResolveMantleArmsHandBones(PlayerControllerB player) { if (_mantleArmsHandBonesResolved) { return; } _mantleArmsHandBonesResolved = true; Transform val = (((Object)(object)player != (Object)null) ? player.playerModelArmsMetarig : null); if ((Object)(object)val == (Object)null) { return; } Transform[] componentsInChildren = ((Component)val).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if ((Object)(object)_mantleArmsHandLeft == (Object)null && string.Equals(((Object)val2).name, "hand.L", StringComparison.Ordinal)) { _mantleArmsHandLeft = val2; } else if ((Object)(object)_mantleArmsHandRight == (Object)null && string.Equals(((Object)val2).name, "hand.R", StringComparison.Ordinal)) { _mantleArmsHandRight = val2; } else if ((Object)(object)_mantleArmsSpine003 == (Object)null && string.Equals(((Object)val2).name, "spine.003", StringComparison.Ordinal)) { _mantleArmsSpine003 = val2; } else if ((Object)(object)_mantleArmsShoulderLeft == (Object)null && string.Equals(((Object)val2).name, "shoulder.L", StringComparison.Ordinal)) { _mantleArmsShoulderLeft = val2; } else if ((Object)(object)_mantleArmsShoulderRight == (Object)null && string.Equals(((Object)val2).name, "shoulder.R", StringComparison.Ordinal)) { _mantleArmsShoulderRight = val2; } else if ((Object)(object)_mantleArmsTargetLeft == (Object)null && string.Equals(((Object)val2).name, "ArmsLeftArm_target", StringComparison.Ordinal)) { _mantleArmsTargetLeft = val2; } else if ((Object)(object)_mantleArmsTargetRight == (Object)null && string.Equals(((Object)val2).name, "ArmsRightArm_target", StringComparison.Ordinal)) { _mantleArmsTargetRight = val2; } } } private static string FormatNullablePosition(Transform transform) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)transform == (Object)null) { return ""; } Vector3 position = transform.position; return $"({position.x:F4}, {position.y:F4}, {position.z:F4})"; } private static void ReanchorMantleFirstPersonArms(PlayerControllerB player) { //IL_003a: 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_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_00a7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } try { if ((Object)(object)player.localArmsTransform != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) { Transform transform = ((Component)player.gameplayCamera).transform; player.localArmsTransform.position = transform.position + transform.up * -0.5f; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Panic Slide] Mantle local arms position re-anchor skipped: " + ex.Message)); } } try { if ((Object)(object)player.playerModelArmsMetarig != (Object)null && (Object)(object)player.localArmsRotationTarget != (Object)null) { player.playerModelArmsMetarig.rotation = player.localArmsRotationTarget.rotation; } } catch (Exception ex2) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogDebug((object)("[Panic Slide] Mantle arms metarig rotation re-anchor skipped: " + ex2.Message)); } } } private static void HideLocalMantleBody(PlayerControllerB player) { ResolveMantleHideTargets(player); if (_mantleFpHiddenLayer >= 0) { for (int i = 0; i < _mantleBodyLods.Length; i++) { Renderer val = _mantleBodyLods[i]; if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null) { ((Component)val).gameObject.layer = _mantleFpHiddenLayer; } } } bool hidden = SlideAnimationBridge.IsFirstPersonViewLocalBodyShown(); SetMantleBodyForceHidden(player, hidden); for (int j = 0; j < _mantleHeadCosmetics.Length; j++) { Renderer val2 = _mantleHeadCosmetics[j]; if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } } private static void SetMantleBodyForceHidden(PlayerControllerB player, bool hidden) { if (!((Object)(object)player == (Object)null)) { SetForceRenderingOff((Renderer)(object)player.thisPlayerModel, hidden); SetForceRenderingOff((Renderer)(object)player.thisPlayerModelLOD1, hidden); SetForceRenderingOff((Renderer)(object)player.thisPlayerModelLOD2, hidden); _mantleBodyForceHidden = hidden; } } private static void SetForceRenderingOff(Renderer renderer, bool value) { if ((Object)(object)renderer != (Object)null && renderer.forceRenderingOff != value) { renderer.forceRenderingOff = value; } } private static void RestoreLocalMantleBody() { if (_mantleBodyForceHidden) { SetMantleBodyForceHidden(_mantlePlayer, hidden: false); } for (int i = 0; i < _mantleBodyLods.Length; i++) { Renderer val = _mantleBodyLods[i]; if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null && i < _mantleBodyLodSavedLayers.Length) { ((Component)val).gameObject.layer = _mantleBodyLodSavedLayers[i]; } } for (int j = 0; j < _mantleHeadCosmetics.Length; j++) { Renderer val2 = _mantleHeadCosmetics[j]; if ((Object)(object)val2 != (Object)null && j < _mantleHeadCosmeticSavedEnabled.Length) { val2.enabled = _mantleHeadCosmeticSavedEnabled[j]; } } _mantleHideResolved = false; _mantleBodyLods = Array.Empty(); _mantleBodyLodSavedLayers = Array.Empty(); _mantleFpHiddenLayer = -1; _mantleHeadCosmetics = Array.Empty(); _mantleHeadCosmeticSavedEnabled = Array.Empty(); } private static void ResolveMantleHideTargets(PlayerControllerB player) { if (!_mantleHideResolved && !((Object)(object)player == (Object)null)) { _mantleHideResolved = true; _mantleFpHiddenLayer = (((Object)(object)player.thisPlayerModel != (Object)null && (Object)(object)((Component)player.thisPlayerModel).gameObject != (Object)null) ? ((Component)player.thisPlayerModel).gameObject.layer : (-1)); List list = new List(); AddRenderer((Renderer)(object)player.thisPlayerModelLOD1, list); AddRenderer((Renderer)(object)player.thisPlayerModelLOD2, list); _mantleBodyLods = list.ToArray(); _mantleBodyLodSavedLayers = new int[_mantleBodyLods.Length]; for (int i = 0; i < _mantleBodyLods.Length; i++) { _mantleBodyLodSavedLayers[i] = (((Object)(object)_mantleBodyLods[i] != (Object)null && (Object)(object)((Component)_mantleBodyLods[i]).gameObject != (Object)null) ? ((Component)_mantleBodyLods[i]).gameObject.layer : 0); } List list2 = new List(); AddRenderersUnder(player.localVisor, list2); AddRenderersUnder(player.headCostumeContainerLocal, list2); _mantleHeadCosmetics = list2.ToArray(); _mantleHeadCosmeticSavedEnabled = new bool[_mantleHeadCosmetics.Length]; for (int j = 0; j < _mantleHeadCosmetics.Length; j++) { _mantleHeadCosmeticSavedEnabled[j] = (Object)(object)_mantleHeadCosmetics[j] != (Object)null && _mantleHeadCosmetics[j].enabled; } } } private static void AddRenderer(Renderer renderer, List renderers) { if ((Object)(object)renderer != (Object)null && !renderers.Contains(renderer)) { renderers.Add(renderer); } } private static void SetMantleFirstPersonArmsHidden(PlayerControllerB player, bool hidden) { ResolveMantleFpArmRenderers(player); _mantleFpArmsHidden = hidden; for (int i = 0; i < _mantleFpArmRenderers.Length; i++) { Renderer val = _mantleFpArmRenderers[i]; if ((Object)(object)val != (Object)null) { val.forceRenderingOff = hidden; } } } private static void ResolveMantleFpArmRenderers(PlayerControllerB player) { if (!_mantleFpArmRenderersResolved && !((Object)(object)player == (Object)null)) { _mantleFpArmRenderersResolved = true; Transform playerModelArmsMetarig = player.playerModelArmsMetarig; Transform val = (((Object)(object)playerModelArmsMetarig != (Object)null) ? playerModelArmsMetarig.parent : null); _mantleFpArmRenderers = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentsInChildren(true) : Array.Empty()); } } private static void ApplyMantleBodyGrabIK(PlayerControllerB player, float weight) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (!(weight <= 0.02f)) { ResolveBodyArmBones(player); ApplyMantleBodyGrabIK(weight, _mantleLedgeGripCenter, _mantleWallNormal, _bodyArmUpperL, _bodyArmLowerL, _bodyHandL, _bodyArmUpperR, _bodyArmLowerR, _bodyHandR); } } private static void ApplyRemoteMantleBodyGrabIK(PlayerControllerB player) { ulong playerClientId = player.playerClientId; if (!RemoteMantles.TryGetValue(playerClientId, out var value)) { return; } ConfigEntry remoteMantleBodyGrabIk = Plugin.RemoteMantleBodyGrabIk; if (remoteMantleBodyGrabIk != null && !remoteMantleBodyGrabIk.Value) { RemoteMantles.Remove(playerClientId); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-mantle] body_grab_end_gate: " + $"playerClientId={playerClientId} reason='config_disabled'.")); } return; } if (value.Player != player || !SlideAnimationBridge.IsActive(player)) { RemoteMantles.Remove(playerClientId); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide.remote-mantle] body_grab_end_gate: " + $"playerClientId={playerClientId} reason='" + ((value.Player != player) ? "player_replaced" : "bridge_inactive") + "'.")); } return; } float num = value.CalculateGrabEnvelope(); if (num <= 0.02f) { value.LogBodyGrabGate("envelope_zero", num); return; } value.ResolveBodyArmBones(); if (!value.HasBodyArmBones) { value.LogBodyGrabGate("bones_missing", num); } else { ApplyRemoteMantleBodyGrabPose(value, num); } } private static void ApplyRemoteMantleBodyGrabPose(RemoteMantlePresentation remote, float weight) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_004e: Unknown result type (might be due to invalid IL or missing references) AssignMantleGrips(remote.BodyHandL, remote.BodyHandR, remote.LedgeGripCenter, remote.WallNormal, out var gripL, out var gripR); bool reachClamped; bool num = SolveArmBendPreservingBlended(remote.BodyArmUpperL, remote.BodyArmLowerL, remote.BodyHandL, gripL, weight, out reachClamped); bool reachClamped2; bool flag = SolveArmBendPreservingBlended(remote.BodyArmUpperR, remote.BodyArmLowerR, remote.BodyHandR, gripR, weight, out reachClamped2); if (!num || !flag) { remote.LogBodyGrabGate("solve_skipped", weight); } else { remote.LogBodyGrabGate((reachClamped || reachClamped2) ? "applied_bend_preserving_clamped" : "applied_bend_preserving", weight); } } private static void ApplyMantleBodyGrabIK(float weight, Vector3 ledgeGripCenter, Vector3 wallNormal, Transform armUpperL, Transform armLowerL, Transform handL, Transform armUpperR, Transform armLowerR, Transform handR) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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) if (!(weight <= 0.02f) && !((Object)(object)armUpperL == (Object)null) && !((Object)(object)armLowerL == (Object)null) && !((Object)(object)handL == (Object)null) && !((Object)(object)armUpperR == (Object)null) && !((Object)(object)armLowerR == (Object)null) && !((Object)(object)handR == (Object)null)) { AssignMantleGrips(handL, handR, ledgeGripCenter, wallNormal, out var gripL, out var gripR); SolveArmFabrikBlended(armUpperL, armLowerL, handL, gripL, weight); SolveArmFabrikBlended(armUpperR, armLowerR, handR, gripR, weight); } } private static void ApplyMantleFpArmGrabIK(PlayerControllerB player, float weight) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_008f: 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_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_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_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: 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_0121: 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_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_011b: Unknown result type (might be due to invalid IL or missing references) //IL_011c: 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_014c: Unknown result type (might be due to invalid IL or missing references) if (weight <= 0.02f) { return; } ResolveFpArmBones(player); if ((Object)(object)_fpArmUpperL == (Object)null || (Object)(object)_fpArmLowerL == (Object)null || (Object)(object)_fpHandL == (Object)null || (Object)(object)_fpArmUpperR == (Object)null || (Object)(object)_fpArmLowerR == (Object)null || (Object)(object)_fpHandR == (Object)null) { return; } Camera gameplayCamera = player.gameplayCamera; if (!((Object)(object)gameplayCamera == (Object)null)) { Vector3 val = Vector3.Cross(_mantleWallNormal, Vector3.up); val = ((((Vector3)(ref val)).sqrMagnitude < 1E-05f) ? Vector3.right : ((Vector3)(ref val)).normalized); Vector3 val2 = ProjectGripToViewmodel(gameplayCamera, _mantleLedgeGripCenter - val * 0.28f); Vector3 val3 = ProjectGripToViewmodel(gameplayCamera, _mantleLedgeGripCenter + val * 0.28f); Vector3 target; Vector3 target2; if (Vector3.Distance(_fpHandL.position, val3) + Vector3.Distance(_fpHandR.position, val2) < Vector3.Distance(_fpHandL.position, val2) + Vector3.Distance(_fpHandR.position, val3)) { target = val3; target2 = val2; } else { target = val2; target2 = val3; } SolveArmFabrikBlended(_fpArmUpperL, _fpArmLowerL, _fpHandL, target, weight); SolveArmFabrikBlended(_fpArmUpperR, _fpArmLowerR, _fpHandR, target2, weight); } } private static Vector3 ProjectGripToViewmodel(Camera cam, Vector3 worldGrip) { //IL_0006: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: 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_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)cam).transform.InverseTransformDirection(worldGrip - ((Component)cam).transform.position); if (val.z < 0.05f) { val.z = 0.05f; } Vector3 val2 = val * (0.5f / val.z); return ((Component)cam).transform.TransformPoint(val2); } private static void AssignMantleGrips(Transform handL, Transform handR, out Vector3 gripL, out Vector3 gripR) { //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) AssignMantleGrips(handL, handR, _mantleLedgeGripCenter, _mantleWallNormal, out gripL, out gripR); } private static void AssignMantleGrips(Transform handL, Transform handR, Vector3 ledgeGripCenter, Vector3 wallNormal, out Vector3 gripL, out Vector3 gripR) { //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_0006: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_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_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //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_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009c: 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_0083: 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_008b: 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) Vector3 val = Vector3.Cross(wallNormal, Vector3.up); val = ((((Vector3)(ref val)).sqrMagnitude < 1E-05f) ? Vector3.right : ((Vector3)(ref val)).normalized); Vector3 val2 = ledgeGripCenter - val * 0.28f; Vector3 val3 = ledgeGripCenter + val * 0.28f; if (Vector3.Distance(handL.position, val3) + Vector3.Distance(handR.position, val2) < Vector3.Distance(handL.position, val2) + Vector3.Distance(handR.position, val3)) { gripL = val3; gripR = val2; } else { gripL = val2; gripR = val3; } } private static void ResolveFpArmBones(PlayerControllerB player) { if (!_mantleFpArmBonesResolved) { _mantleFpArmBonesResolved = true; Transform val = (((Object)(object)player != (Object)null) ? player.playerModelArmsMetarig : null); if (!((Object)(object)val == (Object)null)) { _fpArmUpperL = FindDeep(val, "arm.L_upper"); _fpArmLowerL = FindDeep(val, "arm.L_lower"); _fpHandL = FindDeep(val, "hand.L"); _fpArmUpperR = FindDeep(val, "arm.R_upper"); _fpArmLowerR = FindDeep(val, "arm.R_lower"); _fpHandR = FindDeep(val, "hand.R"); } } } private static void SolveArmFabrikBlended(Transform upper, Transform lower, Transform hand, Vector3 target, float weight) { //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) //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_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_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_0125: 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_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0115: 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) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0146: 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_0149: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: 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_00ab: 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_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01c3: 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_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) //IL_019b: Unknown result type (might be due to invalid IL or missing references) weight = Mathf.Clamp01(weight); if (weight <= 0.001f) { return; } Quaternion rotation = upper.rotation; Quaternion rotation2 = lower.rotation; Vector3 position = upper.position; Vector3 val = lower.position; Vector3 val2 = hand.position; float num = Vector3.Distance(position, val); float num2 = Vector3.Distance(val, val2); if (num < 0.0001f || num2 < 0.0001f) { return; } Vector3 val3; if (Vector3.Distance(position, target) >= num + num2) { val3 = target - position; Vector3 normalized = ((Vector3)(ref val3)).normalized; val = position + normalized * num; val2 = val + normalized * num2; } else { for (int i = 0; i < 10; i++) { if (!(Vector3.Distance(val2, target) > 0.0001f)) { break; } val2 = target; Vector3 val4 = val2; val3 = val - val2; val = val4 + ((Vector3)(ref val3)).normalized * num2; val3 = val - position; val = position + ((Vector3)(ref val3)).normalized * num; Vector3 val5 = val; val3 = val2 - val; val2 = val5 + ((Vector3)(ref val3)).normalized * num2; } } Vector3 val6 = lower.position - upper.position; if (((Vector3)(ref val6)).sqrMagnitude > 1E-08f) { upper.rotation = Quaternion.FromToRotation(val6, val - position) * upper.rotation; } Vector3 val7 = hand.position - lower.position; if (((Vector3)(ref val7)).sqrMagnitude > 1E-08f) { lower.rotation = Quaternion.FromToRotation(val7, val2 - val) * lower.rotation; } upper.rotation = Quaternion.Slerp(rotation, upper.rotation, weight); lower.rotation = Quaternion.Slerp(rotation2, lower.rotation, weight); } private static bool SolveArmBendPreservingBlended(Transform upper, Transform lower, Transform hand, Vector3 target, float weight, out bool reachClamped) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0060: 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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: 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_0099: 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_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: 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_00f2: 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_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0183: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_019f: 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_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01ab: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01b1: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: 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_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_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: 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_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_0201: Unknown result type (might be due to invalid IL or missing references) //IL_01c8: Unknown result type (might be due to invalid IL or missing references) //IL_01ca: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) //IL_01dd: 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_0137: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: 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_0247: Unknown result type (might be due to invalid IL or missing references) //IL_024a: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0259: 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_0268: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_026d: Unknown result type (might be due to invalid IL or missing references) //IL_0220: Unknown result type (might be due to invalid IL or missing references) //IL_0222: 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_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) reachClamped = false; weight = Mathf.Clamp01(weight); if (weight <= 0.001f || (Object)(object)upper == (Object)null || (Object)(object)lower == (Object)null || (Object)(object)hand == (Object)null) { return false; } Quaternion rotation = upper.rotation; Quaternion rotation2 = lower.rotation; Vector3 position = upper.position; Vector3 position2 = lower.position; Vector3 position3 = hand.position; float num = Vector3.Distance(position, position2); float num2 = Vector3.Distance(position2, position3); Vector3 val = target - position; float magnitude = ((Vector3)(ref val)).magnitude; if (num < 0.0001f || num2 < 0.0001f || magnitude < 0.0001f) { return false; } Vector3 val2 = val / magnitude; float num3 = Mathf.Abs(num - num2) + 0.0001f; float num4 = Mathf.Max(num3, (num + num2) * 0.92f); float num5 = Mathf.Clamp(magnitude, num3, num4); reachClamped = magnitude < num3 || magnitude > num4; Vector3 val3 = position2 - position; Vector3 val4 = val3 - val2 * Vector3.Dot(val3, val2); if (((Vector3)(ref val4)).sqrMagnitude < 1E-08f) { val4 = Vector3.Cross(val2, Vector3.up); if (((Vector3)(ref val4)).sqrMagnitude < 1E-08f) { val4 = Vector3.Cross(val2, Vector3.forward); } } ((Vector3)(ref val4)).Normalize(); float num6 = (num * num - num2 * num2 + num5 * num5) / (2f * num5); float num7 = Mathf.Sqrt(Mathf.Max(0f, num * num - num6 * num6)); Vector3 val5 = position + val2 * num6 + val4 * num7; Vector3 val6 = position + val2 * num5; Vector3 val7 = position2 - position; if (((Vector3)(ref val7)).sqrMagnitude > 1E-08f) { upper.rotation = Quaternion.FromToRotation(val7, val5 - position) * upper.rotation; } Vector3 val8 = hand.position - lower.position; Vector3 val9 = val6 - val5; if (((Vector3)(ref val8)).sqrMagnitude > 1E-08f && ((Vector3)(ref val9)).sqrMagnitude > 1E-08f) { lower.rotation = Quaternion.FromToRotation(val8, val9) * lower.rotation; } Quaternion rotation3 = upper.rotation; Quaternion rotation4 = lower.rotation; upper.rotation = rotation; lower.rotation = rotation2; upper.rotation = Quaternion.Slerp(rotation, rotation3, weight); lower.rotation = Quaternion.Slerp(rotation2, rotation4, weight); return true; } private static void ResolveBodyArmBones(PlayerControllerB player) { if (_mantleBodyArmBonesResolved) { return; } _mantleBodyArmBonesResolved = true; if ((Object)(object)player == (Object)null) { return; } Transform val = null; Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); foreach (Transform val2 in componentsInChildren) { if (string.Equals(((Object)val2).name, "metarig", StringComparison.Ordinal) && (Object)(object)val2.parent != (Object)null && string.Equals(((Object)val2.parent).name, "ScavengerModel", StringComparison.Ordinal)) { val = val2; break; } } if (!((Object)(object)val == (Object)null)) { _bodyArmUpperL = FindDeep(val, "arm.L_upper"); _bodyArmLowerL = FindDeep(val, "arm.L_lower"); _bodyHandL = FindDeep(val, "hand.L"); _bodyArmUpperR = FindDeep(val, "arm.R_upper"); _bodyArmLowerR = FindDeep(val, "arm.R_lower"); _bodyHandR = FindDeep(val, "hand.R"); } } private static void CullMantleViewOccluders(PlayerControllerB player) { //IL_0035: 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_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_00c0: Unknown result type (might be due to invalid IL or missing references) RestoreMantleViewOccluders(); if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return; } ResolveMantleFpArmRenderers(player); Camera gameplayCamera = player.gameplayCamera; int cullingMask = gameplayCamera.cullingMask; Vector3 position = ((Component)gameplayCamera).transform.position; float num = 0.1024f; Renderer[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || !val.enabled || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } int layer = ((Component)val).gameObject.layer; if (layer < 0 || layer >= 32 || (cullingMask & (1 << layer)) == 0 || IsMantleFpArmRenderer(val)) { continue; } Bounds bounds = val.bounds; float num2 = ((Bounds)(ref bounds)).SqrDistance(position); if (num2 > num) { continue; } val.forceRenderingOff = true; _mantleTempCulled.Add(val); if (_mantleOccluderLogged.Add(((Object)val).name)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Panic Slide] Mantle FP occluder culled: '{((Object)val).name}' (layer={layer}, dist={Mathf.Sqrt(num2):F2})"); } } } } private static void RestoreMantleViewOccluders() { for (int i = 0; i < _mantleTempCulled.Count; i++) { if ((Object)(object)_mantleTempCulled[i] != (Object)null) { _mantleTempCulled[i].forceRenderingOff = false; } } _mantleTempCulled.Clear(); } private static bool IsMantleFpArmRenderer(Renderer renderer) { for (int i = 0; i < _mantleFpArmRenderers.Length; i++) { if (_mantleFpArmRenderers[i] == renderer) { return true; } } return false; } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } if (string.Equals(((Object)root).name, name, StringComparison.Ordinal)) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindDeep(root.GetChild(i), name); if ((Object)(object)val != (Object)null) { return val; } } return null; } internal static bool IsDebugThirdPersonCamActive() { if (!_debugThirdPersonResolved) { _debugThirdPersonResolved = true; try { Type type = Type.GetType("Y4NGZDebugTools.DebugGUI, Y4NGZDebugTools", throwOnError: false); if (type == null) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { try { type = assemblies[i].GetType("Y4NGZDebugTools.DebugGUI", throwOnError: false); } catch { type = null; } if (type != null) { break; } } } if (type != null) { _debugThirdPersonField = type.GetField("ThirdPersonCam", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); _debugStaticCamField = type.GetField("StaticCamActive", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); if (_debugThirdPersonField == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Panic Slide] Y4NGZDebugTools.DebugGUI is loaded but its ThirdPersonCam field could not be resolved; the debug third-person camera gate is disabled."); } } if (_debugStaticCamField == null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"[Panic Slide] Y4NGZDebugTools.DebugGUI is loaded but its StaticCamActive field could not be resolved; the frozen-camera gate is disabled."); } } } } catch (Exception ex) { _debugThirdPersonField = null; ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Panic Slide] failed to resolve Y4NGZDebugTools.DebugGUI.ThirdPersonCam: " + ex.Message)); } } } try { bool flag = default(bool); int num; if (_debugThirdPersonField != null) { object value = _debugThirdPersonField.GetValue(null); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } bool flag2 = default(bool); int num2; if (_debugStaticCamField != null) { object value = _debugStaticCamField.GetValue(null); if (value is bool) { flag2 = (bool)value; num2 = 1; } else { num2 = 0; } } else { num2 = 0; } return (byte)((uint)num2 & (flag2 ? 1u : 0u)) != 0; } catch { return false; } } private static void AddRenderersUnder(Transform root, List renderers) { if (!((Object)(object)root == (Object)null)) { Renderer[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { AddRenderer(componentsInChildren[i], renderers); } } } private static void LogMantleOccluderDumpOnce(PlayerControllerB player) { //IL_0037: 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_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) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (_mantleOccluderDumpDone || (Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return; } _mantleOccluderDumpDone = true; try { Camera gameplayCamera = player.gameplayCamera; int cullingMask = gameplayCamera.cullingMask; Vector3 position = ((Component)gameplayCamera).transform.position; List list = new List(); Renderer[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val == (Object)null || !val.enabled || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } int layer = ((Component)val).gameObject.layer; if (layer >= 0 && layer < 32 && (cullingMask & (1 << layer)) != 0) { Bounds bounds = val.bounds; float num = Vector3.Distance(((Bounds)(ref bounds)).center, position); if (!(num > 1.2f)) { list.Add($"'{((Object)val).name}'(layer={layer}, dist={num:F2})"); } } } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide] Mantle occluder dump (renderers drawn by gameplay camera within 1.2m): " + ((list.Count == 0) ? "" : string.Join(", ", list.ToArray())))); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Panic Slide] Mantle occluder dump failed: " + ex.Message)); } } } private static void FinishMantle() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB mantlePlayer = _mantlePlayer; if ((Object)(object)mantlePlayer != (Object)null) { SendMantleStop(mantlePlayer.playerClientId); SetPlayerPosition(mantlePlayer, _mantleEndPosition); ZeroMovementForces(mantlePlayer); ZeroFallValues(mantlePlayer); SlideAnimationBridge.End(mantlePlayer, "mantle-finished"); } RestoreMantleState(); _cooldownEnd = Time.time + 0.8f; } private static void AbortMantle(string reason) { //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_0045: Unknown result type (might be due to invalid IL or missing references) if (_mantleActive) { PlayerControllerB mantlePlayer = _mantlePlayer; if ((Object)(object)mantlePlayer != (Object)null) { SendMantleStop(mantlePlayer.playerClientId); } if ((Object)(object)mantlePlayer != (Object)null && !mantlePlayer.isPlayerDead && _mantleLastSafePosition != Vector3.zero) { SetPlayerPosition(mantlePlayer, _mantleLastSafePosition); } if ((Object)(object)mantlePlayer != (Object)null && _mantleAnimStarted) { SlideAnimationBridge.TriggerExit(mantlePlayer); SlideAnimationBridge.End(mantlePlayer, reason); } RestoreMantleState(); _nextRetryTime = Time.time + 0.05f; } } private static void RestoreMantleState() { //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_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_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB mantlePlayer = _mantlePlayer; RestoreInput(mantlePlayer); if ((Object)(object)mantlePlayer != (Object)null) { ZeroMovementForces(mantlePlayer); ZeroFallValues(mantlePlayer); } RestoreLocalMantleBody(); SetMantleFirstPersonArmsHidden(mantlePlayer, hidden: false); _mantleFpArmRenderersResolved = false; _mantleFpArmRenderers = Array.Empty(); _mantleFpArmsHidden = false; RestoreMantleViewOccluders(); _mantleOccluderLogged.Clear(); _mantleBodyArmBonesResolved = false; _bodyArmUpperL = (_bodyArmLowerL = (_bodyHandL = null)); _bodyArmUpperR = (_bodyArmLowerR = (_bodyHandR = null)); _mantleFpArmBonesResolved = false; _fpArmUpperL = (_fpArmLowerL = (_fpHandL = null)); _fpArmUpperR = (_fpArmLowerR = (_fpHandR = null)); PanicSlidePatch.RestoreCameraOffset(); PanicSlidePatch.EndFirstPersonMovementPresentation(); PanicSlidePatch.EndMovementLookLimit(mantlePlayer); UnsubscribeMantleRenderTruth(); _mantleActive = false; _mantlePlayer = null; _mantleStartPosition = Vector3.zero; _mantleLiftPosition = Vector3.zero; _mantleEndPosition = Vector3.zero; _mantleLastSafePosition = Vector3.zero; _mantleStartedAt = 0f; _mantleDuration = 0f; _mantleAnimStarted = false; _nextMantleArmsDiagnosticAt = 0f; } private static void SaveAndLockInput(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { if (!_mantleInputSaved) { _savedDisableMoveInput = player.disableMoveInput; _mantleInputSaved = true; } player.disableMoveInput = true; } } private static void RestoreInput(PlayerControllerB player) { if (_mantleInputSaved && (Object)(object)player != (Object)null) { player.disableMoveInput = _savedDisableMoveInput; } _savedDisableMoveInput = false; _mantleInputSaved = false; } private static void SetPlayerPosition(PlayerControllerB player, Vector3 position) { //IL_0020: 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) if ((Object)(object)player == (Object)null) { return; } CharacterController thisController = player.thisController; if ((Object)(object)thisController == (Object)null) { ((Component)player).transform.position = position; return; } bool enabled = ((Collider)thisController).enabled; if (enabled) { ((Collider)thisController).enabled = false; } ((Component)player).transform.position = position; if (enabled) { ((Collider)thisController).enabled = true; } } private static void ApplyStaminaCost(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { player.sprintMeter = Mathf.Clamp01(player.sprintMeter - 0.08f); if ((Object)(object)player.sprintMeterUI != (Object)null) { player.sprintMeterUI.fillAmount = player.sprintMeter; } } } private static void ZeroMovementForces(PlayerControllerB player) { //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_002d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return; } player.externalForceAutoFade = Vector3.zero; ResolveExternalForcesField(); if (!(_externalForcesField != null)) { return; } try { _externalForcesField.SetValue(player, Vector3.zero); } catch { } } private static void ZeroFallValues(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } ResolveFallFields(); try { if (_fallValueField != null) { _fallValueField.SetValue(player, 0f); } if (_fallValueUncappedField != null) { _fallValueUncappedField.SetValue(player, 0f); } } catch { } } private static float CalculateMantleCameraEnvelope() { if (!_mantleActive || _mantleDuration <= 0.001f) { return 0f; } float num = Mathf.Clamp(Time.time - _mantleStartedAt, 0f, _mantleDuration); float num2 = Mathf.Clamp01(num / 0.12f); float num3 = Mathf.SmoothStep(0f, 1f, num2); float num4 = _mantleDuration * 0.9f; float num5 = Mathf.Max(0f, num4 - 0.18f); if (num <= num5) { return num3; } float num6 = Mathf.Max(0.0001f, num4 - num5); float num7 = Mathf.Clamp01((num - num5) / num6); return Mathf.Min(num3, 1f - Mathf.SmoothStep(0f, 1f, num7)); } private static bool HasDestinationClearance(CharacterController controller, Vector3 destinationFeet, int mask) { //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller == (Object)null) { return false; } float num = Mathf.Max(0.05f, controller.radius - 0.02f); float num2 = Mathf.Max(controller.height, num * 2f + 0.1f); Vector3 val = destinationFeet + Vector3.up * (num + 0.05f); Vector3 val2 = destinationFeet + Vector3.up * (num2 - num + 0.05f); return !Physics.CheckCapsule(val, val2, num, mask, (QueryTriggerInteraction)1); } private static bool HasSweptCapsuleClearance(CharacterController controller, Vector3 fromTransformPosition, Vector3 toTransformPosition, int mask) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0055: 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_0062: 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_007a: 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_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009b: 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) if ((Object)(object)controller == (Object)null) { return false; } Vector3 val = toTransformPosition - fromTransformPosition; float magnitude = ((Vector3)(ref val)).magnitude; if (magnitude <= 0.001f) { return true; } float num = Mathf.Max(0.05f, controller.radius - 0.08f); float num2 = Mathf.Max(controller.height, num * 2f + 0.1f); Vector3 val2 = fromTransformPosition + controller.center; Vector3 val3 = val2 + Vector3.down * (num2 * 0.5f - num); Vector3 val4 = val2 + Vector3.up * (num2 * 0.5f - num); RaycastHit val5 = default(RaycastHit); return !Physics.CapsuleCast(val3, val4, num, val / magnitude, ref val5, magnitude, mask, (QueryTriggerInteraction)1); } private static bool HasInteriorContainment(PlayerControllerB player, Vector3 destinationFeet, int mask) { //IL_0013: 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_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) if ((Object)(object)player == (Object)null || !player.isInsideFactory) { return true; } return Physics.Raycast(destinationFeet + Vector3.up * 0.15f, Vector3.up, 12f, mask, (QueryTriggerInteraction)1); } private static bool IsRejectedMantleSurface(Collider collider) { if ((Object)(object)collider == (Object)null) { return true; } if ((Object)(object)collider.attachedRigidbody != (Object)null || (Object)(object)((Component)collider).GetComponentInParent() != (Object)null) { return true; } if ((Object)(object)((Component)collider).GetComponentInParent() != (Object)null) { return true; } return false; } private static float ResolveFeetY(PlayerControllerB player, CharacterController controller) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0012: 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_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)controller != (Object)null) { Bounds bounds = ((Collider)controller).bounds; if (((Bounds)(ref bounds)).size.y > 0.01f) { return ((Bounds)(ref bounds)).min.y; } } if (!((Object)(object)player != (Object)null)) { return 0f; } return ((Component)player).transform.position.y; } private static Vector3 ResolveCameraForward(PlayerControllerB player) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((player != null) ? ((Component)player).transform : null)); Vector3 val2 = (((Object)(object)val != (Object)null) ? Vector3.ProjectOnPlane(val.forward, Vector3.up) : Vector3.zero); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f && (Object)(object)player != (Object)null) { val2 = Vector3.ProjectOnPlane(((Component)player).transform.forward, Vector3.up); } if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.forward; } return ((Vector3)(ref val2)).normalized; } private static bool HasMantleIntent(PlayerControllerB player, Vector3 forward, Vector3 wallNormal) { //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_0006: 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_000c: 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_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_00a7: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.ProjectOnPlane(forward, Vector3.up); Vector3 val2 = Vector3.ProjectOnPlane(wallNormal, Vector3.up); if (((Vector3)(ref val)).sqrMagnitude > 0.01f && ((Vector3)(ref val2)).sqrMagnitude > 0.01f && Vector3.Dot(((Vector3)(ref val)).normalized, -((Vector3)(ref val2)).normalized) > 0.35f) { return true; } if ((Object)(object)player == (Object)null || (Object)(object)player.thisController == (Object)null) { return false; } Vector3 velocity = player.thisController.velocity; velocity.y = 0f; if (((Vector3)(ref velocity)).sqrMagnitude < 0.0001f || ((Vector3)(ref val)).sqrMagnitude <= 0.01f) { return false; } return Vector3.Dot(velocity, ((Vector3)(ref val)).normalized) > 0.25f; } private static bool IsPlayerInVehicle(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } ResolveVehicleMembers(); try { bool flag = default(bool); for (int i = 0; i < _vehicleBoolFields.Length; i++) { object value = _vehicleBoolFields[i].GetValue(player); int num; if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) != 0) { return true; } } bool flag2 = default(bool); for (int j = 0; j < _vehicleBoolProperties.Length; j++) { object value = _vehicleBoolProperties[j].GetValue(player, null); int num2; if (value is bool) { flag2 = (bool)value; num2 = 1; } else { num2 = 0; } if (((uint)num2 & (flag2 ? 1u : 0u)) != 0) { return true; } } } catch { } return false; } private static void ResolveVehicleMembers() { if (_vehicleMembersResolved) { return; } _vehicleMembersResolved = true; string[] array = new string[4] { "inVehicleAnimation", "isInVehicle", "isInCruiser", "isDrivingVehicle" }; List list = new List(); List list2 = new List(); for (int i = 0; i < array.Length; i++) { FieldInfo field = typeof(PlayerControllerB).GetField(array[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { list.Add(field); } PropertyInfo property = typeof(PlayerControllerB).GetProperty(array[i], BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(bool)) { list2.Add(property); } } _vehicleBoolFields = list.ToArray(); _vehicleBoolProperties = list2.ToArray(); } private static void ResolveFallFields() { if (!_fallFieldsResolved) { _fallFieldsResolved = true; _fallValueField = FindFloatField("fallValue", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _fallValueUncappedField = FindFloatField("fallValueUncapped", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } private static void ResolveExternalForcesField() { if (!_externalForcesResolved) { _externalForcesResolved = true; FieldInfo field = typeof(PlayerControllerB).GetField("externalForces", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(Vector3)) { _externalForcesField = field; } } } private static FieldInfo FindFloatField(string name, BindingFlags flags) { FieldInfo field = typeof(PlayerControllerB).GetField(name, flags); if (!(field != null) || !(field.FieldType == typeof(float))) { return null; } return field; } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; RemoteMantles.Clear(); } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<1>__OnReceiveMantleStart; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveMantleStart; <>O.<1>__OnReceiveMantleStart = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZ_MantleStart", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<2>__OnReceiveMantleStop; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveMantleStop; <>O.<2>__OnReceiveMantleStop = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("Y4NGZ_MantleStop", (HandleNamedMessageDelegate)obj2); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("LedgeMantlePatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void SendMantleStart(ulong playerClientId, byte clipId, float sessionSeconds, Vector3 ledgeGripCenter, Vector3 wallNormal) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendMantleStart(playerClientId, clipId, sessionSeconds, ledgeGripCenter, wallNormal, includeExtension: true, null); } else { SendMantleStart(playerClientId, clipId, sessionSeconds, ledgeGripCenter, wallNormal, includeExtension: true, 0uL); } } } private static void SendMantleStart(ulong playerClientId, byte clipId, float sessionSeconds, Vector3 ledgeGripCenter, Vector3 wallNormal, bool includeExtension, ulong? clientId) { //IL_0037: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: 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_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_00d5: 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_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } int num = 9 + (includeExtension ? 28 : 0); FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(num, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerClientId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref clipId, default(ForPrimitives)); if (includeExtension) { ((FastBufferWriter)(ref val)).WriteValueSafe(ref sessionSeconds, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref ledgeGripCenter.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref ledgeGripCenter.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref ledgeGripCenter.z, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref wallNormal.x, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref wallNormal.y, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref wallNormal.z, default(ForPrimitives)); } if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ_MantleStart", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ_MantleStart", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void SendMantleStop(ulong playerClientId) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendMantleStop(playerClientId, null); } else { SendMantleStop(playerClientId, 0uL); } } } private static void SendMantleStop(ulong playerClientId, ulong? clientId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerClientId, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ_MantleStop", clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ_MantleStop", val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveMantleStart(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_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_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_005e: 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_0076: 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_008e: 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_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_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_00d6: 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_00ee: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); byte clipId = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref clipId, default(ForPrimitives)); float sessionSeconds = 0f; Vector3 zero = Vector3.zero; Vector3 zero2 = Vector3.zero; bool flag = ((FastBufferReader)(ref reader)).Length - ((FastBufferReader)(ref reader)).Position >= 28; if (flag) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref sessionSeconds, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero.x, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero.y, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero.z, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero2.x, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero2.y, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref zero2.z, default(ForPrimitives)); } ApplyRemoteMantleStart(playerClientId, clipId, sessionSeconds, zero, zero2, flag); RelayMantleStartIfHost(senderClientId, playerClientId, clipId, sessionSeconds, zero, zero2, flag); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("LedgeMantlePatch: malformed mantle start message: " + ex.Message)); } } } private static void OnReceiveMantleStop(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); ApplyRemoteMantleStop(playerClientId); RelayMantleStopIfHost(senderClientId, playerClientId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("LedgeMantlePatch: malformed mantle stop message: " + ex.Message)); } } } private static void RelayMantleStartIfHost(ulong senderClientId, ulong playerClientId, byte clipId, float sessionSeconds, Vector3 ledgeGripCenter, Vector3 wallNormal, bool hasExtension) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendMantleStart(playerClientId, clipId, sessionSeconds, ledgeGripCenter, wallNormal, hasExtension, null); } } private static void RelayMantleStopIfHost(ulong senderClientId, ulong playerClientId) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendMantleStop(playerClientId, null); } } private static void ApplyRemoteMantleStart(ulong playerClientId, byte clipId, float sessionSeconds, Vector3 ledgeGripCenter, Vector3 wallNormal, bool hasExtension) { //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01b2: Unknown result type (might be due to invalid IL or missing references) bool flag = clipId != 0; bool flag2 = hasExtension && !float.IsNaN(sessionSeconds) && !float.IsInfinity(sessionSeconds) && sessionSeconds > 0.001f; float num = SlideAnimationBridge.ResolveMantleSessionSeconds(flag, flag2 ? sessionSeconds : 0f); bool flag3 = Plugin.RemoteMantleBodyGrabIk?.Value ?? true; PlayerControllerB val = ResolvePlayer(playerClientId); if ((Object)(object)val == (Object)null || IsLocalPlayer(val)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-mantle] start_gate: " + $"playerClientId={playerClientId} tall={flag} bridgeStarted=False " + "payload='" + (hasExtension ? "extended" : "legacy") + "' durationSource='" + (flag2 ? "received" : "fallback") + "' " + $"duration={num:0.######} " + $"bodyGrabConfigured={flag3} bodyGrabEnabled=False " + "reason='" + (((Object)(object)val == (Object)null) ? "player_missing" : "local_player") + "'.")); } return; } bool flag4 = SlideAnimationBridge.BeginMantle(val, flag, num); bool flag5 = flag4 && flag3 && hasExtension && ((Vector3)(ref wallNormal)).sqrMagnitude > 0.0001f; string text = ((!flag4) ? "bridge_start_failed" : ((!flag3) ? "config_disabled" : ((!hasExtension) ? "legacy_payload" : ((((Vector3)(ref wallNormal)).sqrMagnitude <= 0.0001f) ? "wall_normal_invalid" : "ready")))); RemoteMantles.Remove(playerClientId); if (flag5) { RemoteMantles[playerClientId] = new RemoteMantlePresentation(val, num, ledgeGripCenter, ((Vector3)(ref wallNormal)).normalized); } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide.remote-mantle] start_gate: " + $"playerClientId={playerClientId} tall={flag} bridgeStarted={flag4} " + "payload='" + (hasExtension ? "extended" : "legacy") + "' durationSource='" + (flag2 ? "received" : "fallback") + "' " + $"duration={num:0.######} " + $"bodyGrabConfigured={flag3} bodyGrabEnabled={flag5} " + "bodyGrabReason='" + text + "'.")); } } private static void ApplyRemoteMantleStop(ulong playerClientId) { bool flag = RemoteMantles.Remove(playerClientId); if (flag) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-mantle] body_grab_end_gate: " + $"playerClientId={playerClientId} reason='stop_received'.")); } } PlayerControllerB val = ResolvePlayer(playerClientId); bool flag2 = (Object)(object)val != (Object)null && !IsLocalPlayer(val); if (flag2) { SlideAnimationBridge.End(val, "remote-mantle-stop"); } ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide.remote-mantle] stop_gate: " + $"playerClientId={playerClientId} bridgeEnded={flag2} " + $"bodyGrabPresentationRemoved={flag}.")); } } private static void ClearRemoteMantlePresentations(string reason) { int count = RemoteMantles.Count; RemoteMantles.Clear(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-mantle] body_grab_clear_gate: " + $"cleared={count} reason='{reason}'.")); } } private static PlayerControllerB ResolvePlayer(ulong playerClientId) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null) { return null; } for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if ((Object)(object)val != (Object)null && val.playerClientId == playerClientId) { return val; } } return null; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } [HarmonyPatch] internal static class MaskedPatch { private static bool LocalPlayerIsInvisibleToMasked() { return false; } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForClosestPlayer")] private static void PreventMaskedTargeting(EnemyAI __instance, ref PlayerControllerB __result) { try { if (__instance is MaskedPlayerEnemy && (Object)(object)__result != (Object)null && (Object)(object)__result == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedTargeting failed: {arg}"); } } [HarmonyPostfix] [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] private static void PreventMaskedProximityTarget(EnemyAI __instance, ref PlayerControllerB __result) { try { if (__instance is MaskedPlayerEnemy && (Object)(object)__result != (Object)null && (Object)(object)__result == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedProximityTarget failed: {arg}"); } } [HarmonyPrefix] [HarmonyPatch(typeof(MaskedPlayerEnemy), "OnCollideWithPlayer")] private static bool PreventMaskedKill(Collider other) { try { PlayerControllerB component = ((Component)other).gameObject.GetComponent(); if ((Object)(object)component != (Object)null && (Object)(object)component == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.PreventMaskedKill failed: {arg}"); } return true; } [HarmonyPostfix] [HarmonyPatch(typeof(MaskedPlayerEnemy), "DoAIInterval")] private static void ClearMaskedTarget(MaskedPlayerEnemy __instance) { try { if ((Object)(object)((EnemyAI)__instance).targetPlayer != (Object)null && (Object)(object)((EnemyAI)__instance).targetPlayer == (Object)(object)GameNetworkManager.Instance.localPlayerController && LocalPlayerIsInvisibleToMasked()) { ((EnemyAI)__instance).targetPlayer = null; ((EnemyAI)__instance).movingTowardsTargetPlayer = false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"MaskedPatch.ClearMaskedTarget failed: {arg}"); } } } [HarmonyPatch] internal static class MergedUpgradePatches { private sealed class AppliedBonuses { internal float MovementSpeed; internal float SprintTime; internal float JumpForce; internal float GrabDistance; internal float ClimbSpeed; internal float SlopeModifierSpeed; internal float SlopeIntensity; internal float SinkingSpeed; internal float ExtraRegenTimer; internal int MaxHealth = 100; } private const string PhysicalConditioning = "Sprinter"; private const string QuickHands = "Quick Hands"; private const string ThickSkin = "Resilience"; private const float MovementSpeedBonus = 1.4f; private const float SprintTimeBonus = 6f; private const float StaminaRegenMultiplier = 1.05f; private const float JumpForceBonus = 3f; private const float JumpForceFinalBonus = 0.75f; private const float FootstepNoiseReduction = 10f; private const float SinkingPenaltyReduction = 0.2f; private const float TractionIncrease = 0.25f; private const float SlopePenaltyReduction = 0.25f; private const float CrouchPenaltyReduction = 0.2f; private const float FallDamageMultiplier = 0.75f; private const float GrabDistancePerTier = 1f; private const int GrabDistanceMaxTiers = 3; private const float InteractionSpeedPerTier = 0.1f; private const float ClimbSpeedPerTierMultiplier = 0.2f; private const int ClimbSpeedMaxTiers = 3; private const int HealthPerTier = 20; private const int BonusRegenAmount = 1; private const float RegenCapIncrease = 0.5f; private const int VanillaMaxHealth = 100; private const int VanillaRegenCap = 20; private static readonly Dictionary BonusesByPlayer = new Dictionary(); private static readonly Dictionary SpeedMultipliersBySource = new Dictionary(); internal static void SetSpeedMultiplier(string sourceId, float multiplier) { if (!string.IsNullOrEmpty(sourceId)) { if (multiplier <= 1f) { SpeedMultipliersBySource.Remove(sourceId); } else { SpeedMultipliersBySource[sourceId] = multiplier; } } } internal static void ClearSpeedMultiplier(string sourceId) { if (!string.IsNullOrEmpty(sourceId)) { SpeedMultipliersBySource.Remove(sourceId); } } private static float GetExternalSpeedMultiplier() { if (SpeedMultipliersBySource.Count == 0) { return 1f; } float num = 1f; foreach (float value in SpeedMultipliersBySource.Values) { num *= value; } return num; } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PlayerLateUpdatePostfix(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { AppliedBonuses bonuses = GetBonuses(__instance); ApplyStatBonuses(__instance, bonuses); ApplyHealthCap(__instance, bonuses); TickBonusStaminaRegen(__instance); TickBonusHealthRegen(__instance, bonuses); } } private static void ApplyStatBonuses(PlayerControllerB player, AppliedBonuses bonuses) { int num = Tier("Sprinter"); int num2 = Tier("Quick Hands"); float num3 = player.movementSpeed - bonuses.MovementSpeed; float num4 = ((num >= 1) ? 1.4f : 0f); if (num >= 4 && player.isCrouching) { num4 += Mathf.Max(0f, num3) * GetCrouchSpeedBonusMultiplier(); } float externalSpeedMultiplier = GetExternalSpeedMultiplier(); if (externalSpeedMultiplier > 1f) { float num5 = Mathf.Max(0f, num3 + num4); num4 += num5 * (externalSpeedMultiplier - 1f); } player.movementSpeed = Mathf.Max(0.1f, num3 + num4); bonuses.MovementSpeed = num4; float num6 = player.sprintTime - bonuses.SprintTime; float num7 = ((num >= 2) ? 6f : 0f); player.sprintTime = Mathf.Max(0.1f, num6 + num7); bonuses.SprintTime = num7; float num8 = player.jumpForce - bonuses.JumpForce; float num9 = 0f; if (num >= 3) { num9 += 3f; } if (num >= 4) { num9 += 0.75f; } player.jumpForce = Mathf.Max(0.1f, num8 + num9); bonuses.JumpForce = num9; float num10 = player.grabDistance - bonuses.GrabDistance; float num11 = (float)Mathf.Min(num2, 3) * 1f; player.grabDistance = Mathf.Max(1f, num10 + num11); bonuses.GrabDistance = num11; float num12 = player.climbSpeed - bonuses.ClimbSpeed; float num13 = ((num > 0) ? (Mathf.Max(0f, num12) * (float)Mathf.Min(num, 3) * 0.2f) : 0f); player.climbSpeed = Mathf.Max(0.1f, num12 + num13); bonuses.ClimbSpeed = num13; float num14 = player.slopeModifierSpeed - bonuses.SlopeModifierSpeed; float num15 = ((num >= 2) ? (Mathf.Max(0f, num14) * 0.25f) : 0f); player.slopeModifierSpeed = Mathf.Max(0.01f, num14 + num15); bonuses.SlopeModifierSpeed = num15; float num16 = player.slopeIntensity - bonuses.SlopeIntensity; float num17 = ((num >= 3) ? ((0f - Mathf.Max(0f, num16)) * 0.25f) : 0f); player.slopeIntensity = Mathf.Max(0f, num16 + num17); bonuses.SlopeIntensity = num17; float num18 = player.sinkingSpeedMultiplier - bonuses.SinkingSpeed; float num19 = ((num >= 1 && player.isSinking) ? ((0f - Mathf.Max(0f, num18)) * 0.2f) : 0f); player.sinkingSpeedMultiplier = Mathf.Max(0f, num18 + num19); bonuses.SinkingSpeed = num19; } private static float GetCrouchSpeedBonusMultiplier() { float num = 2f / 3f; return (num + (1f - num) * 0.2f) / num - 1f; } private static void TickBonusStaminaRegen(PlayerControllerB player) { if (Tier("Sprinter") >= 2 && !player.isSprinting && player.isMovementHindered <= 0 && !(player.sprintMeter >= 1f)) { float num = Time.deltaTime / Mathf.Max(0.1f, player.sprintTime + (player.isWalking ? 9f : 4f)); player.sprintMeter = Mathf.Clamp01(player.sprintMeter + num * 0.049999952f); if ((Object)(object)player.sprintMeterUI != (Object)null) { player.sprintMeterUI.fillAmount = player.sprintMeter; } } } private static void ApplyHealthCap(PlayerControllerB player, AppliedBonuses bonuses) { int maxHealth = GetMaxHealth(); if (maxHealth <= 100) { bonuses.MaxHealth = 100; return; } if (bonuses.MaxHealth != maxHealth) { int num = Mathf.Max(100, bonuses.MaxHealth); if (player.health >= Mathf.Min(100, num)) { player.health = maxHealth; UpdateHealthUi(player); } bonuses.MaxHealth = maxHealth; } if (player.health > maxHealth) { player.health = maxHealth; UpdateHealthUi(player); } } private static void TickBonusHealthRegen(PlayerControllerB player, AppliedBonuses bonuses) { int num = Tier("Resilience"); if (num <= 0 || player.isPlayerDead) { return; } int num2 = ((num >= 2) ? Mathf.RoundToInt(30f) : 20); num2 = Mathf.Min(num2, GetMaxHealth()); if (player.health >= num2) { return; } bonuses.ExtraRegenTimer -= Time.deltaTime; if (!(bonuses.ExtraRegenTimer > 0f)) { bonuses.ExtraRegenTimer = 1f; int num3 = ((player.health < 20) ? 1 : 1); player.health = Mathf.Min(player.health + num3, num2); if (player.health >= 20 && player.criticallyInjured) { player.MakeCriticallyInjured(false); } UpdateHealthUi(player); } } private static int GetMaxHealth() { int num = Tier("Resilience"); if (num > 0) { return 100 + num * 20; } return 100; } private static AppliedBonuses GetBonuses(PlayerControllerB player) { ulong playerClientId = player.playerClientId; if (!BonusesByPlayer.TryGetValue(playerClientId, out var value)) { value = new AppliedBonuses(); BonusesByPlayer[playerClientId] = value; } return value; } private static int Tier(string upgradeName) { return Mathf.Max(0, Y4NGZUpgradeManager.GetLevel(upgradeName)); } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void UpdateHealthUi(PlayerControllerB player) { HUDManager instance = HUDManager.Instance; if (!((Object)(object)instance == (Object)null)) { instance.SetCracksOnVisor((float)Mathf.Min(player.health, 100)); instance.UpdateHealthUI(player.health, false); } } [HarmonyPatch(typeof(HUDManager), "HoldInteractionFill")] [HarmonyPrefix] private static void HoldInteractionFillPrefix(ref float speedMultiplier) { int num = Tier("Quick Hands"); if (num > 0) { speedMultiplier *= 1f + (float)num * 0.1f; } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPrefix] private static void DamagePlayerPrefix(PlayerControllerB __instance, ref int damageNumber, CauseOfDeath causeOfDeath, bool fallDamage) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Invalid comparison between Unknown and I4 if (IsLocalPlayer(__instance) && Tier("Sprinter") >= 5 && (fallDamage || (int)causeOfDeath == 2)) { damageNumber = Mathf.Max(0, Mathf.RoundToInt((float)damageNumber * 0.75f)); } } [HarmonyPatch(typeof(RoundManager), "PlayAudibleNoise")] [HarmonyPrefix] private static void PlayAudibleNoisePrefix(Vector3 noisePosition, ref float noiseRange, int noiseID = 0) { //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) if (noiseID == 6 && Tier("Sprinter") >= 4) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null) && !(Vector3.Distance(((Component)val).transform.position, noisePosition) > 2.5f)) { noiseRange = Mathf.Max(0f, noiseRange - 10f); } } } [HarmonyPatch(typeof(StartOfRound), "ReviveDeadPlayers")] [HarmonyPostfix] private static void ReviveDeadPlayersPostfix() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { AppliedBonuses bonuses = GetBonuses(val); bonuses.MaxHealth = 100; ApplyHealthCap(val, bonuses); } } [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] [HarmonyPostfix] private static void ShipLeavePostfix() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val == (Object)null)) { GetBonuses(val).ExtraRegenTimer = 0f; } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void DisconnectPostfix() { BonusesByPlayer.Clear(); SpeedMultipliersBySource.Clear(); } } internal enum NativeFistPhase : byte { Inactive, Equipping, Idle, Punching, Unequipping } internal enum NativeFistHand : byte { None, Left, Right } internal enum NativeFistHitKind : byte { Miss, Surface, Enemy, ClingingEnemy, Player } internal sealed class NativeFistSessionModel { internal const double EquipPlaybackSpeed = 2.0; internal const double PunchPlaybackSpeed = 1.8; internal const double UnequipPlaybackSpeed = 2.0; internal const double EquipSeconds = 11.0 / 30.0; internal const double InitialPunchLeadSeconds = 0.1; internal const double PunchContactSeconds = 11.0 / 54.0; internal const double InitialPunchContactSeconds = 41.0 / 135.0; internal const double PunchCadenceSeconds = 0.75; internal const double InactivitySeconds = 3.0; internal const double UnequipSeconds = 5.0 / 12.0; private bool hasStateSequence; private bool hasPunchSequence; private uint lastStateSequence; private uint lastPunchSequence; internal NativeFistPhase Phase { get; private set; } internal NativeFistHand NextHand { get; private set; } = NativeFistHand.Left; internal NativeFistHand ActiveHand { get; private set; } internal uint LastStateSequence => lastStateSequence; internal uint LastPunchSequence => lastPunchSequence; internal uint QueuedPunchSequence { get; private set; } internal bool HasQueuedPunch { get; private set; } internal double LastAcceptedPunchAt { get; private set; } = double.NegativeInfinity; internal double NextPunchAllowedAt { get; private set; } = double.NegativeInfinity; internal int Generation { get; private set; } internal bool TrySetActive(uint sequence, bool desiredActive) { if (!AcceptSequence(sequence, ref hasStateSequence, ref lastStateSequence)) { return false; } if (!desiredActive) { Interrupt(); return true; } if (Phase != NativeFistPhase.Inactive) { return false; } Phase = NativeFistPhase.Equipping; ActiveHand = NativeFistHand.None; HasQueuedPunch = false; QueuedPunchSequence = 0u; Generation++; return true; } internal bool TryQueueOrStartPunch(uint sequence, double now, out NativeFistHand hand) { hand = NativeFistHand.None; if (!AcceptSequence(sequence, ref hasPunchSequence, ref lastPunchSequence)) { return false; } if (Phase == NativeFistPhase.Equipping) { if (HasQueuedPunch) { return false; } HasQueuedPunch = true; QueuedPunchSequence = sequence; LastAcceptedPunchAt = now; return true; } if (Phase != NativeFistPhase.Idle || now + 1E-06 < NextPunchAllowedAt) { return false; } hand = BeginPunch(now, updateAcceptedInputTime: true); return true; } internal bool FinishEquip(double now, out uint punchSequence, out NativeFistHand hand) { punchSequence = 0u; hand = NativeFistHand.None; if (Phase != NativeFistPhase.Equipping) { return false; } Phase = NativeFistPhase.Idle; if (!HasQueuedPunch) { return true; } HasQueuedPunch = false; punchSequence = QueuedPunchSequence; QueuedPunchSequence = 0u; hand = BeginPunch(now, updateAcceptedInputTime: false); return true; } internal bool FinishPunch() { if (Phase != NativeFistPhase.Punching) { return false; } Phase = NativeFistPhase.Idle; ActiveHand = NativeFistHand.None; return true; } internal bool ShouldBeginUnequip(double now) { if (Phase == NativeFistPhase.Idle) { return now - LastAcceptedPunchAt + 1E-06 >= 3.0; } return false; } internal bool BeginUnequip() { if (Phase == NativeFistPhase.Inactive || Phase == NativeFistPhase.Unequipping) { return false; } Phase = NativeFistPhase.Unequipping; ActiveHand = NativeFistHand.None; HasQueuedPunch = false; QueuedPunchSequence = 0u; Generation++; return true; } internal bool TryBeginUnequip(uint sequence) { if (!AcceptSequence(sequence, ref hasStateSequence, ref lastStateSequence)) { return false; } return BeginUnequip(); } internal void FinishUnequip() { if (Phase == NativeFistPhase.Unequipping) { ResetState(); } } internal void Interrupt() { Generation++; ResetState(); } private NativeFistHand BeginPunch(double now, bool updateAcceptedInputTime) { NativeFistHand nextHand = NextHand; NextHand = ((nextHand != NativeFistHand.Left) ? NativeFistHand.Left : NativeFistHand.Right); ActiveHand = nextHand; Phase = NativeFistPhase.Punching; if (updateAcceptedInputTime) { LastAcceptedPunchAt = now; } NextPunchAllowedAt = now + 0.75; Generation++; return nextHand; } private void ResetState() { Phase = NativeFistPhase.Inactive; NextHand = NativeFistHand.Left; ActiveHand = NativeFistHand.None; HasQueuedPunch = false; QueuedPunchSequence = 0u; LastAcceptedPunchAt = double.NegativeInfinity; NextPunchAllowedAt = double.NegativeInfinity; } private static bool AcceptSequence(uint candidate, ref bool hasValue, ref uint last) { if (hasValue && (int)(candidate - last) <= 0) { return false; } hasValue = true; last = candidate; return true; } } internal sealed class NativeFistFractionalDamage { private readonly Dictionary remainderByTarget = new Dictionary(); internal int Add(TKey target, float shovelUnits) { if (target == null || shovelUnits <= 0f || float.IsNaN(shovelUnits) || float.IsInfinity(shovelUnits)) { return 0; } remainderByTarget.TryGetValue(target, out var value); float num = value + shovelUnits; int num2 = (int)Math.Floor(num + 1E-05f); float num3 = num - (float)num2; if (num3 <= 1E-05f) { remainderByTarget.Remove(target); } else { remainderByTarget[target] = num3; } return num2; } internal void Remove(TKey target) { if (target != null) { remainderByTarget.Remove(target); } } internal void Clear() { remainderByTarget.Clear(); } } [HarmonyPatch] internal static class NativeFistsPatch { private sealed class ServerSession { internal readonly NativeFistSessionModel Model = new NativeFistSessionModel(); internal Vector3 QueuedOrigin; internal Vector3 QueuedForward; internal uint ActivePunchSequence; } private sealed class PresentationSession { internal InteractionAnimationHandle Handle = InteractionAnimationHandle.Empty; internal NativeFistPhase Phase; internal bool HasPunchSequence; internal uint LastPunchSequence; internal bool HasNearWall; internal bool NearWall; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnStateRequest; public static HandleNamedMessageDelegate <1>__OnSprintExitRequest; public static HandleNamedMessageDelegate <2>__OnPunchRequest; public static HandleNamedMessageDelegate <3>__OnEvent; public static HandleNamedMessageDelegate <4>__OnImpact; public static HandleNamedMessageDelegate <5>__OnSnapshot; public static Action <6>__OnClientConnected; public static Action <7>__OnClientDisconnected; } private const string StateRequestMessage = "Y4NGZ.NativeFists.StateRequest.v1"; private const string SprintExitRequestMessage = "Y4NGZ.NativeFists.SprintExitRequest.v1"; private const string PunchRequestMessage = "Y4NGZ.NativeFists.PunchRequest.v1"; private const string EventMessage = "Y4NGZ.NativeFists.Event.v1"; private const string ImpactMessage = "Y4NGZ.NativeFists.Impact.v1"; private const string SnapshotMessage = "Y4NGZ.NativeFists.Snapshot.v1"; private const string PackId = "y4ngz.upgrades.native-fists"; private const string FirstPersonInteractionId = "y4ngz.native-fists.firstperson"; private const string ThirdPersonInteractionId = "y4ngz.native-fists.thirdperson"; private const string FirstPersonManifestFile = "y4ngz-upgrades-fists-firstperson.manifest.json"; private const string ThirdPersonManifestFile = "y4ngz-upgrades-fists-thirdperson.manifest.json"; private const string EnterTrigger = "Y4NGZ_Fists_Enter"; private const string PunchLeftTrigger = "PunchLeft"; private const string PunchRightTrigger = "PunchRight"; private const string SyncIdleTrigger = "SyncIdle"; private const string NearWallBool = "FistsNearWall"; private const string UpperBodyLayer = "UpperBodyEmotes"; private const float NearWallEnterWeight = 0.08f; private const float NearWallExitWeight = 0.02f; private const float RangeMeters = 1.2f; private const float SphereRadiusMeters = 0.8f; private const int CollisionMask = 11012424; private const int PlayerDamage = 10; private const float EnemyStunSeconds = 1f; private const float MaxAimOriginErrorMeters = 0.75f; private const float MinAimForwardDot = 0.25f; private const int FistNoiseId = 9011; private static readonly Dictionary ServerSessions = new Dictionary(); private static readonly Dictionary Presentations = new Dictionary(); private static readonly HashSet PendingSnapshotPlayers = new HashSet(); private static readonly NativeFistFractionalDamage FractionalEnemyDamage = new NativeFistFractionalDamage(); private static readonly FieldInfo NutcrackerIsInspectingField = AccessTools.Field(typeof(NutcrackerEnemyAI), "isInspecting"); private static readonly MethodInfo BushWolfHitTongueLocalClientMethod = AccessTools.Method(typeof(BushWolfEnemy), "HitTongueLocalClient", (Type[])null, (Type[])null); private static NetworkManager registeredNetworkManager; private static bool packRegistered; private static bool missingManifestLogged; private static float nextPackRegistrationAttemptAt; private static uint nextLocalSequence = 1u; private static NativeFistPhase localPhase = NativeFistPhase.Inactive; private static NativeFistHand localNextHand = NativeFistHand.Left; private static uint localActivePunchSequence; private static int localGeneration; private static float localNextPunchAllowedAt; private static AudioClip vanillaSwingClip; private static AudioClip[] vanillaHitClips; private static bool vanillaAudioResolved; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void ConnectClientToPlayerObjectPostfix() { RegisterNetworkHandlers(); EnsurePackRegistered(); } internal static void OnRoundStarted() { ResetRuntime(unregisterNetwork: false); RegisterNetworkHandlers(); EnsurePackRegistered(); } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void ResetShipPostfix() { ResetRuntime(unregisterNetwork: false); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void DisconnectPostfix() { ResetRuntime(unregisterNetwork: true); } [HarmonyPatch(typeof(PlayerControllerB), "ActivateItem_performed")] [HarmonyPrefix] private static bool ActivateItemPerformedPrefix(PlayerControllerB __instance, CallbackContext context) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return true; } if (!((CallbackContext)(ref context)).performed || !NativeFistsUpgrade.IsUnlocked()) { return true; } if (!CanUseFists(__instance, requireEmptyHands: true)) { return true; } try { RegisterNetworkHandlers(); EnsurePackRegistered(); if (localPhase == NativeFistPhase.Inactive) { uint sequence = NextLocalSequence(); uint sequence2 = NextLocalSequence(); localPhase = NativeFistPhase.Equipping; localNextHand = NativeFistHand.Right; localGeneration++; int generation = localGeneration; EnsurePresentation(__instance, directToIdle: false); FirePresentationTrigger(__instance.actualClientId, "Y4NGZ_Fists_Enter"); SendStateRequest(sequence, desiredActive: true); SendPunchRequest(sequence2, __instance); MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(PredictInitialPunch(sequence2, generation)); } return false; } if (localPhase != NativeFistPhase.Idle || Time.realtimeSinceStartup + 0.0001f < localNextPunchAllowedAt) { return false; } uint sequence3 = NextLocalSequence(); NativeFistHand nativeFistHand = localNextHand; localNextHand = ((nativeFistHand != NativeFistHand.Left) ? NativeFistHand.Left : NativeFistHand.Right); PresentPunch(__instance.actualClientId, sequence3, nativeFistHand); SendPunchRequest(sequence3, __instance); return false; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)("NativeFists: local activation failed: " + ex)); } InterruptLocal(sendRequest: true); return false; } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static bool BeginGrabObjectPrefix(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return true; } if (localPhase == NativeFistPhase.Punching) { return false; } if (localPhase != NativeFistPhase.Inactive) { InterruptLocal(sendRequest: true); } return true; } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PlayerLateUpdatePostfix(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return; } RetryPendingSnapshot(__instance); if ((Object)(object)__instance == (Object)(object)GameNetworkManager.Instance?.localPlayerController && localPhase != NativeFistPhase.Inactive) { if (__instance.isSprinting) { BeginLocalSprintExit(__instance); } else if (!CanUseFists(__instance, requireEmptyHands: true)) { InterruptLocal(sendRequest: true); } } UpdatePresentationParameters(__instance); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } ulong actualClientId = __instance.actualClientId; if (ServerSessions.TryGetValue(actualClientId, out var value) && value.Model.Phase != NativeFistPhase.Inactive) { if (__instance.isSprinting) { BeginServerUnequip(actualClientId, value); } else if (!CanUseFists(__instance, requireEmptyHands: true) || UpgradeTierSync.GetTier(actualClientId, "lethal_hands_training") <= 0) { InterruptServer(actualClientId, value); } else if (value.Model.ShouldBeginUnequip(NetworkTime())) { BeginServerUnequip(actualClientId, value); } } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void KillPlayerPostfix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { ulong actualClientId = __instance.actualClientId; if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && ServerSessions.TryGetValue(actualClientId, out var value)) { InterruptServer(actualClientId, value); } StopPresentation(actualClientId, immediate: true); if ((Object)(object)__instance == (Object)(object)GameNetworkManager.Instance?.localPlayerController) { ResetLocalState(); } } } private static IEnumerator PredictInitialPunch(uint sequence, int generation) { yield return (object)new WaitForSeconds(0.1f); if (generation == localGeneration && localPhase != NativeFistPhase.Inactive && localPhase != NativeFistPhase.Unequipping) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { PresentPunch(val.actualClientId, sequence, NativeFistHand.Left); } } } private static IEnumerator PredictPunchFinished(uint sequence, int generation) { yield return (object)new WaitForSeconds(0.75f); if (generation == localGeneration && localPhase == NativeFistPhase.Punching && localActivePunchSequence == sequence) { localPhase = NativeFistPhase.Idle; } } private static void RegisterNetworkHandlers() { //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //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_00fb: Expected O, but got Unknown //IL_007e: 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_0089: Expected O, but got Unknown //IL_0116: 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_0121: Expected O, but got Unknown //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) //IL_00af: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsListening || (Object)(object)registeredNetworkManager == (Object)(object)singleton) { return; } UnregisterNetworkHandlers(); try { if (singleton.IsServer) { object obj = <>O.<0>__OnStateRequest; if (obj == null) { HandleNamedMessageDelegate val2 = OnStateRequest; <>O.<0>__OnStateRequest = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.StateRequest.v1", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnSprintExitRequest; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnSprintExitRequest; <>O.<1>__OnSprintExitRequest = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.SprintExitRequest.v1", (HandleNamedMessageDelegate)obj2); object obj3 = <>O.<2>__OnPunchRequest; if (obj3 == null) { HandleNamedMessageDelegate val4 = OnPunchRequest; <>O.<2>__OnPunchRequest = val4; obj3 = (object)val4; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.PunchRequest.v1", (HandleNamedMessageDelegate)obj3); } object obj4 = <>O.<3>__OnEvent; if (obj4 == null) { HandleNamedMessageDelegate val5 = OnEvent; <>O.<3>__OnEvent = val5; obj4 = (object)val5; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.Event.v1", (HandleNamedMessageDelegate)obj4); object obj5 = <>O.<4>__OnImpact; if (obj5 == null) { HandleNamedMessageDelegate val6 = OnImpact; <>O.<4>__OnImpact = val6; obj5 = (object)val6; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.Impact.v1", (HandleNamedMessageDelegate)obj5); object obj6 = <>O.<5>__OnSnapshot; if (obj6 == null) { HandleNamedMessageDelegate val7 = OnSnapshot; <>O.<5>__OnSnapshot = val7; obj6 = (object)val7; } val.RegisterNamedMessageHandler("Y4NGZ.NativeFists.Snapshot.v1", (HandleNamedMessageDelegate)obj6); singleton.OnClientConnectedCallback += OnClientConnected; singleton.OnClientDisconnectCallback += OnClientDisconnected; registeredNetworkManager = singleton; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"NativeFists: reliable-sequenced handlers registered."); } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)("NativeFists: handler registration failed: " + ex)); } UnregisterNetworkHandlers(); } } private static void UnregisterNetworkHandlers() { NetworkManager val = registeredNetworkManager; CustomMessagingManager val2 = ((val != null) ? val.CustomMessagingManager : null); if (val2 != null) { try { if (val.IsServer) { val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.StateRequest.v1"); val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.SprintExitRequest.v1"); val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.PunchRequest.v1"); } val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.Event.v1"); val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.Impact.v1"); val2.UnregisterNamedMessageHandler("Y4NGZ.NativeFists.Snapshot.v1"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: handler unregister failed: " + ex.Message)); } } } if ((Object)(object)val != (Object)null) { val.OnClientConnectedCallback -= OnClientConnected; val.OnClientDisconnectCallback -= OnClientDisconnected; } registeredNetworkManager = null; } private static void OnClientConnected(ulong clientId) { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer) { MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(SendSnapshotAfterJoin(clientId)); } } } private static IEnumerator SendSnapshotAfterJoin(ulong clientId) { float deadline = Time.realtimeSinceStartup + 5f; while (Time.realtimeSinceStartup < deadline && (Object)(object)ResolvePlayer(clientId) == (Object)null) { yield return null; } yield return (object)new WaitForSeconds(0.25f); if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.IsServer && NetworkManager.Singleton.ConnectedClients.ContainsKey(clientId)) { SendSnapshot(clientId); } } private static void OnClientDisconnected(ulong clientId) { if (ServerSessions.TryGetValue(clientId, out var value)) { value.Model.Interrupt(); } ServerSessions.Remove(clientId); PendingSnapshotPlayers.Remove(clientId); StopPresentation(clientId, immediate: true); } private unsafe static void SendStateRequest(uint sequence, bool desiredActive) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0037: 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_0050: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(5, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref sequence, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref desiredActive, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.NativeFists.StateRequest.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void SendSprintExitRequest(uint sequence) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref sequence, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.NativeFists.SprintExitRequest.v1", 0uL, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void SendPunchRequest(uint sequence, PlayerControllerB player) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; Transform val = (((Object)(object)player?.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : null); if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || (Object)(object)val == (Object)null) { return; } Vector3 position = val.position; Vector3 forward = val.forward; Vector3 normalized = ((Vector3)(ref forward)).normalized; FastBufferWriter val2 = default(FastBufferWriter); ((FastBufferWriter)(ref val2))..ctor(32, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref sequence, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref position); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref normalized); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.NativeFists.PunchRequest.v1", 0uL, val2, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val2))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnStateRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } try { uint sequence = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref sequence, default(ForPrimitives)); bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref flag, default(ForPrimitives)); PlayerControllerB val = ResolvePlayer(senderClientId); if ((Object)(object)val == (Object)null || val.actualClientId != senderClientId) { return; } ServerSession serverSession = GetServerSession(senderClientId); if (!flag) { if (serverSession.Model.TrySetActive(sequence, desiredActive: false)) { BroadcastEvent(senderClientId, sequence, NativeFistPhase.Inactive, NativeFistHand.None); } } else if (UpgradeTierSync.GetTier(senderClientId, "lethal_hands_training") <= 0 || !CanUseFists(val, requireEmptyHands: true)) { BroadcastEvent(senderClientId, sequence, NativeFistPhase.Inactive, NativeFistHand.None); } else if (serverSession.Model.TrySetActive(sequence, desiredActive: true)) { BroadcastEvent(senderClientId, sequence, NativeFistPhase.Equipping, NativeFistHand.None); int generation = serverSession.Model.Generation; MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(FinishServerEquip(senderClientId, serverSession, generation)); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid StateRequest: " + ex.Message)); } } } private static void OnSprintExitRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } try { uint value = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); PlayerControllerB val = ResolvePlayer(senderClientId); if (!((Object)(object)val == (Object)null) && val.actualClientId == senderClientId) { ServerSession serverSession = GetServerSession(senderClientId); BeginServerUnequip(senderClientId, serverSession, value); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid SprintExitRequest: " + ex.Message)); } } } private static void OnPunchRequest(ulong senderClientId, FastBufferReader reader) { //IL_0021: 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_007e: 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_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_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_00ec: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || !NetworkManager.Singleton.IsServer) { return; } try { uint sequence = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref sequence, default(ForPrimitives)); Vector3 origin = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref origin); Vector3 val = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val); PlayerControllerB val2 = ResolvePlayer(senderClientId); if ((Object)(object)val2 == (Object)null || val2.actualClientId != senderClientId) { return; } ServerSession serverSession = GetServerSession(senderClientId); if (UpgradeTierSync.GetTier(senderClientId, "lethal_hands_training") <= 0 || !CanUseFists(val2, requireEmptyHands: true) || !ValidateAim(val2, origin, val)) { BroadcastEvent(senderClientId, sequence, serverSession.Model.Phase, serverSession.Model.ActiveHand); return; } NativeFistPhase phase = serverSession.Model.Phase; origin = ServerAimOrigin(val2); ((Vector3)(ref val)).Normalize(); if (serverSession.Model.TryQueueOrStartPunch(sequence, NetworkTime(), out var hand)) { if (phase == NativeFistPhase.Equipping) { serverSession.QueuedOrigin = origin; serverSession.QueuedForward = val; } else { StartServerPunch(senderClientId, serverSession, sequence, hand, origin, val); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid PunchRequest: " + ex.Message)); } } } private static IEnumerator FinishServerEquip(ulong clientId, ServerSession session, int generation) { yield return (object)new WaitForSeconds(0.1f); if (session != null && session.Model.Generation == generation && session.Model.Phase == NativeFistPhase.Equipping && session.Model.FinishEquip(NetworkTime(), out var punchSequence, out var hand)) { if (hand == NativeFistHand.None) { BroadcastEvent(clientId, punchSequence, NativeFistPhase.Idle, NativeFistHand.None); BeginServerUnequip(clientId, session); } else { StartServerPunch(clientId, session, punchSequence, hand, session.QueuedOrigin, session.QueuedForward); } } } private static void StartServerPunch(ulong clientId, ServerSession session, uint sequence, NativeFistHand hand, Vector3 origin, Vector3 forward) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) session.ActivePunchSequence = sequence; int generation = session.Model.Generation; BroadcastEvent(clientId, sequence, NativeFistPhase.Punching, hand); MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(ResolveServerPunch(clientId, session, sequence, origin, forward, generation)); } } private static IEnumerator ResolveServerPunch(ulong clientId, ServerSession session, uint sequence, Vector3 origin, Vector3 forward, int generation) { //IL_001c: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) yield return (object)new WaitForSeconds(11f / 54f); if (!IsCurrentPunch(session, sequence, generation)) { yield break; } PlayerControllerB val = ResolvePlayer(clientId); if ((Object)(object)val == (Object)null) { InterruptServer(clientId, session); yield break; } if (val.isSprinting) { BeginServerUnequip(clientId, session); yield break; } if (!CanUseFists(val, requireEmptyHands: true)) { InterruptServer(clientId, session); yield break; } ResolveAuthoritativeHit(clientId, sequence, val, origin, forward); yield return (object)new WaitForSeconds(59f / 108f); if (IsCurrentPunch(session, sequence, generation) && session.Model.FinishPunch()) { BroadcastEvent(clientId, sequence, NativeFistPhase.Idle, NativeFistHand.None); } } private static bool IsCurrentPunch(ServerSession session, uint sequence, int generation) { if (session != null && session.Model.Generation == generation && session.Model.Phase == NativeFistPhase.Punching) { return session.ActivePunchSequence == sequence; } return false; } private static void BeginServerUnequip(ulong clientId, ServerSession session, uint? requestedSequence = null) { if (session != null && (requestedSequence.HasValue ? session.Model.TryBeginUnequip(requestedSequence.Value) : session.Model.BeginUnequip())) { int generation = session.Model.Generation; uint sequence = requestedSequence ?? session.Model.LastPunchSequence; BroadcastEvent(clientId, sequence, NativeFistPhase.Unequipping, NativeFistHand.None); MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(FinishServerUnequip(clientId, session, sequence, generation)); } } } private static IEnumerator FinishServerUnequip(ulong clientId, ServerSession session, uint sequence, int generation) { yield return (object)new WaitForSeconds(5f / 12f); if (session != null && session.Model.Generation == generation && session.Model.Phase == NativeFistPhase.Unequipping) { session.Model.FinishUnequip(); BroadcastEvent(clientId, sequence, NativeFistPhase.Inactive, NativeFistHand.None); } } private static void InterruptServer(ulong clientId, ServerSession session) { if (session != null && session.Model.Phase != NativeFistPhase.Inactive) { uint lastStateSequence = session.Model.LastStateSequence; session.Model.Interrupt(); BroadcastEvent(clientId, lastStateSequence, NativeFistPhase.Inactive, NativeFistHand.None); } } private static void ResolveAuthoritativeHit(ulong clientId, uint sequence, PlayerControllerB attacker, Vector3 origin, Vector3 forward) { //IL_0007: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f4: 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_006f: 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_0086: 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_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_029a: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0250: Unknown result type (might be due to invalid IL or missing references) ((Vector3)(ref forward)).Normalize(); RaycastHit[] array = Physics.SphereCastAll(origin, 0.8f, forward, 1.2f, 11012424, (QueryTriggerInteraction)2); Array.Sort(array, (RaycastHit left, RaycastHit right) => ((RaycastHit)(ref left)).distance.CompareTo(((RaycastHit)(ref right)).distance)); for (int num = 0; num < array.Length; num++) { RaycastHit val = array[num]; Collider collider = ((RaycastHit)(ref val)).collider; if ((Object)(object)collider == (Object)null) { continue; } Vector3 point = ((((RaycastHit)(ref val)).point == Vector3.zero) ? collider.ClosestPoint(origin + forward * Mathf.Max(((RaycastHit)(ref val)).distance, 0.01f)) : ((RaycastHit)(ref val)).point); int layer = ((Component)collider).gameObject.layer; if ((layer == 8 || layer == 11) && !collider.isTrigger) { BroadcastImpact(clientId, sequence, NativeFistHitKind.Surface, FistSurfaceClassifier.ResolveSurfaceIndex(collider), ChooseVanillaHitClip(), point); EmitAuthorityNoise(attacker, point); return; } if (!IsWorldBlocked(origin, point) && TryHitClingingTongue(collider, attacker)) { BroadcastImpact(clientId, sequence, NativeFistHitKind.ClingingEnemy, -1, ChooseVanillaHitClip(), point); EmitAuthorityNoise(attacker, point); return; } PlayerControllerB val2 = ((Component)collider).GetComponent() ?? ((Component)collider).GetComponentInParent(); EnemyAICollisionDetect val3 = ((Component)collider).GetComponent() ?? ((Component)collider).GetComponentInParent(); EnemyAI val4 = (((Object)(object)val3 != (Object)null) ? val3.mainScript : (((Component)collider).GetComponent() ?? ((Component)collider).GetComponentInParent())); if ((Object)(object)val4 != (Object)null) { if (IsWorldBlocked(origin, point)) { continue; } if (val4.isEnemyDead) { FractionalEnemyDamage.Remove(val4); } else { if (StartOfRound.Instance.hangarDoorsClosed && val4.isInsidePlayerShip != attacker.isInHangarShipRoom) { continue; } bool num2 = IsClingingEnemy(val4, attacker); int tier = UpgradeTierSync.GetTier(clientId, "lethal_hands_training"); bool num3 = CanDamageEnemy(val4); int num4 = (num3 ? FractionalEnemyDamage.Add(val4, NativeFistsUpgrade.GetDamageForTier(tier)) : 0); if (num4 > 0) { val4.HitEnemy(num4, attacker, true, 1); val4.HitEnemyClientRpc(num4, -1, true, 1); if (val4.isEnemyDead) { FractionalEnemyDamage.Remove(val4); } } if (num3 && tier >= 3 && !val4.isEnemyDead) { val4.SetEnemyStunned(true, 1f, attacker); } NativeFistHitKind kind = (num2 ? NativeFistHitKind.ClingingEnemy : NativeFistHitKind.Enemy); BroadcastImpact(clientId, sequence, kind, -1, ChooseVanillaHitClip(), point); EmitAuthorityNoise(attacker, point); return; } } else if (!((Object)(object)val2 == (Object)(object)attacker) && !IsWorldBlocked(origin, point) && (Object)(object)val2 != (Object)null && val2.isPlayerControlled && !val2.isPlayerDead && !Object.op_Implicit((Object)(object)val2.inAnimationWithEnemy)) { val2.DamagePlayerFromOtherClientClientRpc(10, forward, (int)attacker.playerClientId, Mathf.Max(0, val2.health - 10)); BroadcastImpact(clientId, sequence, NativeFistHitKind.Player, -1, ChooseVanillaHitClip(), point); EmitAuthorityNoise(attacker, point); return; } } BroadcastImpact(clientId, sequence, NativeFistHitKind.Miss, -1, byte.MaxValue, origin + forward * 1.2f); } private static bool CanDamageEnemy(EnemyAI enemy) { NutcrackerEnemyAI val = (NutcrackerEnemyAI)(object)((enemy is NutcrackerEnemyAI) ? enemy : null); if (val == null) { return true; } bool flag = default(bool); int num; if (NutcrackerIsInspectingField != null) { object value = NutcrackerIsInspectingField.GetValue(val); if (value is bool) { flag = (bool)value; num = 1; } else { num = 0; } } else { num = 0; } if (((uint)num & (flag ? 1u : 0u)) == 0) { return ((EnemyAI)val).currentBehaviourStateIndex == 2; } return true; } private static bool IsClingingEnemy(EnemyAI enemy, PlayerControllerB player) { CentipedeAI val = (CentipedeAI)(object)((enemy is CentipedeAI) ? enemy : null); if (val != null) { return (Object)(object)val.clingingToPlayer == (Object)(object)player; } FlowerSnakeEnemy val2 = (FlowerSnakeEnemy)(object)((enemy is FlowerSnakeEnemy) ? enemy : null); if (val2 != null) { return (Object)(object)val2.clingingToPlayer == (Object)(object)player; } return false; } private static bool TryHitClingingTongue(Collider collider, PlayerControllerB attacker) { BushWolfTongueCollider val = ((Component)collider).GetComponent() ?? ((Component)collider).GetComponentInParent(); BushWolfEnemy val2 = (((Object)(object)val != (Object)null) ? val.bushWolfScript : null); if ((Object)(object)val2 == (Object)null || (Object)(object)val2.draggingPlayer != (Object)(object)attacker || BushWolfHitTongueLocalClientMethod == null) { return false; } try { BushWolfHitTongueLocalClientMethod.Invoke(val2, null); val2.HitTongueClientRpc(-1); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: fox tongue hit failed: " + ex.Message)); } return false; } } private static bool IsWorldBlocked(Vector3 origin, Vector3 point) { //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_001a: 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) if (point != Vector3.zero && (Object)(object)StartOfRound.Instance != (Object)null) { return Physics.Linecast(origin, point, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1); } return false; } private static void EmitAuthorityNoise(PlayerControllerB attacker, Vector3 point) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) RoundManager instance = RoundManager.Instance; if (instance != null) { instance.PlayAudibleNoise(point, 17f, 0.8f, 0, (Object)(object)attacker != (Object)null && attacker.isInElevator && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.hangarDoorsClosed, 9011); } } private unsafe static void BroadcastEvent(ulong playerId, uint sequence, NativeFistPhase phase, NativeFistHand hand) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0054: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || !singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(14, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref sequence, default(ForPrimitives)); byte b = (byte)phase; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); b = (byte)hand; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ.NativeFists.Event.v1", val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnEvent(ulong senderClientId, FastBufferReader reader) { //IL_000b: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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) if (senderClientId != 0L) { return; } try { ulong playerId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerId, default(ForPrimitives)); uint sequence = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref sequence, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b2, default(ForPrimitives)); if (b <= 4 && b2 <= 2) { ApplyAuthoritativeEvent(playerId, sequence, (NativeFistPhase)b, (NativeFistHand)b2); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid Event: " + ex.Message)); } } } private static void ApplyAuthoritativeEvent(ulong playerId, uint sequence, NativeFistPhase phase, NativeFistHand hand) { PlayerControllerB val = ResolvePlayer(playerId); if ((Object)(object)val == (Object)null) { if (phase != NativeFistPhase.Inactive) { PendingSnapshotPlayers.Add(playerId); } return; } if (phase == NativeFistPhase.Inactive) { StopPresentation(playerId, immediate: true); } else { PresentationSession value; bool flag = Presentations.TryGetValue(playerId, out value) && value.Phase == NativeFistPhase.Equipping; EnsurePresentation(val, directToIdle: false); if (phase == NativeFistPhase.Equipping && !flag) { FirePresentationTrigger(playerId, "Y4NGZ_Fists_Enter"); } else { switch (phase) { case NativeFistPhase.Punching: PresentPunch(playerId, sequence, hand); break; case NativeFistPhase.Unequipping: StopPresentation(playerId, immediate: false); break; } } if (Presentations.TryGetValue(playerId, out var value2)) { value2.Phase = phase; } } if (!((Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { return; } if (phase == NativeFistPhase.Unequipping && val.isSprinting) { ResetLocalState(); return; } localPhase = phase; switch (phase) { case NativeFistPhase.Punching: localNextHand = ((hand != NativeFistHand.Left) ? NativeFistHand.Left : NativeFistHand.Right); break; case NativeFistPhase.Inactive: ResetLocalState(); break; } } private unsafe static void BroadcastImpact(ulong playerId, uint sequence, NativeFistHitKind kind, int surfaceIndex, byte audioSelection, Vector3 point) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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_0054: 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_006a: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || !singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(32, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref sequence, default(ForPrimitives)); byte b = (byte)kind; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); short num = (short)surfaceIndex; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref audioSelection, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref point); singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ.NativeFists.Impact.v1", val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnImpact(ulong senderClientId, FastBufferReader reader) { //IL_000b: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0044: 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_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) if (senderClientId != 0L) { return; } try { ulong clientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref clientId, default(ForPrimitives)); uint num = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); short surfaceIndex = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref surfaceIndex, default(ForPrimitives)); byte audioSelection = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref audioSelection, default(ForPrimitives)); Vector3 point = default(Vector3); ((FastBufferReader)(ref reader)).ReadValueSafe(ref point); if (b <= 4) { PlayImpactPresentation(ResolvePlayer(clientId), (NativeFistHitKind)b, surfaceIndex, audioSelection, point); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid Impact: " + ex.Message)); } } } private unsafe static void SendSnapshot(ulong recipientClientId) { //IL_009c: 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_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_00e7: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || !singleton.IsServer) { return; } List list = new List(); foreach (KeyValuePair serverSession in ServerSessions) { NativeFistPhase phase = serverSession.Value.Model.Phase; if (phase != NativeFistPhase.Inactive && phase != NativeFistPhase.Unequipping) { list.Add(serverSession.Key); } } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(2 + list.Count * 8, (Allocator)2, -1); try { ushort num = (ushort)list.Count; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); for (int i = 0; i < list.Count; i++) { ulong num2 = list[i]; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num2, default(ForPrimitives)); } singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.NativeFists.Snapshot.v1", recipientClientId, val, (NetworkDelivery)3); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnSnapshot(ulong senderClientId, FastBufferReader reader) { //IL_000b: 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_0021: 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) if (senderClientId != 0L) { return; } try { ushort num = default(ushort); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); ulong num2 = default(ulong); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); PlayerControllerB val = ResolvePlayer(num2); if ((Object)(object)val == (Object)null) { PendingSnapshotPlayers.Add(num2); } else { EnsurePresentation(val, directToIdle: true); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: invalid Snapshot: " + ex.Message)); } } } private static void RetryPendingSnapshot(PlayerControllerB player) { if ((Object)(object)player != (Object)null && PendingSnapshotPlayers.Remove(player.actualClientId)) { EnsurePresentation(player, directToIdle: true); } } private static bool EnsurePackRegistered() { //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //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_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: 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_0112: Expected O, but got Unknown if (packRegistered) { return true; } if (Time.realtimeSinceStartup < nextPackRegistrationAttemptAt) { return false; } nextPackRegistrationAttemptAt = Time.realtimeSinceStartup + 2f; string text = Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? string.Empty; string path = Path.Combine(text, "y4ngz-upgrades-fists-firstperson.manifest.json"); string path2 = Path.Combine(text, "y4ngz-upgrades-fists-thirdperson.manifest.json"); if (!File.Exists(path) || !File.Exists(path2)) { if (!missingManifestLogged) { missingManifestLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"NativeFists: animation manifests missing; combat is active but presentation cannot start."); } } return false; } try { InteractionAnimationPackDefinition val = new InteractionAnimationPackDefinition(); val.PackId = "y4ngz.upgrades.native-fists"; val.Version = "1.0.0"; val.AssetRootPath = text; val.Interactions = (InteractionAnimationDefinition[])(object)new InteractionAnimationDefinition[2] { new InteractionAnimationDefinition { InteractionId = "y4ngz.native-fists.firstperson", PresentationKind = (InteractionAnimationPresentationKind)0, ManifestJson = File.ReadAllText(path) }, new InteractionAnimationDefinition { InteractionId = "y4ngz.native-fists.thirdperson", PresentationKind = (InteractionAnimationPresentationKind)1, ManifestJson = File.ReadAllText(path2) } }; string text2 = default(string); if (!LCInteractionAnimationAPI.TryRegisterInteractionPack(val, ref text2) && !string.Equals(text2, "pack_already_registered", StringComparison.OrdinalIgnoreCase)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("NativeFists: pack registration failed: " + text2)); } return false; } packRegistered = true; missingManifestLogged = false; return true; } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("NativeFists: pack registration failed: " + ex.Message)); } return false; } } private static void EnsurePresentation(PlayerControllerB player, bool directToIdle) { //IL_0035: 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_0066: 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_008f: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !EnsurePackRegistered()) { return; } ulong actualClientId = player.actualClientId; if (Presentations.TryGetValue(actualClientId, out var value) && ((InteractionAnimationHandle)(ref value.Handle)).IsValid && LCInteractionAnimationAPI.IsInteractionActive(value.Handle)) { return; } bool flag = (Object)(object)player == (Object)(object)GameNetworkManager.Instance?.localPlayerController; InteractionAnimationHandle val = default(InteractionAnimationHandle); string text = default(string); if (!LCInteractionAnimationAPI.TryStartInteraction(new InteractionAnimationRequest { Player = player, PackId = "y4ngz.upgrades.native-fists", InteractionId = (flag ? "y4ngz.native-fists.firstperson" : "y4ngz.native-fists.thirdperson") }, ref val, ref text)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: " + (flag ? "FP" : "TP") + " presentation failed: " + text)); } return; } Presentations[actualClientId] = new PresentationSession { Handle = val, Phase = ((!directToIdle) ? NativeFistPhase.Equipping : NativeFistPhase.Idle) }; if (directToIdle && !LCInteractionAnimationAPI.TryFireInteractionTrigger(val, "SyncIdle")) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"NativeFists: late-join SyncIdle presentation trigger rejected."); } } UpdatePresentationParameters(player); } private static void UpdatePresentationParameters(PlayerControllerB player) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || !Presentations.TryGetValue(player.actualClientId, out var value) || !((InteractionAnimationHandle)(ref value.Handle)).IsValid || !LCInteractionAnimationAPI.IsInteractionActive(value.Handle) || value.Phase == NativeFistPhase.Inactive || value.Phase == NativeFistPhase.Unequipping) { return; } float num = 0f; Animator playerBodyAnimator = player.playerBodyAnimator; if ((Object)(object)playerBodyAnimator != (Object)null) { int layerIndex = playerBodyAnimator.GetLayerIndex("UpperBodyEmotes"); if (layerIndex >= 0) { num = playerBodyAnimator.GetLayerWeight(layerIndex); } } bool flag = ((value.HasNearWall && value.NearWall) ? (num > 0.02f) : (num >= 0.08f)); if ((!value.HasNearWall || value.NearWall != flag) && LCInteractionAnimationAPI.TrySetInteractionBool(value.Handle, "FistsNearWall", flag)) { value.HasNearWall = true; value.NearWall = flag; } } private static bool FirePresentationTrigger(ulong playerId, string trigger) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (Presentations.TryGetValue(playerId, out var value) && ((InteractionAnimationHandle)(ref value.Handle)).IsValid && LCInteractionAnimationAPI.IsInteractionActive(value.Handle)) { return LCInteractionAnimationAPI.TryFireInteractionTrigger(value.Handle, trigger); } return false; } private static void PresentPunch(ulong playerId, uint sequence, NativeFistHand hand) { PlayerControllerB val = ResolvePlayer(playerId); if ((Object)(object)val == (Object)null) { return; } EnsurePresentation(val, directToIdle: false); if (!Presentations.TryGetValue(playerId, out var value) || (value.HasPunchSequence && value.LastPunchSequence == sequence)) { return; } value.HasPunchSequence = true; value.LastPunchSequence = sequence; value.Phase = NativeFistPhase.Punching; string text = ((hand == NativeFistHand.Right) ? "PunchRight" : "PunchLeft"); if (FirePresentationTrigger(playerId, text)) { PlayVanillaSwing(val); } else { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)($"NativeFists: punch presentation trigger rejected player={playerId} " + $"sequence={sequence} trigger='{text}'; suppressing orphan swing audio.")); } } if ((Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController) { localPhase = NativeFistPhase.Punching; localActivePunchSequence = sequence; localNextPunchAllowedAt = Time.realtimeSinceStartup + 0.75f; localGeneration++; MonoBehaviour obj = Host(); if (obj != null) { obj.StartCoroutine(PredictPunchFinished(sequence, localGeneration)); } } } private static void StopPresentation(ulong playerId, bool immediate) { //IL_002b: 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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) if (!Presentations.TryGetValue(playerId, out var value) || (!immediate && value.Phase == NativeFistPhase.Unequipping)) { return; } if (((InteractionAnimationHandle)(ref value.Handle)).IsValid && LCInteractionAnimationAPI.IsInteractionActive(value.Handle)) { string text = default(string); if (immediate) { LCInteractionAnimationAPI.TryStopInteraction(value.Handle, (InteractionAnimationStopReason)2); } else if (!LCInteractionAnimationAPI.TryBeginInteractionExit(value.Handle, ref text)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("NativeFists: graceful Unequip presentation rejected: " + text)); } LCInteractionAnimationAPI.TryStopInteraction(value.Handle, (InteractionAnimationStopReason)0); } } if (immediate) { Presentations.Remove(playerId); } else { value.Phase = NativeFistPhase.Unequipping; } } private static void BeginLocalSprintExit(PlayerControllerB local) { if (!((Object)(object)local == (Object)null) && localPhase != NativeFistPhase.Inactive) { uint sequence = NextLocalSequence(); StopPresentation(local.actualClientId, immediate: false); ResetLocalState(); if ((Object)(object)registeredNetworkManager != (Object)null) { SendSprintExitRequest(sequence); } } } private static void InterruptLocal(bool sendRequest) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (sendRequest && (Object)(object)registeredNetworkManager != (Object)null) { SendStateRequest(NextLocalSequence(), desiredActive: false); } if ((Object)(object)val != (Object)null) { StopPresentation(val.actualClientId, immediate: true); } ResetLocalState(); } private static void ResetLocalState() { localGeneration++; localPhase = NativeFistPhase.Inactive; localNextHand = NativeFistHand.Left; localActivePunchSequence = 0u; localNextPunchAllowedAt = 0f; } private static void ResetRuntime(bool unregisterNetwork) { foreach (ulong item in new List(Presentations.Keys)) { StopPresentation(item, immediate: true); } Presentations.Clear(); PendingSnapshotPlayers.Clear(); ServerSessions.Clear(); FractionalEnemyDamage.Clear(); nextLocalSequence = 1u; ResetLocalState(); vanillaSwingClip = null; vanillaHitClips = null; vanillaAudioResolved = false; if (unregisterNetwork) { UnregisterNetworkHandlers(); packRegistered = false; missingManifestLogged = false; nextPackRegistrationAttemptAt = 0f; } } private static ServerSession GetServerSession(ulong clientId) { if (!ServerSessions.TryGetValue(clientId, out var value)) { value = new ServerSession(); ServerSessions[clientId] = value; } return value; } private static PlayerControllerB ResolvePlayer(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } foreach (PlayerControllerB val in array) { if ((Object)(object)val != (Object)null && val.actualClientId == clientId) { return val; } } return null; } private static bool CanUseFists(PlayerControllerB player, bool requireEmptyHands) { if ((Object)(object)player == (Object)null || !player.isPlayerControlled || player.isPlayerDead || player.isSprinting || player.isTypingChat || player.inTerminalMenu || player.isClimbingLadder || player.inVehicleAnimation || player.inSpecialInteractAnimation || player.enteringSpecialAnimation || player.playingQuickSpecialAnimation || Object.op_Implicit((Object)(object)player.inAnimationWithEnemy) || player.performingEmote || player.doingUpperBodyEmote > 0f || player.isHoldingInteract || player.teleportedLastFrame || player.inSpecialMenu || player.isGrabbingObjectAnimation || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { return false; } if (requireEmptyHands) { if ((Object)(object)player.currentlyHeldObjectServer == (Object)null) { return !player.isHoldingObject; } return false; } return true; } private static Vector3 ServerAimOrigin(PlayerControllerB player) { //IL_0039: 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) //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) if (!((Object)(object)player.gameplayCamera != (Object)null)) { return ((Component)player).transform.position + Vector3.up * 1.5f; } return ((Component)player.gameplayCamera).transform.position; } private static bool ValidateAim(PlayerControllerB player, Vector3 origin, Vector3 forward) { //IL_0000: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005b: 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_0060: 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_0062: 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_0078: Unknown result type (might be due to invalid IL or missing references) if (!IsFinite(origin) || !IsFinite(forward) || ((Vector3)(ref forward)).magnitude < 0.8f || ((Vector3)(ref forward)).magnitude > 1.2f) { return false; } Vector3 val = ServerAimOrigin(player); Vector3 val2 = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.forward : ((Component)player).transform.forward); if (Vector3.Distance(origin, val) <= 0.75f) { return Vector3.Dot(((Vector3)(ref forward)).normalized, ((Vector3)(ref val2)).normalized) >= 0.25f; } return false; } private static bool IsFinite(Vector3 value) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (IsFinite(value.x) && IsFinite(value.y)) { return IsFinite(value.z); } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } private static double NetworkTime() { //IL_0018: 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) if (!((Object)(object)NetworkManager.Singleton != (Object)null)) { return Time.realtimeSinceStartupAsDouble; } NetworkTime serverTime = NetworkManager.Singleton.ServerTime; return ((NetworkTime)(ref serverTime)).Time; } private static uint NextLocalSequence() { uint num = nextLocalSequence++; if (num != 0) { return num; } return nextLocalSequence++; } private static MonoBehaviour Host() { if ((Object)(object)StartOfRound.Instance != (Object)null) { return (MonoBehaviour)(object)StartOfRound.Instance; } if ((Object)(object)GameNetworkManager.Instance != (Object)null) { return (MonoBehaviour)(object)GameNetworkManager.Instance; } return (MonoBehaviour)(object)HUDManager.Instance; } private static byte ChooseVanillaHitClip() { ResolveVanillaShovelAudio(); if (vanillaHitClips != null && vanillaHitClips.Length != 0) { return (byte)Random.Range(0, Mathf.Min(vanillaHitClips.Length, 255)); } return byte.MaxValue; } private static void PlayVanillaSwing(PlayerControllerB player) { ResolveVanillaShovelAudio(); if ((Object)(object)player?.movementAudio != (Object)null && (Object)(object)vanillaSwingClip != (Object)null) { player.movementAudio.PlayOneShot(vanillaSwingClip); } } private static void PlayImpactPresentation(PlayerControllerB attacker, NativeFistHitKind kind, int surfaceIndex, byte audioSelection, Vector3 point) { if (kind == NativeFistHitKind.Miss) { return; } ResolveVanillaShovelAudio(); AudioSource val = attacker?.movementAudio; if ((Object)(object)val != (Object)null && vanillaHitClips != null && audioSelection < vanillaHitClips.Length && (Object)(object)vanillaHitClips[audioSelection] != (Object)null) { val.PlayOneShot(vanillaHitClips[audioSelection]); } if (kind == NativeFistHitKind.Surface && (Object)(object)val != (Object)null) { AudioClip val2 = FistSurfaceClassifier.HitSurfaceClip(surfaceIndex); if ((Object)(object)val2 != (Object)null) { val.PlayOneShot(val2); } } } private static void ResolveVanillaShovelAudio() { if (vanillaAudioResolved) { return; } vanillaAudioResolved = true; AllItemsList val = StartOfRound.Instance?.allItemsList; if (val?.itemsList == null) { return; } for (int i = 0; i < val.itemsList.Count; i++) { Item val2 = val.itemsList[i]; Shovel val3 = (((Object)(object)val2?.spawnPrefab != (Object)null) ? val2.spawnPrefab.GetComponent() : null); if (!((Object)(object)val3 == (Object)null)) { vanillaSwingClip = val3.swing; vanillaHitClips = val3.hitSFX; break; } } } } internal static class NativeInventoryModel { internal const int VanillaSlotCount = 4; internal const int MaximumBonusSlots = 3; internal const int PhysicalSlotCount = 7; internal const int UtilitySlotIndex = 50; internal static int GetUnlockedSlotCount(int tier) { if (tier <= 0) { return 4; } if (tier >= 3) { return 7; } return 4 + tier; } internal static int GetTwoHandedLimit(int tier) { if (tier < 3) { return 1; } return 2; } internal static bool IsSelectable(int slot, int unlockedSlotCount, int occupancyMask) { if (slot < 0 || slot >= 7) { return false; } if (slot >= unlockedSlotCount) { return (occupancyMask & (1 << slot)) != 0; } return true; } internal static int FindFirstEmptySlot(bool utilitySlotAvailable, int currentSlot, int unlockedSlotCount, int occupancyMask) { if (utilitySlotAvailable) { return 50; } int num = ClampUnlockedCount(unlockedSlotCount); if (currentSlot >= 0 && currentSlot < num && (occupancyMask & (1 << currentSlot)) == 0) { return currentSlot; } for (int i = 0; i < num; i++) { if ((occupancyMask & (1 << i)) == 0) { return i; } } return -1; } internal static int FindNextSelectableSlot(int currentSlot, bool forward, int unlockedSlotCount, int occupancyMask) { int num = ClampUnlockedCount(unlockedSlotCount); int num2; switch (currentSlot) { case 50: { if (forward) { return 0; } for (int num3 = 6; num3 >= 0; num3--) { if (IsSelectable(num3, num, occupancyMask)) { return num3; } } return num - 1; } default: num2 = (forward ? 6 : 0); break; case 0: case 1: case 2: case 3: case 4: case 5: case 6: num2 = currentSlot; break; } int num4 = num2; for (int i = 1; i <= 7; i++) { int num5 = (forward ? ((num4 + i) % 7) : ((num4 - i + 14) % 7)); if (IsSelectable(num5, num, occupancyMask)) { return num5; } } return num - 1; } internal static int GetHighestUnlockedSlot(int unlockedSlotCount) { return ClampUnlockedCount(unlockedSlotCount) - 1; } private static int ClampUnlockedCount(int unlockedSlotCount) { if (unlockedSlotCount < 4) { return 4; } if (unlockedSlotCount > 7) { return 7; } return unlockedSlotCount; } } [HarmonyPatch] internal static class PanicSlidePatch { private enum SlideState { None, Starting, Sliding, Exiting } private struct RendererPresentationState { internal Renderer Renderer; internal bool Enabled; internal ShadowCastingMode ShadowMode; internal int Layer; internal bool Valid; internal RendererPresentationState(Renderer renderer) { //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) Renderer = renderer; Enabled = (Object)(object)renderer != (Object)null && renderer.enabled; ShadowMode = (ShadowCastingMode)(((Object)(object)renderer != (Object)null) ? ((int)renderer.shadowCastingMode) : 0); Layer = (((Object)(object)renderer != (Object)null && (Object)(object)((Component)renderer).gameObject != (Object)null) ? ((Component)renderer).gameObject.layer : 0); Valid = (Object)(object)renderer != (Object)null; } } private sealed class RemoteSlideTerrainPresentation { private readonly Transform _presentationRoot; private readonly Vector3 _baseLocalPosition; private readonly Quaternion _baseLocalRotation; private Vector3 _smoothedGroundNormal = Vector3.up; private bool _groundNormalInitialized; private string _lastGateResult; internal PlayerControllerB Player { get; } internal bool IsReady { get { if ((Object)(object)Player != (Object)null) { return (Object)(object)_presentationRoot != (Object)null; } return false; } } internal RemoteSlideTerrainPresentation(PlayerControllerB player) { //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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_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) Player = player; _presentationRoot = ResolveBodyMetarig(player); if ((Object)(object)_presentationRoot != (Object)null) { _baseLocalPosition = _presentationRoot.localPosition; _baseLocalRotation = _presentationRoot.localRotation; } } internal void Apply() { //IL_002f: 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_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_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_001a: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: 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_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_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00de: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0175: Unknown result type (might be due to invalid IL or missing references) //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018b: Unknown result type (might be due to invalid IL or missing references) //IL_019d: 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_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) Vector3 groundNormal; if (!IsReady) { groundNormal = default(Vector3); LogGate("presentation_root_missing", 0f, 0f, groundNormal); return; } _presentationRoot.localPosition = _baseLocalPosition; _presentationRoot.localRotation = _baseLocalRotation; Vector3 position = _presentationRoot.position; Quaternion rotation = _presentationRoot.rotation; int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); RaycastHit val = default(RaycastHit); if (!Physics.Raycast(position + Vector3.up * 1.5f, Vector3.down, ref val, 4f, num, (QueryTriggerInteraction)1)) { groundNormal = default(Vector3); LogGate("ground_miss", 0f, 0f, groundNormal); return; } groundNormal = ((RaycastHit)(ref val)).normal; Vector3 val2; if (!(((Vector3)(ref groundNormal)).sqrMagnitude > 0.0001f)) { val2 = Vector3.up; } else { groundNormal = ((RaycastHit)(ref val)).normal; val2 = ((Vector3)(ref groundNormal)).normalized; } Vector3 val3 = val2; if (!_groundNormalInitialized) { _smoothedGroundNormal = val3; _groundNormalInitialized = true; } else { float num2 = 1f - Mathf.Exp(-14f * Time.deltaTime); groundNormal = Vector3.Slerp(_smoothedGroundNormal, val3, num2); _smoothedGroundNormal = ((Vector3)(ref groundNormal)).normalized; } _presentationRoot.rotation = Quaternion.FromToRotation(Vector3.up, _smoothedGroundNormal) * rotation; _presentationRoot.position = new Vector3(position.x, ((RaycastHit)(ref val)).point.y + 0.02f, position.z); LogGate("applied", ((RaycastHit)(ref val)).point.y, _presentationRoot.position.y - position.y, _smoothedGroundNormal); } internal void Restore() { //IL_0016: 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) if (!((Object)(object)_presentationRoot == (Object)null)) { _presentationRoot.localPosition = _baseLocalPosition; _presentationRoot.localRotation = _baseLocalRotation; } } private void LogGate(string result, float groundY = 0f, float presentationDeltaY = 0f, Vector3 groundNormal = default(Vector3)) { //IL_0088: 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_00a0: Unknown result type (might be due to invalid IL or missing references) if (!string.Equals(_lastGateResult, result, StringComparison.Ordinal)) { _lastGateResult = result; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-slide] terrain_gate: playerClientId=" + (Player?.playerClientId.ToString() ?? "") + " " + $"result='{result}' groundY={groundY:0.######} " + $"presentationDeltaY={presentationDeltaY:0.######} " + $"groundNormal=({groundNormal.x:0.######},{groundNormal.y:0.######},{groundNormal.z:0.######}).")); } } } private static Transform ResolveBodyMetarig(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)player).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (string.Equals(((Object)val).name, "metarig", StringComparison.Ordinal) && (Object)(object)val.parent != (Object)null && string.Equals(((Object)val.parent).name, "ScavengerModel", StringComparison.Ordinal)) { return val; } } return null; } } [CompilerGenerated] private static class <>O { public static Action <0>__OnMovementBeginCameraRendering; public static HandleNamedMessageDelegate <1>__OnReceiveSlideStart; public static HandleNamedMessageDelegate <2>__OnReceiveSlideStop; } private const string MSG_SLIDE_START = "Y4NGZ_SlideStart"; private const string MSG_SLIDE_STOP = "Y4NGZ_SlideStop"; private const float STARTING_SECONDS = 0.833f; private const float MOVEMENT_LOOK_YAW_DEGREES_PER_SECOND = 300f; private const float MOVEMENT_LOOK_PITCH_DEGREES_PER_SECOND = 220f; private const float REMOTE_SLIDE_GROUND_RAY_START_METERS = 1.5f; private const float REMOTE_SLIDE_GROUND_RAY_DISTANCE_METERS = 4f; private const float REMOTE_SLIDE_GROUND_CLEARANCE_METERS = 0.02f; private const float REMOTE_SLIDE_NORMAL_RESPONSE = 14f; private static float _cooldownEnd; private static bool _handlersRegistered; private static readonly Dictionary RemoteSlidePresentations = new Dictionary(); private static SlideState _localSlideState; private static PlayerControllerB _localSlidePlayer; private static Vector3 _slideDirection; private static float _slideStartedAt; private static float _slideExitStartedAt; private static float _airborneSeconds; private static bool _stopSent; private static bool _slideForcedCrouch; private static PlayerControllerB _lookLimitedPlayer; private static bool _lookLimiterInitialized; private static float _lastLimitedBodyYaw; private static float _lastLimitedCameraPitch; private static bool _cameraUpFieldResolved; private static FieldInfo _cameraUpField; private static Transform _cameraOffsetTransform; private static Vector3 _cameraBaseLocalPosition; private static float _cameraAppliedOffset; private static bool _cameraOffsetApplied; private static bool _cameraRotationApplied; private static PlayerControllerB _armsPresentationPlayer; private static bool _armsPresentationSaved; private static bool _savedArmsRendererEnabled; private static bool _savedLocalArmsMatchCamera; private static bool _movementRenderHookSubscribed; private static bool _vanillaCameraBaseCaptured; private static Vector3 _vanillaCameraBaseLocal; private static PlayerControllerB _presentationPlayer; private static RendererPresentationState _savedPlayerModelState; private static RendererPresentationState _savedPlayerModelLod1State; private static RendererPresentationState _savedPlayerModelLod2State; private static bool _presentationLayerRedirectActive; private static int _presentationVisibleLayer = -1; private static bool _presentationSaved; private static bool _jumpMemberResolved; private static FieldInfo _isJumpingField; private static PropertyInfo _isJumpingProperty; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } internal static void OnRoundStarted() { RegisterNetworkHandlers(); _cooldownEnd = 0f; ForceEndLocalSlide("start-game", sendStop: false); SlideAnimationBridge.EndAll("start-game"); ClearRemoteSlideTerrainPresentations("start-game"); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ForceEndLocalSlide("end-of-game", sendStop: true); SlideAnimationBridge.EndAll("end-of-game"); ClearRemoteSlideTerrainPresentations("end-of-game"); } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectCaptureCameraBase(PlayerControllerB __instance) { //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) if (IsLocalPlayer(__instance) && !((Object)(object)__instance.gameplayCamera == (Object)null)) { _vanillaCameraBaseLocal = ((Component)__instance.gameplayCamera).transform.localPosition; _vanillaCameraBaseCaptured = true; } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { RegisterNetworkHandlers(); UpdateLocalSlide(__instance); SlideAnimationBridge.Tick(); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] [HarmonyPriority(-100)] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null)) { if (!IsLocalPlayer(__instance)) { ApplyRemoteSlideTerrainConformance(__instance); } else if ((Object)(object)__instance == (Object)(object)_localSlidePlayer && _localSlideState != SlideState.None) { ReapplyFirstPersonMovementPresentation(__instance); ApplySlideCameraTreatment(__instance); ApplyMovementLookLimit(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "Crouch_performed")] [HarmonyPrefix] private static bool PreCrouchPerformed(PlayerControllerB __instance, CallbackContext context) { if (!((CallbackContext)(ref context)).performed) { return true; } if (IsLocalPlayer(__instance) && IsLocalSlideActive()) { StartLocalExit("crouch-cancel"); return false; } if (!IsLocalPlayer(__instance) || !PanicSlideUpgrade.IsUnlocked()) { return true; } if (!CanSlide(__instance)) { return true; } TrySlide(__instance); return false; } private static bool CanSlide(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead) { return false; } if (_localSlideState != SlideState.None) { return false; } if (!player.isSprinting || player.isCrouching) { return false; } if ((Object)(object)player.thisController == (Object)null || !player.thisController.isGrounded) { return false; } if (player.sprintMeter < 0.16f) { return false; } if ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) { return false; } if (player.isTypingChat || player.inTerminalMenu || player.inSpecialInteractAnimation) { return false; } return true; } private static void TrySlide(PlayerControllerB player) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: 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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) if (Time.time < _cooldownEnd) { return; } Vector3 val = ResolveCameraForward(player); InteractionAnimationHandle val2 = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val2)) { LCInteractionAnimationAPI.TryStopInteraction(val2, (InteractionAnimationStopReason)2); } InteractionAnimationHandle val3 = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)0, ref val3)) { LCInteractionAnimationAPI.TryStopInteraction(val3, (InteractionAnimationStopReason)2); } InteractionAnimationHandle val4 = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val4) || LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)0, ref val4) || !SlideAnimationBridge.Begin(player)) { return; } BeginLocalAnimatedSlide(player, val); player.Crouch(true); _slideForcedCrouch = player.isCrouching; if (!_slideForcedCrouch) { ForceEndLocalSlide("crouch-rejected", sendStop: false); return; } float num = Mathf.Clamp(1.15f - (player.carryWeight - 1f) * 0.12f, 0.55f, 1.15f); player.externalForceAutoFade += val * 15.5f * num; player.sprintMeter = Mathf.Clamp01(player.sprintMeter - 0.14f); if ((Object)(object)player.sprintMeterUI != (Object)null) { player.sprintMeterUI.fillAmount = player.sprintMeter; } _cooldownEnd = Time.time + 2.25f; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ShakeCamera((ScreenShakeType)0); } SendSlideStart(player.playerClientId); } private static void BeginLocalAnimatedSlide(PlayerControllerB player, Vector3 direction) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) RestoreCameraOffset(); _localSlidePlayer = player; _localSlideState = SlideState.Starting; _slideDirection = ((((Vector3)(ref direction)).sqrMagnitude > 0.001f) ? ((Vector3)(ref direction)).normalized : ((Component)player).transform.forward); _slideStartedAt = Time.time; _slideExitStartedAt = 0f; _airborneSeconds = 0f; _stopSent = false; BeginMovementLookLimit(player); BeginFirstPersonMovementPresentation(player); } private static void UpdateLocalSlide(PlayerControllerB player) { if (_localSlideState == SlideState.None) { RestoreCameraOffset(); return; } if ((Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)_localSlidePlayer) { ForceEndLocalSlide("player-changed", sendStop: true); return; } if (player.isPlayerDead) { ForceEndLocalSlide("player-dead", sendStop: true); return; } if (_localSlideState == SlideState.Exiting) { if (Time.time - _slideExitStartedAt >= 0.55f) { FinishLocalSlideState(); } return; } float num = Time.time - _slideStartedAt; if (_localSlideState == SlideState.Starting && num >= 0.833f) { _localSlideState = SlideState.Sliding; } if (ShouldExitSlide(player, num, out var reason)) { if (string.Equals(reason, "special-interact", StringComparison.Ordinal)) { ForceEndLocalSlide(reason, sendStop: true); } else { StartLocalExit(reason); } return; } UpdateSlideDirection(player); ApplySustainForce(player, num); if (num >= 1.35f) { StartLocalExit("duration"); } } private static bool ShouldExitSlide(PlayerControllerB player, float elapsed, out string reason) { reason = null; if ((Object)(object)player == (Object)null || player.isPlayerDead) { reason = "player-dead"; return true; } if (player.inSpecialInteractAnimation) { reason = "special-interact"; return true; } if (IsPlayerJumping(player)) { reason = "jump"; return true; } if ((Object)(object)player.thisController != (Object)null && player.thisController.isGrounded) { _airborneSeconds = 0f; } else { _airborneSeconds += Time.deltaTime; if (_airborneSeconds > 0.35f) { reason = "airborne"; return true; } } if (elapsed > 0.4f && GetHorizontalSpeed(player) < 2.5f) { reason = "low-speed"; return true; } return false; } private static bool IsPlayerJumping(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } ResolveJumpMember(); try { if (_isJumpingField != null && _isJumpingField.GetValue(player) is bool result) { return result; } if (_isJumpingProperty != null && _isJumpingProperty.GetValue(player, null) is bool result2) { return result2; } } catch { } return false; } private static void ResolveJumpMember() { if (!_jumpMemberResolved) { _jumpMemberResolved = true; _isJumpingField = typeof(PlayerControllerB).GetField("isJumping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _isJumpingProperty = typeof(PlayerControllerB).GetProperty("isJumping", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } private static void UpdateSlideDirection(PlayerControllerB player) { //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_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_002e: 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_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) Vector3 val = ResolveCameraForward(player); if (!(((Vector3)(ref val)).sqrMagnitude < 0.001f)) { float num = MathF.PI / 3f * Time.deltaTime; Vector3 val2 = Vector3.RotateTowards(_slideDirection, val, num, 0f); _slideDirection = ((Vector3)(ref val2)).normalized; } } private static void ApplySustainForce(PlayerControllerB player, float elapsed) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !(((Vector3)(ref _slideDirection)).sqrMagnitude < 0.001f)) { float num = Mathf.Clamp01(1f - elapsed / 1.35f); player.externalForceAutoFade += _slideDirection * (4.5f * num * Time.deltaTime); } } private static void StartLocalExit(string reason) { if (_localSlideState != SlideState.None) { _localSlideState = SlideState.Exiting; _slideExitStartedAt = Time.time; _airborneSeconds = 0f; ClearSlideHorizontalMomentum(_localSlidePlayer); if ((Object)(object)_localSlidePlayer != (Object)null) { SlideAnimationBridge.TriggerExit(_localSlidePlayer); } if (!_stopSent && (Object)(object)_localSlidePlayer != (Object)null) { _stopSent = true; SendSlideStop(_localSlidePlayer.playerClientId); } } } private static void FinishLocalSlideState() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB localSlidePlayer = _localSlidePlayer; RestoreCameraOffset(); EndFirstPersonMovementPresentation(); ClearSlideHorizontalMomentum(localSlidePlayer); if (_slideForcedCrouch && (Object)(object)localSlidePlayer != (Object)null && localSlidePlayer.isCrouching) { localSlidePlayer.Crouch(false); } _localSlideState = SlideState.None; _localSlidePlayer = null; _slideDirection = Vector3.zero; _slideStartedAt = 0f; _slideExitStartedAt = 0f; _airborneSeconds = 0f; _stopSent = false; _slideForcedCrouch = false; EndMovementLookLimit(localSlidePlayer); } internal static void BeginMovementLookLimit(PlayerControllerB player) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) _lookLimitedPlayer = player; _lookLimiterInitialized = false; if (!((Object)(object)player == (Object)null) && !((Object)(object)player.gameplayCamera == (Object)null)) { Transform val = (((Object)(object)player.thisPlayerBody != (Object)null) ? player.thisPlayerBody : ((Component)player).transform); _lastLimitedBodyYaw = (((Object)(object)val != (Object)null) ? val.eulerAngles.y : 0f); _lastLimitedCameraPitch = ReadVanillaCameraPitch(player); _lookLimiterInitialized = true; } } private static float ReadVanillaCameraPitch(PlayerControllerB player) { //IL_005a: Unknown result type (might be due to invalid IL or missing references) ResolveCameraUpField(); if (_cameraUpField != null) { try { if (_cameraUpField.GetValue(player) is float angle) { return NormalizeSignedAngle(angle); } } catch { } } if (!((Object)(object)player.gameplayCamera != (Object)null)) { return 0f; } return NormalizeSignedAngle(((Component)player.gameplayCamera).transform.localEulerAngles.x); } internal static void ApplyMovementLookLimit(PlayerControllerB player) { //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0113: 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_0072: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null || (Object)(object)player != (Object)(object)_lookLimitedPlayer || LedgeMantlePatch.IsDebugThirdPersonCamActive()) { return; } if (!_lookLimiterInitialized) { BeginMovementLookLimit(player); return; } float num = Mathf.Max(0.0001f, Time.unscaledDeltaTime); Transform val = (((Object)(object)player.thisPlayerBody != (Object)null) ? player.thisPlayerBody : ((Component)player).transform); if ((Object)(object)val != (Object)null) { float y = val.eulerAngles.y; float num2 = 300f * num; float num3 = _lastLimitedBodyYaw + Mathf.Clamp(Mathf.DeltaAngle(_lastLimitedBodyYaw, y), 0f - num2, num2); Vector3 eulerAngles = val.eulerAngles; eulerAngles.y = num3; val.eulerAngles = eulerAngles; _lastLimitedBodyYaw = num3; } Transform transform = ((Component)player.gameplayCamera).transform; float num4 = ReadVanillaCameraPitch(player); float num5 = 220f * num; float num6 = _lastLimitedCameraPitch + Mathf.Clamp(Mathf.DeltaAngle(_lastLimitedCameraPitch, num4), 0f - num5, num5); num6 = Mathf.Clamp(num6, -80f, 80f); Vector3 localEulerAngles = transform.localEulerAngles; localEulerAngles.x = num6; transform.localEulerAngles = localEulerAngles; _lastLimitedCameraPitch = num6; ResolveCameraUpField(); if (!(_cameraUpField != null)) { return; } try { _cameraUpField.SetValue(player, num6); } catch { } } internal static void EndMovementLookLimit(PlayerControllerB player) { if (!((Object)(object)player != (Object)null) || !((Object)(object)_lookLimitedPlayer != (Object)null) || !((Object)(object)player != (Object)(object)_lookLimitedPlayer)) { _lookLimitedPlayer = null; _lookLimiterInitialized = false; _lastLimitedBodyYaw = 0f; _lastLimitedCameraPitch = 0f; } } private static float NormalizeSignedAngle(float angle) { return Mathf.DeltaAngle(0f, angle); } private static void ResolveCameraUpField() { if (!_cameraUpFieldResolved) { _cameraUpFieldResolved = true; _cameraUpField = typeof(PlayerControllerB).GetField("cameraUp", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } private static void ClearSlideHorizontalMomentum(PlayerControllerB player) { //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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null)) { Vector3 externalForceAutoFade = player.externalForceAutoFade; externalForceAutoFade.x = 0f; externalForceAutoFade.z = 0f; player.externalForceAutoFade = externalForceAutoFade; } } private static void ForceEndLocalSlide(string reason, bool sendStop) { PlayerControllerB localSlidePlayer = _localSlidePlayer; if (sendStop && !_stopSent && (Object)(object)localSlidePlayer != (Object)null) { SendSlideStop(localSlidePlayer.playerClientId); } if ((Object)(object)localSlidePlayer != (Object)null) { SlideAnimationBridge.End(localSlidePlayer, reason); } FinishLocalSlideState(); } private static void ApplySlideCameraTreatment(PlayerControllerB player) { float num = CalculateSlideCameraEnvelope(); ApplyFirstPersonMovementCamera(player, 0.5f * num, -7f * num); } internal static void ApplyFirstPersonMovementCamera(PlayerControllerB player, float dip, float rollDegrees) { //IL_0046: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return; } if (LedgeMantlePatch.IsDebugThirdPersonCamActive()) { RestoreCameraOffset(); ReapplyFirstPersonArmsPresentation(player); return; } Transform transform = ((Component)player.gameplayCamera).transform; if (_vanillaCameraBaseCaptured && SlideAnimationBridge.IsFirstPersonViewLocalBodyShown()) { transform.localPosition = _vanillaCameraBaseLocal; } ReapplyFirstPersonArmsPresentation(player); ApplyCameraRoll(transform, rollDegrees); ApplyCameraDip(transform, dip); } private static void ApplyCameraDip(Transform cameraTransform, float dip) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: 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_0068: 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_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0085: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cameraTransform == (Object)null) { return; } if (dip <= 0.0001f) { RestoreCameraPositionOffset(); return; } if ((Object)(object)_cameraOffsetTransform != (Object)null && (Object)(object)_cameraOffsetTransform != (Object)(object)cameraTransform) { RestoreCameraOffset(); } Vector3 val = cameraTransform.localPosition; if (_cameraOffsetApplied && (Object)(object)_cameraOffsetTransform == (Object)(object)cameraTransform) { Vector3 cameraBaseLocalPosition = _cameraBaseLocalPosition; cameraBaseLocalPosition.y += _cameraAppliedOffset; Vector3 val2 = val - cameraBaseLocalPosition; if (((Vector3)(ref val2)).sqrMagnitude < 0.0004f) { val = (cameraTransform.localPosition = _cameraBaseLocalPosition); } } _cameraOffsetTransform = cameraTransform; _cameraBaseLocalPosition = val; _cameraAppliedOffset = 0f - dip; _cameraOffsetApplied = dip > 0.0001f; Vector3 localPosition = val; localPosition.y -= dip; if (_cameraOffsetApplied) { cameraTransform.localPosition = localPosition; } } private static void ApplyCameraRoll(Transform cameraTransform, float rollDegrees) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)cameraTransform == (Object)null)) { if ((Object)(object)_cameraOffsetTransform != (Object)null && (Object)(object)_cameraOffsetTransform != (Object)(object)cameraTransform) { RestoreCameraOffset(); } _cameraOffsetTransform = cameraTransform; if (Mathf.Abs(rollDegrees) <= 0.001f) { rollDegrees = 0f; } if (Mathf.Abs(rollDegrees) > 0.001f || _cameraRotationApplied) { Vector3 localEulerAngles = cameraTransform.localEulerAngles; localEulerAngles.z = rollDegrees; cameraTransform.localEulerAngles = localEulerAngles; } _cameraRotationApplied = Mathf.Abs(rollDegrees) > 0.001f; if (!_cameraOffsetApplied && !_cameraRotationApplied) { _cameraOffsetTransform = null; } } } private static float CalculateSlideCameraEnvelope() { if (_localSlideState == SlideState.None) { return 0f; } if (_localSlideState == SlideState.Exiting) { float num = Mathf.Clamp01((Time.time - _slideExitStartedAt) / 0.2f); return 1f - Mathf.SmoothStep(0f, 1f, num); } float num2 = Mathf.Clamp01((Time.time - _slideStartedAt) / 0.15f); return Mathf.SmoothStep(0f, 1f, num2); } internal static void RestoreCameraOffset() { //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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) if (!_cameraOffsetApplied && !_cameraRotationApplied) { return; } if ((Object)(object)_cameraOffsetTransform != (Object)null) { if (_cameraOffsetApplied) { _cameraOffsetTransform.localPosition = _cameraBaseLocalPosition; } if (_cameraRotationApplied) { Vector3 localEulerAngles = _cameraOffsetTransform.localEulerAngles; localEulerAngles.z = 0f; _cameraOffsetTransform.localEulerAngles = localEulerAngles; } } _cameraOffsetTransform = null; _cameraBaseLocalPosition = Vector3.zero; _cameraAppliedOffset = 0f; _cameraOffsetApplied = false; _cameraRotationApplied = false; } private static void RestoreCameraPositionOffset() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) if (_cameraOffsetApplied) { if ((Object)(object)_cameraOffsetTransform != (Object)null) { _cameraOffsetTransform.localPosition = _cameraBaseLocalPosition; } _cameraBaseLocalPosition = Vector3.zero; _cameraAppliedOffset = 0f; _cameraOffsetApplied = false; if (!_cameraRotationApplied) { _cameraOffsetTransform = null; } } } internal static void BeginFirstPersonMovementPresentation(PlayerControllerB player, bool showBody = true) { if (IsLocalPlayer(player)) { if (!showBody) { EndFirstPersonMovementPresentation(); BeginFirstPersonArmsPresentation(player); return; } if (_presentationSaved && (Object)(object)_presentationPlayer == (Object)(object)player) { ReapplyFirstPersonMovementPresentation(player); return; } EndFirstPersonMovementPresentation(); _presentationPlayer = player; _presentationSaved = true; _savedPlayerModelState = new RendererPresentationState((Renderer)(object)player.thisPlayerModel); _savedPlayerModelLod1State = new RendererPresentationState((Renderer)(object)player.thisPlayerModelLOD1); _savedPlayerModelLod2State = new RendererPresentationState((Renderer)(object)player.thisPlayerModelLOD2); _presentationVisibleLayer = ResolveFirstPersonVisibleLayer(player); int cameraMask = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera.cullingMask : (-1)); _presentationLayerRedirectActive = _presentationVisibleLayer >= 0 && (RendererLayerNeedsRedirect(_savedPlayerModelState, cameraMask) || RendererLayerNeedsRedirect(_savedPlayerModelLod1State, cameraMask) || RendererLayerNeedsRedirect(_savedPlayerModelLod2State, cameraMask)); BeginFirstPersonArmsPresentation(player); LogFirstPersonPresentationDiagnostics(player, cameraMask); ReapplyFirstPersonMovementPresentation(player); } } internal static void ReapplyFirstPersonMovementPresentation(PlayerControllerB player) { if (_presentationSaved && !((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)_presentationPlayer)) { ApplyBodyRendererPresentation((Renderer)(object)player.thisPlayerModel); ApplyBodyRendererPresentation((Renderer)(object)player.thisPlayerModelLOD1); ApplyBodyRendererPresentation((Renderer)(object)player.thisPlayerModelLOD2); ReapplyFirstPersonArmsPresentation(player); if (_presentationLayerRedirectActive) { ApplyPresentationLayer((Renderer)(object)player.thisPlayerModel); ApplyPresentationLayer((Renderer)(object)player.thisPlayerModelLOD1); ApplyPresentationLayer((Renderer)(object)player.thisPlayerModelLOD2); } } } private static void BeginFirstPersonArmsPresentation(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { if (!_armsPresentationSaved || (Object)(object)_armsPresentationPlayer != (Object)(object)player) { _armsPresentationPlayer = player; _armsPresentationSaved = true; _savedArmsRendererEnabled = (Object)(object)player.thisPlayerModelArms == (Object)null || ((Renderer)player.thisPlayerModelArms).enabled; _savedLocalArmsMatchCamera = player.localArmsMatchCamera; } SubscribeMovementRenderHook(); ReapplyFirstPersonArmsPresentation(player); } } private static void SubscribeMovementRenderHook() { if (!_movementRenderHookSubscribed) { _movementRenderHookSubscribed = true; RenderPipelineManager.beginCameraRendering += OnMovementBeginCameraRendering; } } private static void UnsubscribeMovementRenderHook() { if (_movementRenderHookSubscribed) { _movementRenderHookSubscribed = false; RenderPipelineManager.beginCameraRendering -= OnMovementBeginCameraRendering; } } private static void OnMovementBeginCameraRendering(ScriptableRenderContext context, Camera camera) { PlayerControllerB armsPresentationPlayer = _armsPresentationPlayer; if (!((Object)(object)armsPresentationPlayer == (Object)null) && !((Object)(object)camera == (Object)null) && !((Object)(object)armsPresentationPlayer.gameplayCamera != (Object)(object)camera)) { ReapplyFirstPersonArmsPresentation(armsPresentationPlayer); } } internal static void ReapplyFirstPersonArmsPresentation(PlayerControllerB player) { if (!_armsPresentationSaved || (Object)(object)player == (Object)null || (Object)(object)player != (Object)(object)_armsPresentationPlayer) { return; } if ((Object)(object)player.thisPlayerModelArms != (Object)null) { bool flag = LedgeMantlePatch.IsDebugThirdPersonCamActive(); ((Renderer)player.thisPlayerModelArms).forceRenderingOff = flag; if (!flag) { ((Renderer)player.thisPlayerModelArms).enabled = true; } } player.localArmsMatchCamera = true; } private static void EndFirstPersonArmsPresentation() { UnsubscribeMovementRenderHook(); if (!_armsPresentationSaved) { return; } PlayerControllerB armsPresentationPlayer = _armsPresentationPlayer; if ((Object)(object)armsPresentationPlayer != (Object)null) { if ((Object)(object)armsPresentationPlayer.thisPlayerModelArms != (Object)null) { ((Renderer)armsPresentationPlayer.thisPlayerModelArms).forceRenderingOff = false; ((Renderer)armsPresentationPlayer.thisPlayerModelArms).enabled = _savedArmsRendererEnabled; } armsPresentationPlayer.localArmsMatchCamera = _savedLocalArmsMatchCamera; } _armsPresentationPlayer = null; _armsPresentationSaved = false; _savedArmsRendererEnabled = false; _savedLocalArmsMatchCamera = false; } internal static void EndFirstPersonMovementPresentation() { EndFirstPersonArmsPresentation(); if (_presentationSaved) { RestoreBodyRendererPresentation(_savedPlayerModelState); RestoreBodyRendererPresentation(_savedPlayerModelLod1State); RestoreBodyRendererPresentation(_savedPlayerModelLod2State); _presentationPlayer = null; _savedPlayerModelState = default(RendererPresentationState); _savedPlayerModelLod1State = default(RendererPresentationState); _savedPlayerModelLod2State = default(RendererPresentationState); _presentationLayerRedirectActive = false; _presentationVisibleLayer = -1; _presentationSaved = false; } } private static void ApplyBodyRendererPresentation(Renderer renderer) { if (!((Object)(object)renderer == (Object)null)) { renderer.shadowCastingMode = (ShadowCastingMode)1; } } private static void ApplyPresentationLayer(Renderer renderer) { if (!((Object)(object)renderer == (Object)null) && !((Object)(object)((Component)renderer).gameObject == (Object)null) && _presentationVisibleLayer >= 0) { ((Component)renderer).gameObject.layer = _presentationVisibleLayer; } } private static void RestoreBodyRendererPresentation(RendererPresentationState state) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) if (state.Valid && !((Object)(object)state.Renderer == (Object)null)) { state.Renderer.enabled = state.Enabled; state.Renderer.shadowCastingMode = state.ShadowMode; if ((Object)(object)((Component)state.Renderer).gameObject != (Object)null) { ((Component)state.Renderer).gameObject.layer = state.Layer; } } } private static bool RendererLayerNeedsRedirect(RendererPresentationState state, int cameraMask) { if (state.Valid) { return !IsLayerRenderedByMask(state.Layer, cameraMask); } return false; } private static bool IsLayerRenderedByMask(int layer, int cameraMask) { if (layer >= 0 && layer < 32) { return (cameraMask & (1 << layer)) != 0; } return false; } private static int ResolveFirstPersonVisibleLayer(PlayerControllerB player) { if ((Object)(object)player != (Object)null && (Object)(object)player.thisPlayerModelArms != (Object)null && (Object)(object)((Component)player.thisPlayerModelArms).gameObject != (Object)null) { return ((Component)player.thisPlayerModelArms).gameObject.layer; } int cameraMask = (((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera.cullingMask : (-1)); for (int i = 0; i < 32; i++) { if (IsLayerRenderedByMask(i, cameraMask)) { return i; } } return 0; } private static void LogFirstPersonPresentationDiagnostics(PlayerControllerB player, int cameraMask) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide] First-person movement presentation active. " + $"gameplayCamera.cullingMask=0x{cameraMask:X8}; " + "redirectLayer=" + (_presentationLayerRedirectActive ? _presentationVisibleLayer.ToString() : "") + "; " + FormatRendererForPresentationLog("thisPlayerModel", (Renderer)(object)player?.thisPlayerModel, cameraMask) + "; " + FormatRendererForPresentationLog("thisPlayerModelLOD1", (Renderer)(object)player?.thisPlayerModelLOD1, cameraMask) + "; " + FormatRendererForPresentationLog("thisPlayerModelLOD2", (Renderer)(object)player?.thisPlayerModelLOD2, cameraMask) + "; " + FormatRendererForPresentationLog("thisPlayerModelArms", (Renderer)(object)player?.thisPlayerModelArms, cameraMask))); } } private static string FormatRendererForPresentationLog(string label, Renderer renderer, int cameraMask) { //IL_0075: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)renderer == (Object)null) { return label + "="; } int num = (((Object)(object)((Component)renderer).gameObject != (Object)null) ? ((Component)renderer).gameObject.layer : (-1)); return label + " name='" + ((Object)renderer).name + "'" + $" enabled={renderer.enabled}" + $" shadowCastingMode={renderer.shadowCastingMode}" + $" gameObject.layer={num}" + $" renderedByGameplayCamera={IsLayerRenderedByMask(num, cameraMask)}"; } private static Vector3 ResolveCameraForward(PlayerControllerB player) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((player != null) ? ((Component)player).transform : null)); Vector3 val2 = (((Object)(object)val != (Object)null) ? Vector3.ProjectOnPlane(val.forward, Vector3.up) : Vector3.zero); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f && (Object)(object)player != (Object)null) { val2 = Vector3.ProjectOnPlane(((Component)player).transform.forward, Vector3.up); } if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = Vector3.forward; } return ((Vector3)(ref val2)).normalized; } private static float GetHorizontalSpeed(PlayerControllerB player) { //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) if ((Object)(object)player == (Object)null || (Object)(object)player.thisController == (Object)null) { return 0f; } Vector3 velocity = player.thisController.velocity; velocity.y = 0f; return ((Vector3)(ref velocity)).magnitude; } internal static bool IsSlideActive() { return _localSlideState != SlideState.None; } private static bool IsLocalSlideActive() { if (_localSlideState != SlideState.Starting) { return _localSlideState == SlideState.Sliding; } return true; } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<1>__OnReceiveSlideStart; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveSlideStart; <>O.<1>__OnReceiveSlideStart = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZ_SlideStart", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<2>__OnReceiveSlideStop; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceiveSlideStop; <>O.<2>__OnReceiveSlideStop = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("Y4NGZ_SlideStop", (HandleNamedMessageDelegate)obj2); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("PanicSlidePatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void SendSlideStart(ulong playerClientId) { SendSlideMessage("Y4NGZ_SlideStart", playerClientId); } private static void SendSlideStop(ulong playerClientId) { SendSlideMessage("Y4NGZ_SlideStop", playerClientId); } private static void SendSlideMessage(string messageName, ulong playerClientId) { NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.IsClient && singleton.CustomMessagingManager != null) { if (singleton.IsServer) { SendSlideMessage(messageName, playerClientId, null); } else { SendSlideMessage(messageName, playerClientId, 0uL); } } } private static void SendSlideMessage(string messageName, ulong playerClientId, ulong? clientId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: 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_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerClientId, default(ForPrimitives)); if (clientId.HasValue) { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage(messageName, clientId.Value, val, (NetworkDelivery)3); } else { NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll(messageName, val, (NetworkDelivery)3); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnReceiveSlideStart(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); ApplyRemoteSlideStart(playerClientId); RelaySlideMessageIfHost("Y4NGZ_SlideStart", senderClientId, playerClientId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("PanicSlidePatch: malformed slide start message: " + ex.Message)); } } } private static void OnReceiveSlideStop(ulong senderClientId, FastBufferReader reader) { //IL_0006: 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) try { ulong playerClientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref playerClientId, default(ForPrimitives)); ApplyRemoteSlideStop(playerClientId); RelaySlideMessageIfHost("Y4NGZ_SlideStop", senderClientId, playerClientId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("PanicSlidePatch: malformed slide stop message: " + ex.Message)); } } } private static void RelaySlideMessageIfHost(string messageName, ulong senderClientId, ulong playerClientId) { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { SendSlideMessage(messageName, playerClientId, null); } } private static void ApplyRemoteSlideStart(ulong playerClientId) { bool flag = Plugin.RemoteSlideTerrainConformance?.Value ?? true; PlayerControllerB val = ResolvePlayer(playerClientId); if ((Object)(object)val == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-slide] start_gate: " + $"playerClientId={playerClientId} bridgeStarted=False " + $"terrainConfigured={flag} " + "terrainPresentationStarted=False reason='player_missing'.")); } return; } if (IsLocalPlayer(val)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)("[Panic Slide.remote-slide] start_gate: " + $"playerClientId={playerClientId} bridgeStarted=False " + $"terrainConfigured={flag} " + "terrainPresentationStarted=False reason='local_player'.")); } return; } bool flag2 = SlideAnimationBridge.Begin(val); bool flag3 = false; string arg; RemoteSlideTerrainPresentation value; if (!flag2) { RemoveRemoteSlideTerrainPresentation(playerClientId, "bridge_start_failed"); arg = "bridge_start_failed"; } else if (!flag) { RemoveRemoteSlideTerrainPresentation(playerClientId, "config_disabled"); arg = "config_disabled"; } else if (RemoteSlidePresentations.TryGetValue(playerClientId, out value) && value.Player == val) { flag3 = true; arg = "already_active"; } else { RemoveRemoteSlideTerrainPresentation(playerClientId, "replaced"); RemoteSlideTerrainPresentation remoteSlideTerrainPresentation = new RemoteSlideTerrainPresentation(val); if (remoteSlideTerrainPresentation.IsReady) { RemoteSlidePresentations[playerClientId] = remoteSlideTerrainPresentation; flag3 = true; arg = "ready"; } else { arg = "presentation_root_missing"; } } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)("[Panic Slide.remote-slide] start_gate: " + $"playerClientId={playerClientId} bridgeStarted={flag2} " + $"terrainConfigured={flag} " + $"terrainPresentationStarted={flag3} reason='{arg}'.")); } } private static void ApplyRemoteSlideStop(ulong playerClientId) { PlayerControllerB val = ResolvePlayer(playerClientId); bool flag = (Object)(object)val != (Object)null && !IsLocalPlayer(val); if (flag) { SlideAnimationBridge.TriggerExit(val); } bool flag2 = RemoteSlidePresentations.ContainsKey(playerClientId); if (!flag) { RemoveRemoteSlideTerrainPresentation(playerClientId, "stop_without_remote_player"); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-slide] stop_gate: " + $"playerClientId={playerClientId} bridgeExitTriggered={flag} " + $"terrainPresentationActive={flag2} " + "reason='" + (((Object)(object)val == (Object)null) ? "player_missing" : (IsLocalPlayer(val) ? "local_player" : "exit_started")) + "'.")); } } private static void ApplyRemoteSlideTerrainConformance(PlayerControllerB player) { ulong playerClientId = player.playerClientId; if (!RemoteSlidePresentations.TryGetValue(playerClientId, out var value)) { return; } if (value.Player != player) { RemoveRemoteSlideTerrainPresentation(playerClientId, "player_replaced"); return; } ConfigEntry remoteSlideTerrainConformance = Plugin.RemoteSlideTerrainConformance; if (remoteSlideTerrainConformance != null && !remoteSlideTerrainConformance.Value) { RemoveRemoteSlideTerrainPresentation(playerClientId, "config_disabled"); } else if (!SlideAnimationBridge.IsActive(player)) { RemoveRemoteSlideTerrainPresentation(playerClientId, "bridge_inactive"); } else { value.Apply(); } } private static bool RemoveRemoteSlideTerrainPresentation(ulong playerClientId, string reason) { if (!RemoteSlidePresentations.TryGetValue(playerClientId, out var value)) { return false; } RemoteSlidePresentations.Remove(playerClientId); value.Restore(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-slide] terrain_end_gate: " + $"playerClientId={playerClientId} reason='{reason}'.")); } return true; } private static void ClearRemoteSlideTerrainPresentations(string reason) { int num = 0; foreach (RemoteSlideTerrainPresentation value in RemoteSlidePresentations.Values) { value.Restore(); num++; } RemoteSlidePresentations.Clear(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Panic Slide.remote-slide] terrain_clear_gate: " + $"restored={num} reason='{reason}'.")); } } private static PlayerControllerB ResolvePlayer(ulong playerClientId) { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null || instance.allPlayerScripts == null) { return null; } for (int i = 0; i < instance.allPlayerScripts.Length; i++) { PlayerControllerB val = instance.allPlayerScripts[i]; if ((Object)(object)val != (Object)null && val.playerClientId == playerClientId) { return val; } } return null; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } [HarmonyPatch(typeof(PlayerControllerB))] internal static class PlayerControllerBPatch { private static bool isDeathDrop = false; private static readonly List capturedDeathItems = new List(); [HarmonyPrefix] [HarmonyPatch("KillPlayer")] private static void KillPlayerPrefix() { isDeathDrop = true; } [HarmonyPostfix] [HarmonyPatch("KillPlayer")] private static void KillPlayerPostfix() { isDeathDrop = false; } [HarmonyPrefix] [HarmonyPatch("KillPlayerClientRpc")] private static void KillPlayerClientRpcPrefix() { isDeathDrop = true; } [HarmonyPostfix] [HarmonyPatch("KillPlayerClientRpc")] private static void KillPlayerClientRpcPostfix(PlayerControllerB __instance, int playerId) { //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_002e: Unknown result type (might be due to invalid IL or missing references) isDeathDrop = false; if (Y4NGZUpgradeState.GetActiveUpgrade("Salvager")) { Vector3 position = ((Component)StartOfRound.Instance.allPlayerScripts[playerId]).transform.position; ((MonoBehaviour)GameNetworkManager.Instance).StartCoroutine(AddDeathItemGlow(position)); } } [HarmonyPrefix] [HarmonyPatch("DropAllHeldItems")] private static void DropAllHeldItemsPrefix(PlayerControllerB __instance) { capturedDeathItems.Clear(); if (!isDeathDrop || !Y4NGZUpgradeState.GetActiveUpgrade("Salvager")) { return; } for (int i = 0; i < __instance.ItemSlots.Length; i++) { if ((Object)(object)__instance.ItemSlots[i] != (Object)null) { capturedDeathItems.Add(__instance.ItemSlots[i]); } } } [HarmonyPostfix] [HarmonyPatch("DropAllHeldItems")] private static void DropAllHeldItemsPostfix() { if (capturedDeathItems.Count == 0) { return; } foreach (GrabbableObject capturedDeathItem in capturedDeathItems) { if ((Object)(object)capturedDeathItem != (Object)null && (Object)(object)((Component)capturedDeathItem).gameObject.GetComponent() == (Object)null) { ((Component)capturedDeathItem).gameObject.AddComponent().Initialize(); } } Plugin.Log.LogDebug((object)$"Salvager: Added glow to {capturedDeathItems.Count} death-dropped items."); capturedDeathItems.Clear(); } private static IEnumerator AddDeathItemGlow(Vector3 deathPosition) { //IL_0007: 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) yield return (object)new WaitForSeconds(0.8f); if (!Y4NGZUpgradeState.GetActiveUpgrade("Salvager")) { yield break; } GrabbableObject[] array = Object.FindObjectsOfType(); int num = 0; GrabbableObject[] array2 = array; foreach (GrabbableObject val in array2) { if (!((Object)(object)val == (Object)null) && !val.isHeld && !val.isInShipRoom && !(Vector3.Distance(((Component)val).transform.position, deathPosition) > 12f) && !((Object)(object)((Component)val).gameObject.GetComponent() != (Object)null)) { ((Component)val).gameObject.AddComponent().Initialize(); num++; } } if (num > 0) { Plugin.Log.LogDebug((object)$"Salvager fallback: Added glow to {num} items near death position."); } } [HarmonyPostfix] [HarmonyPatch("Update")] private static void UpdatePostfix(PlayerControllerB __instance) { if (((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { LoneWolfUpgrade.Evaluate(__instance); if (LoneWolfUpgrade.LoneWolfActive) { LoneWolfUpgrade.ApplyStaminaBonus(__instance); } } } } [HarmonyPatch] internal static class LoneWolfCleanupPatch { [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] private static void ShipLeavePostfix() { LoneWolfUpgrade.Cleanup(); } [HarmonyPostfix] [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] private static void EndOfGamePostfix() { LoneWolfUpgrade.Cleanup(); } [HarmonyPostfix] [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] private static void DisconnectPostfix() { LoneWolfUpgrade.Cleanup(); } } internal class SalvagerGlow : MonoBehaviour { private Light glowLight; private GrabbableObject item; private float startTime; public void Initialize() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) item = ((Component)this).GetComponent(); startTime = Time.time; glowLight = ((Component)this).gameObject.AddComponent(); glowLight.type = (LightType)2; glowLight.color = new Color(0.3f, 0.9f, 0.5f); glowLight.intensity = 3.5f; glowLight.range = 7f; glowLight.shadows = (LightShadows)0; } private void Update() { if ((Object)(object)item != (Object)null && (item.isHeld || item.isInShipRoom)) { if ((Object)(object)glowLight != (Object)null) { Object.Destroy((Object)(object)glowLight); } Object.Destroy((Object)(object)this); } if ((Object)(object)glowLight != (Object)null) { float num = 0.55f + 0.45f * Mathf.Sin((Time.time - startTime) * 3.2f); glowLight.intensity = Mathf.Lerp(2f, 5f, num); } } private void OnDestroy() { if ((Object)(object)glowLight != (Object)null) { Object.Destroy((Object)(object)glowLight); } } } [HarmonyPatch] internal static class PredatorInstinctPatch { private const string MARKER_NAME = "Y4NGZ_PredatorInstinct_Marker"; private const float HEARTBEAT_INTERVAL_AT_FAR = 1.6f; private const float HEARTBEAT_INTERVAL_AT_CLOSE = 0.45f; private static AudioClip _heartbeatClip; private static AudioSource _heartbeatSource; private static float _nextHeartbeatTime; private static EnemyAI[] _cachedEnemies = Array.Empty(); private static float _nextEnemyScanTime; private const float ENEMY_SCAN_INTERVAL = 0.5f; private static readonly Dictionary _markerCache = new Dictionary(); private static readonly Dictionary _indicatorCache = new Dictionary(); private static Canvas _overlayCanvas; private static Sprite _enemyMarkerSprite; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0137: 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_0141: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance == (Object)null || !((NetworkBehaviour)__instance).IsOwner || !__instance.isPlayerControlled || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } if (__instance.isPlayerDead) { ClearAllMarkers(); StopHeartbeat(); return; } if (!PredatorInstinctUpgrade.IsUnlocked()) { ClearAllMarkers(); StopHeartbeat(); return; } float range = PredatorInstinctUpgrade.GetRange(); if (range <= 0f) { return; } EnsureCanvas(); Camera cam = (((Object)(object)__instance.gameplayCamera != (Object)null) ? __instance.gameplayCamera : Camera.main); if (Time.time >= _nextEnemyScanTime) { _cachedEnemies = Object.FindObjectsOfType(); _nextEnemyScanTime = Time.time + 0.5f; } float num = range * range; float num2 = float.MaxValue; EnemyAI[] cachedEnemies = _cachedEnemies; foreach (EnemyAI val in cachedEnemies) { if ((Object)(object)val == (Object)null) { continue; } if (val.isEnemyDead) { if (_markerCache.TryGetValue(val, out var value)) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } _markerCache.Remove(val); } RemoveIndicator(val); continue; } Vector3 val2 = ((Component)val).transform.position - ((Component)__instance).transform.position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; Light value2; bool flag = _markerCache.TryGetValue(val, out value2) && (Object)(object)value2 != (Object)null; if (sqrMagnitude <= num) { if (!flag) { AddMarker(val); } UpdateIndicator(val, visible: true, Mathf.Sqrt(sqrMagnitude), range, cam); if (sqrMagnitude < num2) { num2 = sqrMagnitude; } } else { if (flag) { Object.Destroy((Object)(object)((Component)value2).gameObject); _markerCache.Remove(val); } UpdateIndicator(val, visible: false, 0f, range, cam); } } if (PredatorInstinctUpgrade.ShouldHeartbeat() && num2 < float.MaxValue) { EnsureHeartbeatSource(__instance); float num3 = Mathf.Clamp01(Mathf.Sqrt(num2) / range); float num4 = Mathf.Lerp(0.45f, 1.6f, num3); if (Time.time >= _nextHeartbeatTime) { _heartbeatSource.PlayOneShot(_heartbeatClip); _nextHeartbeatTime = Time.time + num4; } } else { StopHeartbeat(); } } private static void AddMarker(EnemyAI enemy) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0053: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Y4NGZ_PredatorInstinct_Marker"); val.transform.SetParent(((Component)enemy).transform, false); val.transform.localPosition = Vector3.up * 0.6f; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.15f, 0.15f); val2.intensity = 4f; val2.range = 6f; val2.shadows = (LightShadows)0; _markerCache[enemy] = val2; } private static void UpdateIndicator(EnemyAI enemy, bool visible, float distance, float range, Camera cam) { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0155: 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_018f: Unknown result type (might be due to invalid IL or missing references) //IL_019a: 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_020f: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) if (!_indicatorCache.TryGetValue(enemy, out var value) || (Object)(object)value == (Object)null) { if (!visible || (Object)(object)_overlayCanvas == (Object)null) { return; } GameObject val = new GameObject("PredatorInstinct_Indicator_" + ((Object)((Component)enemy).gameObject).name); val.transform.SetParent(((Component)_overlayCanvas).transform, false); value = val.AddComponent(); value.sizeDelta = new Vector2(22f, 22f); ((Transform)value).localRotation = Quaternion.Euler(0f, 0f, 45f); Image obj = val.AddComponent(); obj.sprite = GetEnemyMarkerSprite(); ((Graphic)obj).color = new Color(1f, 0.12f, 0.08f, 0f); ((Graphic)obj).raycastTarget = false; _indicatorCache[enemy] = value; } if (!visible || (Object)(object)cam == (Object)null) { ((Component)value).gameObject.SetActive(false); return; } Vector3 val2 = cam.WorldToScreenPoint(ResolveEnemyCenter(enemy)); if (val2.z <= 0f) { val2.x = (float)Screen.width - val2.x; val2.y = (float)Screen.height - val2.y; } val2.x = Mathf.Clamp(val2.x, 34f, (float)Screen.width - 34f); val2.y = Mathf.Clamp(val2.y, 34f, (float)Screen.height - 34f); ((Component)value).gameObject.SetActive(true); ((Transform)value).SetAsLastSibling(); ((Transform)value).position = new Vector3(val2.x, val2.y, 0f); float num = 1f - Mathf.Clamp01(distance / Mathf.Max(range, 0.1f)); float num2 = 0.72f + Mathf.Sin(Time.time * Mathf.Lerp(3.5f, 8f, num)) * 0.18f; float num3 = Mathf.Lerp(0.26f, 0.82f, num) * num2; ((Transform)value).localScale = Vector3.one * Mathf.Lerp(0.85f, 1.28f, num); Image component = ((Component)value).GetComponent(); if ((Object)(object)component != (Object)null) { ((Graphic)component).color = new Color(1f, 0.12f, 0.06f, Mathf.Clamp01(num3)); } } private static void RemoveIndicator(EnemyAI enemy) { if (_indicatorCache.TryGetValue(enemy, out var value)) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)((Component)value).gameObject); } _indicatorCache.Remove(enemy); } } private static void ClearAllMarkers() { foreach (KeyValuePair item in _markerCache) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)((Component)item.Value).gameObject); } } _markerCache.Clear(); foreach (KeyValuePair item2 in _indicatorCache) { if ((Object)(object)item2.Value != (Object)null) { Object.Destroy((Object)(object)((Component)item2.Value).gameObject); } } _indicatorCache.Clear(); _cachedEnemies = Array.Empty(); _nextEnemyScanTime = 0f; } private static void EnsureCanvas() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Expected O, but got Unknown if (!((Object)(object)_overlayCanvas != (Object)null)) { GameObject val = new GameObject("PredatorInstinctCanvas"); _overlayCanvas = val.AddComponent(); _overlayCanvas.renderMode = (RenderMode)0; _overlayCanvas.sortingOrder = 185; CanvasScaler obj = val.AddComponent(); obj.uiScaleMode = (ScaleMode)1; obj.referenceResolution = new Vector2(1920f, 1080f); obj.matchWidthOrHeight = 0.5f; val.AddComponent(); Object.DontDestroyOnLoad((Object)val); } } private static Vector3 ResolveEnemyCenter(EnemyAI enemy) { //IL_0009: 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_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return Vector3.zero; } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position; } Renderer val = null; if (enemy.skinnedMeshRenderers != null) { for (int i = 0; i < enemy.skinnedMeshRenderers.Length; i++) { if (!((Object)(object)enemy.skinnedMeshRenderers[i] == (Object)null)) { val = (Renderer)(object)enemy.skinnedMeshRenderers[i]; break; } } } if ((Object)(object)val == (Object)null && enemy.meshRenderers != null) { for (int j = 0; j < enemy.meshRenderers.Length; j++) { if (!((Object)(object)enemy.meshRenderers[j] == (Object)null)) { val = (Renderer)(object)enemy.meshRenderers[j]; break; } } } if (!((Object)(object)val != (Object)null)) { return ((Component)enemy).transform.position + Vector3.up; } Bounds bounds = val.bounds; return ((Bounds)(ref bounds)).center; } private static Sprite GetEnemyMarkerSprite() { //IL_0019: 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_0025: 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_0035: Expected O, but got Unknown //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_enemyMarkerSprite != (Object)null) { return _enemyMarkerSprite; } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; Vector2 val2 = default(Vector2); ((Vector2)(ref val2))..ctor(31.5f, 31.5f); for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { float num = Mathf.Abs(((float)j - val2.x) / val2.x); float num2 = Mathf.Abs(((float)i - val2.y) / val2.y); float num3 = num + num2; float num4 = Mathf.Clamp01(1f - Mathf.Abs(num3 - 0.72f) / 0.12f); float num5 = Mathf.Clamp01(1f - num3 / 0.32f) * 0.55f; float num6 = Mathf.Clamp01(Mathf.Max(num4, num5)); val.SetPixel(j, i, new Color(1f, 1f, 1f, num6)); } } val.Apply(false, true); _enemyMarkerSprite = Sprite.Create(val, new Rect(0f, 0f, 64f, 64f), new Vector2(0.5f, 0.5f)); ((Object)_enemyMarkerSprite).hideFlags = (HideFlags)61; return _enemyMarkerSprite; } private static void EnsureHeartbeatSource(PlayerControllerB player) { //IL_0072: 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) if ((Object)(object)_heartbeatClip == (Object)null) { _heartbeatClip = BuildHeartbeatClip(); } if ((Object)(object)_heartbeatSource == (Object)null || (Object)(object)((Component)_heartbeatSource).gameObject == (Object)null) { Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); Transform val2 = (((Object)(object)val != (Object)null) ? ((Component)val).transform : ((Component)player).transform); GameObject val3 = new GameObject("Y4NGZ_PredatorInstinct_HeartbeatSrc"); val3.transform.SetParent(val2, false); _heartbeatSource = val3.AddComponent(); _heartbeatSource.spatialBlend = 0f; _heartbeatSource.volume = 0.55f; _heartbeatSource.playOnAwake = false; _nextHeartbeatTime = 0f; } } private static void StopHeartbeat() { if (!((Object)(object)_heartbeatSource == (Object)null)) { _heartbeatSource.Stop(); Object.Destroy((Object)(object)((Component)_heartbeatSource).gameObject); _heartbeatSource = null; _nextHeartbeatTime = 0f; } } private static AudioClip BuildHeartbeatClip() { int num = Mathf.CeilToInt(7717.5f); float[] array = new float[num]; float num2 = 0f; float num3 = 0.13f; float num4 = 55f; float num5 = 70f; float num6 = 18f; for (int i = 0; i < num; i++) { float num7 = (float)i / 22050f; float num8 = ((num7 >= num2) ? (Mathf.Sin(MathF.PI * 2f * num4 * (num7 - num2)) * Mathf.Exp((0f - num6) * (num7 - num2))) : 0f); float num9 = ((num7 >= num3) ? (Mathf.Sin(MathF.PI * 2f * num5 * (num7 - num3)) * Mathf.Exp((0f - num6) * (num7 - num3)) * 0.85f) : 0f); array[i] = Mathf.Clamp(num8 + num9, -1f, 1f); } AudioClip obj = AudioClip.Create("Y4NGZ_PredatorInstinct_Heartbeat", num, 1, 22050, false); obj.SetData(array, 0); return obj; } } [HarmonyPatch] internal static class ProteinPowderFix { private static bool _armoryProbeAudited; [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] [HarmonyPrefix] private static void PreHitEnemyOnLocalClient(ref int force, PlayerControllerB playerWhoHit, out bool __state) { __state = false; if (force <= 0 || (Object)(object)playerWhoHit == (Object)null || (Object)(object)playerWhoHit != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } GrabbableObject currentlyHeldObjectServer = playerWhoHit.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null) { return; } int tier = ProteinPowderUpgrade.GetTier(); if (tier <= 0) { return; } AuditArmoryProbeOnce(); if (!ArmoryItemProbe.IsArmoryWeapon(currentlyHeldObjectServer)) { int num = force; force++; __state = tier >= 2; ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)$"ProteinPowderFix: buffed {((object)currentlyHeldObjectServer).GetType().Name} hit from {num} to {force}."); } } } [HarmonyPatch(typeof(EnemyAI), "HitEnemyOnLocalClient")] [HarmonyPostfix] private static void PostHitEnemyOnLocalClient(EnemyAI __instance, PlayerControllerB playerWhoHit, bool __state) { if (__state && !((Object)(object)__instance == (Object)null) && !__instance.isEnemyDead && !(Random.value > 0.25f)) { RetaliationPatch.StunEnemy(__instance, 1f, playerWhoHit); } } private static void AuditArmoryProbeOnce() { if (_armoryProbeAudited) { return; } _armoryProbeAudited = true; if (OptionalPluginCapabilities.BetterArmory && !AnyArmoryWeaponTypeLoaded()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"ProteinPowderFix: Better Armory is loaded but no Y4NGZUpgrades.Weapons type is present; the armoury-weapon exclusion cannot fire and armoury weapons will receive the melee bonus."); } } } private static bool AnyArmoryWeaponTypeLoaded() { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type[] types; try { types = assemblies[i].GetTypes(); } catch (ReflectionTypeLoadException ex) { types = ex.Types; } catch (Exception) { continue; } if (types == null) { continue; } for (int j = 0; j < types.Length; j++) { string text = types[j]?.Namespace; if (text != null && text.StartsWith("Y4NGZUpgrades.Weapons", StringComparison.Ordinal)) { return true; } } } return false; } } internal static class QuotaGuardCompanyPatch { private static bool _initialized; internal static void Initialize() { if (_initialized) { return; } if (!Chainloader.PluginInfos.ContainsKey("com.y4ngz.company")) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"QuotaGuard: Y4NGZCompany not present; the optional quota-penalty cap bonus is inactive."); } return; } try { InstallProvider(); _initialized = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)"QuotaGuard: death-penalty fraction modifier installed."); } } catch (Exception ex) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("QuotaGuard: failed to install death-penalty fraction modifier: " + ex.Message)); } } } private static void InstallProvider() { Type? type = Type.GetType("Y4NGZCompany.Contracts._Shared.QuotaOverhaulRules, Y4NGZCompany", throwOnError: false); if (type == null) { throw new InvalidOperationException("Y4NGZCompany.Contracts._Shared.QuotaOverhaulRules not found"); } FieldInfo? field = type.GetField("DeathPenaltyFractionModifier", BindingFlags.Static | BindingFlags.Public); if (field == null) { throw new InvalidOperationException("QuotaOverhaulRules.DeathPenaltyFractionModifier not found (Y4NGZCompany too old?)"); } field.SetValue(null, new Func(ModifyDeathPenaltyFraction)); } private static float ModifyDeathPenaltyFraction(float fraction) { if (GetCrewEffectiveTier() >= 1) { return Math.Min(fraction, 0.1f); } return fraction; } internal static int GetCrewEffectiveTier() { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return QuotaGuardUpgrade.GetTier(); } int num = 0; foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && val.isPlayerControlled) { int tier = UpgradeTierSync.GetTier(val.actualClientId, "quota_guard"); if (tier > num) { num = tier; } } } return num; } } [HarmonyPatch] internal static class QuotaGuardDeathPenaltyPatch { private const int NotCaptured = -1; [HarmonyPatch(typeof(HUDManager), "ApplyPenalty")] [HarmonyPrefix] private static void PreApplyPenalty(out int __state) { __state = -1; try { if (QuotaGuardCompanyPatch.GetCrewEffectiveTier() >= 1) { Terminal val = Object.FindObjectOfType(); if (!((Object)(object)val == (Object)null)) { __state = val.groupCredits; } } } catch (Exception arg) { __state = -1; ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"QuotaGuardDeathPenaltyPatch.PreApplyPenalty: {arg}"); } } } [HarmonyPatch(typeof(HUDManager), "ApplyPenalty")] [HarmonyPostfix] private static void PostApplyPenalty(HUDManager __instance, int __state) { if (__state == -1) { return; } try { Terminal val = Object.FindObjectOfType(); if ((Object)(object)val == (Object)null) { return; } int num = __state - val.groupCredits; if (num > 0) { int num2 = (int)((float)num * 0.5f); val.groupCredits = __state - num2; if ((Object)(object)__instance?.statsUIElements?.penaltyTotal != (Object)null) { ((TMP_Text)__instance.statsUIElements.penaltyTotal).text = $"DUE: ${num2}"; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"QuotaGuard: crew-death credit penalty halved ({num} -> {num2})."); } } } catch (Exception arg) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"QuotaGuardDeathPenaltyPatch.PostApplyPenalty: {arg}"); } } } } [HarmonyPatch] internal static class QuotaGuardDeadlinePatch { [HarmonyPatch(typeof(TimeOfDay), "SetNewProfitQuota")] [HarmonyPostfix] private static void AfterSetNewProfitQuota(TimeOfDay __instance) { try { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsServer && QuotaGuardCompanyPatch.GetCrewEffectiveTier() >= 2) { __instance.timeUntilDeadline = __instance.totalTime * 4f; __instance.UpdateProfitQuotaCurrentTime(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"QuotaGuard: extended new quota deadline to {4} days."); } } } catch (Exception arg) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"QuotaGuardDeadlinePatch.AfterSetNewProfitQuota: {arg}"); } } } } [HarmonyPatch] internal static class RetaliationPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnStunRequest; } private const float MELEE_RANGE = 8f; private const float TRACKER_VALIDITY_RANGE = 15f; private const float TRACKER_VALIDITY_WINDOW = 0.5f; private const string MSG_STUN_REQUEST = "Y4NGZ_Retaliation_Stun"; private const int STUN_PAYLOAD_BYTES = 12; internal const float MAX_RELAYED_STUN_SECONDS = 1f; private static bool _handlersRegistered; private static AudioClip _sparkClip; private static bool _sparkClipSearched; private static EnemyAI _lastAttacker; private static float _lastAttackerTime = -1f; private static void RecordAttacker(EnemyAI enemy) { if (!((Object)(object)enemy == (Object)null)) { _lastAttacker = enemy; _lastAttackerTime = Time.time; } } [HarmonyPatch(typeof(EnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static void PreEnemyAIOnCollideWithPlayer(EnemyAI __instance, Collider other) { if (!((Object)(object)other == (Object)null)) { PlayerControllerB component = ((Component)other).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { RecordAttacker(__instance); } } } private static EnemyAI GetRecentAttacker(PlayerControllerB player) { //IL_0037: 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) if ((Object)(object)_lastAttacker == (Object)null) { return null; } if (Time.time - _lastAttackerTime > 0.5f) { return null; } if (_lastAttacker.isEnemyDead) { return null; } if (Vector3.Distance(((Component)player).transform.position, ((Component)_lastAttacker).transform.position) > 15f) { return null; } return _lastAttacker; } private static EnemyAI FindTargetingEnemy(PlayerControllerB player) { //IL_0054: 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) List list = RoundManager.Instance?.SpawnedEnemies; if (list == null) { return null; } EnemyAI result = null; float num = 8f; for (int i = 0; i < list.Count; i++) { EnemyAI val = list[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !((Object)(object)val.targetPlayer != (Object)(object)player)) { float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position); if (num2 < num) { num = num2; result = val; } } } return result; } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber, bool fallDamage, CauseOfDeath causeOfDeath) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController || fallDamage || damageNumber <= 0 || __instance.isPlayerDead || !DamageCauseFilter.IsEnemyMeleeCause(causeOfDeath) || !RetaliationUpgrade.HasMergedRetaliation()) { return; } EnemyAI val = GetRecentAttacker(__instance) ?? FindTargetingEnemy(__instance); if (!((Object)(object)val == (Object)null) && !(Random.value > 0.5f)) { val.HitEnemyOnLocalClient(1, ((Component)__instance).transform.forward, __instance, false, -1); if (!val.isEnemyDead) { StunEnemy(val, 1f, __instance); } PlayReflectAudio(val); } } internal static void StunEnemy(EnemyAI enemy, float seconds, PlayerControllerB source) { //IL_0056: 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_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return; } enemy.SetEnemyStunned(true, seconds, source); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.IsServer) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ulong networkObjectId = ((NetworkBehaviour)enemy).NetworkObjectId; ((FastBufferWriter)(ref val)).WriteValueSafe(ref networkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref seconds, default(ForPrimitives)); customMessagingManager.SendNamedMessage("Y4NGZ_Retaliation_Stun", 0uL, val, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Retaliation] stun relay failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnStunRequest(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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) try { NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } ulong networkObjectId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref networkObjectId, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); num = Mathf.Clamp(num, 0f, 1f); if (!(num <= 0f)) { EnemyAI val = ResolveEnemy(networkObjectId); if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { val.SetEnemyStunned(true, num, ResolvePlayerByActualClientId(senderClientId)); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Retaliation] malformed stun request: " + ex.Message)); } } } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown if (_handlersRegistered) { return; } NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null) { return; } try { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnStunRequest; if (obj == null) { HandleNamedMessageDelegate val = OnStunRequest; <>O.<0>__OnStunRequest = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZ_Retaliation_Stun", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Retaliation] RegisterNamedMessageHandler failed: " + ex.Message)); } } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; _lastAttacker = null; _lastAttackerTime = -1f; } private static EnemyAI ResolveEnemy(ulong networkObjectId) { NetworkManager singleton = NetworkManager.Singleton; NetworkSpawnManager val = ((singleton != null) ? singleton.SpawnManager : null); if (val == null) { return null; } if (!val.SpawnedObjects.TryGetValue(networkObjectId, out var value)) { return null; } if ((Object)(object)value == (Object)null) { return null; } EnemyAI component = ((Component)value).GetComponent(); if ((Object)(object)component != (Object)null) { return component; } component = ((Component)value).GetComponentInChildren(); if ((Object)(object)component != (Object)null) { return component; } return ((Component)value).GetComponentInParent(); } private static PlayerControllerB ResolvePlayerByActualClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].actualClientId == clientId) { return array[i]; } } return null; } private static void PlayReflectAudio(EnemyAI enemy) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) AudioClip val = ResolveSparkClip(); if (!((Object)(object)val == (Object)null)) { AudioSource.PlayClipAtPoint(val, ((Component)enemy).transform.position + Vector3.up * 1f, 0.8f); } } private static AudioClip ResolveSparkClip() { if (_sparkClipSearched) { return _sparkClip; } _sparkClipSearched = true; AudioClip[] array = Resources.FindObjectsOfTypeAll(); AudioClip[] array2 = array; foreach (AudioClip val in array2) { if (!((Object)(object)val == (Object)null)) { string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("shock") || text.Contains("zap") || text.Contains("spark") || text.Contains("electric")) { _sparkClip = val; return _sparkClip; } } } array2 = array; foreach (AudioClip val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { string text2 = ((Object)val2).name.ToLowerInvariant(); if (text2.Contains("impact") || text2.Contains("hit") || text2.Contains("zap")) { _sparkClip = val2; return _sparkClip; } } } return null; } } [HarmonyPatch] internal static class ScannerTransporterPatch { internal sealed class SlotSwitchScope : IDisposable { private PlayerControllerB _player; internal SlotSwitchScope(PlayerControllerB player) { _player = player; _player.twoHanded = false; } public void Dispose() { PlayerControllerB player = _player; _player = null; if ((Object)(object)player != (Object)null) { SyncTwoHandedFlagsToHeldItem(player); } } } private const float MinCarryWeight = 1f; private const float MaxCarryWeight = 10f; [HarmonyPatch(typeof(HUDManager), "MeetsScanNodeRequirements")] [HarmonyPrefix] private static void BetterScannerRangePrefix(ScanNodeProperties node, out int __state) { __state = 0; if (!((Object)(object)node == (Object)null) && node.maxRange > 0 && FieldOpticsUpgrade.GetTier() > 0) { __state = node.maxRange; node.maxRange = Mathf.Max(node.minRange + 1, Mathf.CeilToInt((float)node.maxRange * FieldOpticsUpgrade.GetRangeMultiplier())); } } [HarmonyPatch(typeof(HUDManager), "MeetsScanNodeRequirements")] [HarmonyPostfix] private static void BetterScannerRangePostfix(ScanNodeProperties node, int __state) { if (!((Object)(object)node == (Object)null) && __state > 0) { node.maxRange = __state; } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void ApplyTransporterCarryWeight(PlayerControllerB __instance) { if (!IsLocalPlayer(__instance)) { return; } float carriedItemWeightPenalty = GetCarriedItemWeightPenalty(__instance); float carryWeightMultiplier = TransporterUpgrade.GetCarryWeightMultiplier(); float num = Mathf.Clamp(1f + carriedItemWeightPenalty * carryWeightMultiplier, 1f, 10f); if (!(Mathf.Abs(__instance.carryWeight - num) <= 0.005f)) { __instance.carryWeight = num; StartOfRound instance = StartOfRound.Instance; if (instance != null) { instance.SendChangedWeightEvent(); } } } [HarmonyPatch(typeof(PlayerControllerB), "FirstEmptyItemSlot")] [HarmonyPostfix] private static void LimitTwoHandedInventory(PlayerControllerB __instance, GrabbableObject attemptingGrab, ref int __result) { if (OptionalPluginCapabilities.NativeInventoryAvailable && __result != -1 && IsLocalPlayer(__instance) && !((Object)(object)attemptingGrab == (Object)null) && !((Object)(object)attemptingGrab.itemProperties == (Object)null) && attemptingGrab.itemProperties.twoHanded) { int twoHandedLimit = NativeInventoryModel.GetTwoHandedLimit(ExtraSlotUpgrade.GetTier()); if (CountTwoHandedItems(__instance) >= twoHandedLimit) { __result = -1; } } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] private static void AllowSecondTwoHandedGrabPrefix(PlayerControllerB __instance, out SlotSwitchScope __state) { __state = null; if (CanRelaxTwoHandedHandsFull(__instance) && CountTwoHandedItems(__instance) < 2) { __state = new SlotSwitchScope(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyFinalizer] private static Exception AllowSecondTwoHandedGrabFinalizer(Exception __exception, SlotSwitchScope __state) { __state?.Dispose(); return __exception; } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyPrefix] private static void AllowTwoHandedSlotSwitchPrefix(PlayerControllerB __instance, out SlotSwitchScope __state) { __state = BeginSlotSwitchScope(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ScrollMouse_performed")] [HarmonyFinalizer] private static Exception AllowTwoHandedSlotSwitchFinalizer(Exception __exception, SlotSwitchScope __state) { __state?.Dispose(); return __exception; } [HarmonyPatch(typeof(PlayerControllerB), "UseUtilitySlot_performed")] [HarmonyPrefix] private static void AllowTwoHandedUtilitySwitchPrefix(PlayerControllerB __instance, out SlotSwitchScope __state) { __state = BeginSlotSwitchScope(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "UseUtilitySlot_performed")] [HarmonyFinalizer] private static Exception AllowTwoHandedUtilitySwitchFinalizer(Exception __exception, SlotSwitchScope __state) { __state?.Dispose(); return __exception; } internal static SlotSwitchScope BeginSlotSwitchScope(PlayerControllerB player) { if (!CanRelaxTwoHandedHandsFull(player)) { return null; } return new SlotSwitchScope(player); } private static bool CanRelaxTwoHandedHandsFull(PlayerControllerB player) { if (IsLocalPlayer(player) && OptionalPluginCapabilities.NativeInventoryAvailable && ExtraSlotUpgrade.CanCarryTwoTwoHandedItems()) { return player.twoHanded; } return false; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static float GetCarriedItemWeightPenalty(PlayerControllerB player) { float num = 0f; if ((Object)(object)player == (Object)null) { return num; } if (player.ItemSlots != null) { for (int i = 0; i < player.ItemSlots.Length; i++) { num += GetItemWeightPenalty(player.ItemSlots[i]); } } return num + GetItemWeightPenalty(player.ItemOnlySlot); } private static float GetItemWeightPenalty(GrabbableObject item) { if ((Object)(object)item == (Object)null || (Object)(object)item.itemProperties == (Object)null) { return 0f; } return Mathf.Max(0f, item.itemProperties.weight - 1f); } private static int CountTwoHandedItems(PlayerControllerB player) { int num = 0; if ((Object)(object)player == (Object)null) { return num; } if (player.ItemSlots != null) { for (int i = 0; i < player.ItemSlots.Length; i++) { GrabbableObject val = player.ItemSlots[i]; if ((Object)(object)val != (Object)null && (Object)(object)val.itemProperties != (Object)null && val.itemProperties.twoHanded) { num++; } } } if ((Object)(object)player.ItemOnlySlot != (Object)null && (Object)(object)player.ItemOnlySlot.itemProperties != (Object)null && player.ItemOnlySlot.itemProperties.twoHanded) { num++; } return num; } private static void SyncTwoHandedFlagsToHeldItem(PlayerControllerB player) { if (!((Object)(object)player == (Object)null)) { GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null || (Object)(object)currentlyHeldObjectServer.itemProperties == (Object)null) { player.twoHanded = false; player.twoHandedAnimation = false; } else { player.twoHanded = currentlyHeldObjectServer.itemProperties.twoHanded; player.twoHandedAnimation = currentlyHeldObjectServer.itemProperties.twoHandedAnimation; } } } } internal static class ScavengerCompanyPatch { private const string ShipSystemsAssemblyName = "Y4NGZShipSystems"; private static readonly ConditionalWeakTable> LastHolders = new ConditionalWeakTable>(); private static bool _initialized; internal static void Initialize() { if (_initialized) { return; } if (!OptionalPluginCapabilities.ShipSystems) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Scavenger] Y4NGZ Ship Systems not present; fuel-chute integration disabled."); } return; } _initialized = true; try { InstallPatches(); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Scavenger] Failed to initialize fuel-chute integration: " + ex.Message)); } } } private static void InstallPatches() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Expected O, but got Unknown //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Expected O, but got Unknown //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Expected O, but got Unknown Harmony harmony = new Harmony("com.y4ngz.upgrades"); MethodInfo target = AccessTools.Method(typeof(PlayerControllerB), "DiscardHeldObject", new Type[4] { typeof(bool), typeof(NetworkObject), typeof(Vector3), typeof(bool) }, (Type[])null); TryPatch(harmony, target, new HarmonyMethod(typeof(ScavengerCompanyPatch), "DiscardHeldObjectPrefix", (Type[])null), null, "PlayerControllerB.DiscardHeldObject"); MethodInfo target2 = AccessTools.Method(typeof(PlayerControllerB), "PlaceGrabbableObject", new Type[4] { typeof(Transform), typeof(Vector3), typeof(bool), typeof(GrabbableObject) }, (Type[])null); TryPatch(harmony, target2, null, new HarmonyMethod(typeof(ScavengerCompanyPatch), "PlaceGrabbableObjectPostfix", (Type[])null), "PlayerControllerB.PlaceGrabbableObject"); Type type = CompanyType("FuelChuteController"); if (type == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)"[Scavenger] Y4NGZShipSystems FuelChuteController type was not found; fuel bonus disabled."); } } else { MethodInfo target3 = AccessTools.Method(type, "SinkFuelItemRoutine", new Type[2] { typeof(GrabbableObject), typeof(float) }, (Type[])null); TryPatch(harmony, target3, new HarmonyMethod(typeof(ScavengerCompanyPatch), "SinkFuelItemRoutinePrefix", (Type[])null), null, "FuelChuteController.SinkFuelItemRoutine"); } } private static void DiscardHeldObjectPrefix(PlayerControllerB __instance) { try { if ((Object)(object)__instance != (Object)null) { StampLastHolder(__instance.currentlyHeldObjectServer, __instance.actualClientId); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Scavenger] Failed to track discarded fuel-item holder: " + ex.Message)); } } } private static void PlaceGrabbableObjectPostfix(PlayerControllerB __instance, GrabbableObject placeObject) { try { if ((Object)(object)__instance != (Object)null) { StampLastHolder(placeObject, __instance.actualClientId); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Scavenger] Failed to track placed fuel-item holder: " + ex.Message)); } } } private static void StampLastHolder(GrabbableObject grabbable, ulong clientId) { if (!((Object)(object)grabbable == (Object)null)) { LastHolders.GetOrCreateValue(grabbable).Value = clientId; } } private static void SinkFuelItemRoutinePrefix(GrabbableObject grabbable, ref float fuelValue) { try { if ((Object)(object)grabbable == (Object)null || !LastHolders.TryGetValue(grabbable, out var value)) { return; } ulong value2 = value.Value; int tier = UpgradeTierSync.GetTier(value2, "scavenger"); if (tier > 0) { float num = fuelValue; fuelValue *= ScavengerUpgrade.GetFuelMultiplier(tier); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)$"[Scavenger] Fuel bonus for client {value2}: {num:0.##} -> {fuelValue:0.##}."); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Scavenger] Fuel bonus failed safely: " + ex.Message)); } } } private static void TryPatch(Harmony harmony, MethodBase target, HarmonyMethod prefix, HarmonyMethod postfix, string targetName) { if (target == null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Scavenger] Patch target " + targetName + " was not found; continuing without it.")); } return; } try { harmony.Patch(target, prefix, postfix, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Scavenger] Failed to patch " + targetName + "; continuing without it: " + ex.Message)); } } } private static Type CompanyType(string typeName) { return Type.GetType("Y4NGZCompany.ShipSystems.Fuel." + typeName + ", Y4NGZShipSystems", throwOnError: false) ?? FindShipSystemsTypeByName(typeName); } private static Type FindShipSystemsTypeByName(string typeName) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (assembly == null || assembly.GetName().Name != "Y4NGZShipSystems") { continue; } try { Type[] types = assembly.GetTypes(); foreach (Type type in types) { if (type != null && string.Equals(type.Name, typeName, StringComparison.Ordinal)) { return type; } } } catch (ReflectionTypeLoadException ex) { Type[] types = ex.Types; foreach (Type type2 in types) { if (type2 != null && string.Equals(type2.Name, typeName, StringComparison.Ordinal)) { return type2; } } } catch (Exception ex2) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Scavenger] Failed to inspect Y4NGZShipSystems types: " + ex2.Message)); } } } return null; } } internal static class ShadowStepNetState { private struct Entry { internal byte Tier; internal bool Cloaked; } [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetStateServerRpc; public static HandleNamedMessageDelegate <1>__OnRequestAllServerRpc; public static HandleNamedMessageDelegate <2>__OnSetStateClientRpc; public static HandleNamedMessageDelegate <3>__OnSyncAllClientRpc; } private const string MSG_SET_SERVER = "Y4NGZShadowStep.SetServerRpc"; private const string MSG_SET_CLIENT = "Y4NGZShadowStep.SetClientRpc"; private const string MSG_REQUEST_ALL_SERVER = "Y4NGZShadowStep.RequestAllServerRpc"; private const string MSG_SYNC_ALL_CLIENT = "Y4NGZShadowStep.SyncAllClientRpc"; private const byte MaxSyncedTier = 3; private static readonly Dictionary StatesByClient = new Dictionary(); private static bool _handlersRegistered; private static NetworkManager _registeredNetworkManager; internal static int GetTier(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0; } if (!StatesByClient.TryGetValue(player.actualClientId, out var value)) { return 0; } return value.Tier; } internal static bool IsCloaked(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (StatesByClient.TryGetValue(player.actualClientId, out var value)) { return value.Cloaked; } return false; } internal static void RegisterNetworkHandlers() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //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: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || (_handlersRegistered && _registeredNetworkManager == singleton)) { return; } if (_handlersRegistered) { UnregisterNetworkHandlers(); } try { if (singleton.IsServer) { object obj = <>O.<0>__OnSetStateServerRpc; if (obj == null) { HandleNamedMessageDelegate val2 = OnSetStateServerRpc; <>O.<0>__OnSetStateServerRpc = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZShadowStep.SetServerRpc", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequestAllServerRpc; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnRequestAllServerRpc; <>O.<1>__OnRequestAllServerRpc = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZShadowStep.RequestAllServerRpc", (HandleNamedMessageDelegate)obj2); } object obj3 = <>O.<2>__OnSetStateClientRpc; if (obj3 == null) { HandleNamedMessageDelegate val4 = OnSetStateClientRpc; <>O.<2>__OnSetStateClientRpc = val4; obj3 = (object)val4; } val.RegisterNamedMessageHandler("Y4NGZShadowStep.SetClientRpc", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnSyncAllClientRpc; if (obj4 == null) { HandleNamedMessageDelegate val5 = OnSyncAllClientRpc; <>O.<3>__OnSyncAllClientRpc = val5; obj4 = (object)val5; } val.RegisterNamedMessageHandler("Y4NGZShadowStep.SyncAllClientRpc", (HandleNamedMessageDelegate)obj4); _handlersRegistered = true; _registeredNetworkManager = singleton; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Shadow Step] network handlers registered."); } } catch (Exception arg) { _handlersRegistered = false; _registeredNetworkManager = null; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"[Shadow Step] handler registration failed: {arg}"); } } } internal static void Clear() { StatesByClient.Clear(); UnregisterNetworkHandlers(); } internal static void ResetForNewCycle() { StatesByClient.Clear(); RegisterNetworkHandlers(); ShadowStepPatch.PublishLocalState(force: true); RequestAllFromServer(); } internal static void RequestAllFromServer() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.CustomMessagingManager == null || singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4, (Allocator)2, -1); try { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZShadowStep.RequestAllServerRpc", 0uL, val, (NetworkDelivery)4); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] RequestAllFromServer failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } internal static void RemoveClient(ulong clientId) { StatesByClient.Remove(clientId); } internal static void PublishLocalState(byte tier, bool cloaked) { //IL_008a: 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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val2 == (Object)null) { return; } ApplyState(val2.actualClientId, tier, cloaked, allowVisuals: false); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsClient || !_handlersRegistered) { return; } try { if (singleton.IsServer) { BroadcastState(val2.actualClientId, tier, cloaked); return; } FastBufferWriter val3 = default(FastBufferWriter); ((FastBufferWriter)(ref val3))..ctor(4, (Allocator)2, -1); try { ((FastBufferWriter)(ref val3)).WriteValueSafe(ref tier, default(ForPrimitives)); ((FastBufferWriter)(ref val3)).WriteValueSafe(ref cloaked, default(ForPrimitives)); val.SendNamedMessage("Y4NGZShadowStep.SetServerRpc", 0uL, val3, (NetworkDelivery)4); } finally { ((FastBufferWriter)(ref val3)).Dispose(); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] PublishLocalState failed: " + ex.Message)); } } } private static void BroadcastState(ulong clientId, byte tier, bool cloaked) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(16, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref clientId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref cloaked, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZShadowStep.SetClientRpc", val, (NetworkDelivery)4); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] BroadcastState failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void OnSetStateServerRpc(ulong senderClientId, FastBufferReader reader) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } try { byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); bool cloaked = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref cloaked, default(ForPrimitives)); if (b <= 3) { ApplyState(senderClientId, b, cloaked, allowVisuals: true); BroadcastState(senderClientId, b, cloaked); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] malformed SetServer message: " + ex.Message)); } } } private static void OnSetStateClientRpc(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0035: 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_0048: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L) { return; } try { ulong clientId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref clientId, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); bool cloaked = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref cloaked, default(ForPrimitives)); if (b <= 3) { ApplyState(clientId, b, cloaked, allowVisuals: true); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] malformed SetClient message: " + ex.Message)); } } } private static void OnRequestAllServerRpc(ulong senderClientId, FastBufferReader reader) { //IL_0044: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0098: 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) //IL_00b9: 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_00eb: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer || singleton.CustomMessagingManager == null) { return; } try { int count = StatesByClient.Count; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4 + count * 12, (Allocator)2, -1); try { short num = (short)count; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); foreach (KeyValuePair item in StatesByClient) { ulong key = item.Key; ((FastBufferWriter)(ref val)).WriteValueSafe(ref key, default(ForPrimitives)); Entry value = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref value.Tier, default(ForPrimitives)); value = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref value.Cloaked, default(ForPrimitives)); } singleton.CustomMessagingManager.SendNamedMessage("Y4NGZShadowStep.SyncAllClientRpc", senderClientId, val, (NetworkDelivery)4); } finally { ((FastBufferWriter)(ref val)).Dispose(); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Shadow Step] OnRequestAllServerRpc failed: {arg}"); } } } private static void OnSyncAllClientRpc(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0038: 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_004a: 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_005c: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || singleton.IsServer || senderClientId != 0L) { return; } try { short num = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); ulong clientId = default(ulong); byte b = default(byte); bool cloaked = default(bool); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref clientId, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref cloaked, default(ForPrimitives)); if (b <= 3) { ApplyState(clientId, b, cloaked, allowVisuals: true); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] malformed SyncAll message: " + ex.Message)); } } } private static void ApplyState(ulong clientId, byte tier, bool cloaked, bool allowVisuals) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) StatesByClient.TryGetValue(clientId, out var value); bool flag = StatesByClient.ContainsKey(clientId); StatesByClient[clientId] = new Entry { Tier = tier, Cloaked = cloaked }; bool flag2 = cloaked && (!flag || !value.Cloaked); bool flag3 = !cloaked && flag && value.Cloaked; if (flag2) { ShadowStepPatch.ForceDeaggroForPlayer(ResolvePlayer(clientId)); } if (!allowVisuals || (!flag2 && !flag3)) { return; } PlayerControllerB val = ResolvePlayer(clientId); if (!((Object)(object)val == (Object)null)) { PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if (!((Object)(object)val2 != (Object)null) || !((Object)(object)val == (Object)(object)val2)) { CamoShellCloak.SetCloaked(val, cloaked); ShadowStepPatch.SpawnSmokePoof(((Component)val).transform.position); } } } internal static PlayerControllerB ResolvePlayer(ulong actualClientId) { PlayerControllerB[] array = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.allPlayerScripts : null); if (array == null) { return null; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].actualClientId == actualClientId) { return array[i]; } } return null; } private static void UnregisterNetworkHandlers() { if (!_handlersRegistered) { return; } NetworkManager val = _registeredNetworkManager ?? NetworkManager.Singleton; CustomMessagingManager val2 = ((val != null) ? val.CustomMessagingManager : null); if (val2 != null) { try { if (val.IsServer) { val2.UnregisterNamedMessageHandler("Y4NGZShadowStep.SetServerRpc"); val2.UnregisterNamedMessageHandler("Y4NGZShadowStep.RequestAllServerRpc"); } val2.UnregisterNamedMessageHandler("Y4NGZShadowStep.SetClientRpc"); val2.UnregisterNamedMessageHandler("Y4NGZShadowStep.SyncAllClientRpc"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Shadow Step] handler unregister failed: " + ex.Message)); } } } _handlersRegistered = false; _registeredNetworkManager = null; } } [HarmonyPatch] internal static class ShadowStepPatch { private static bool _externalInvisibilityActive = false; private static float _externalInvisibilityEndTime = 0f; private const string HUD_SPRITE = "shadow_hud"; private const int HUD_STACK_POSITION = 2; private const float RemoteReconcileInterval = 0.25f; private static byte _publishedTier = byte.MaxValue; private static bool _publishedCloak; private static bool _publishedOnce; private static float _nextRemoteReconcile; private static AudioClip _activationClip; private static AudioClip _deactivationClip; private static float _originalAudioVolume = 1f; private static bool _audioVolumeCaptured = false; private static AudioSource _hissSource; private static AudioClip _hissClip; private static bool _cloakEffectsActive = false; private static AudioLowPassFilter _cloakLowPassFilter; private static bool _cloakLowPassWasAdded = false; private static float _originalLowPassCutoff = 22000f; private static float _originalLowPassResonance = 1f; private const float CLOAK_AUDIO_VOLUME_SCALE = 0.72f; private const float CLOAK_LOW_PASS_CUTOFF = 850f; private const float CLOAK_LOW_PASS_RESONANCE = 1.15f; private static Canvas _cloakOverlayCanvas; private static GameObject _cloakVignetteObj; private static RawImage _cloakVignette; private static Texture2D _vignetteTexture; private static GameObject _smokePrefab; private static bool _smokePrefabSearched; private static PlayerControllerB LocalPlayer { get { if (!((Object)(object)GameNetworkManager.Instance != (Object)null)) { return null; } return GameNetworkManager.Instance.localPlayerController; } } private static AudioClip GetActivationClip() { if ((Object)(object)_activationClip != (Object)null) { return _activationClip; } int num = 44100; float num2 = 0.25f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; for (int i = 0; i < num3; i++) { float num4 = (float)i / (float)num; float num5 = num4 / num2; float num6 = Mathf.Lerp(1200f, 200f, num5); float num7 = Mathf.Exp((0f - num4) * 6f); float num8 = Mathf.Sin(MathF.PI * 2f * num6 * num4) * num7 * 1.5f; float num9 = Random.Range(-1f, 1f) * num7 * 0.3f; array[i] = Mathf.Clamp(num8 + num9, -1f, 1f); } _activationClip = AudioClip.Create("Y4NGZ_ShadowStep_PhaseOut", num3, 1, num, false); bool flag = _activationClip.SetData(array, 0); Plugin.Log.LogInfo((object)$"[Shadow Step] Generated activation clip: samples={num3}, SetData={flag}"); return _activationClip; } private static AudioClip GetDeactivationClip() { if ((Object)(object)_deactivationClip != (Object)null) { return _deactivationClip; } int num = 44100; float num2 = 0.12f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; for (int i = 0; i < num3; i++) { float num4 = (float)i / (float)num; float num5 = num4 / num2; float num6 = Mathf.Lerp(200f, 800f, num5); float num7 = Mathf.Exp((0f - num4) * 10f); array[i] = Mathf.Clamp(Mathf.Sin(MathF.PI * 2f * num6 * num4) * num7 * 1.5f, -1f, 1f); } _deactivationClip = AudioClip.Create("Y4NGZ_ShadowStep_SnapOff", num3, 1, num, false); bool flag = _deactivationClip.SetData(array, 0); Plugin.Log.LogInfo((object)$"[Shadow Step] Generated deactivation clip: samples={num3}, SetData={flag}"); return _deactivationClip; } private static AudioClip GetHissClip() { if ((Object)(object)_hissClip != (Object)null) { return _hissClip; } int num = 44100; float num2 = 2f; int num3 = (int)((float)num * num2); float[] array = new float[num3]; Random random = new Random(42); for (int i = 0; i < num3; i++) { array[i] = (float)(random.NextDouble() * 2.0 - 1.0) * 0.12f; } _hissClip = AudioClip.Create("Y4NGZ_ShadowStep_Hiss", num3, 1, num, false); _hissClip.SetData(array, 0); return _hissClip; } private static bool IsLocal(PlayerControllerB player) { PlayerControllerB localPlayer = LocalPlayer; if ((Object)(object)localPlayer != (Object)null && (Object)(object)player != (Object)null) { return (Object)(object)player == (Object)(object)localPlayer; } return false; } internal static bool IsPlayerCloaked(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (IsLocal(player)) { return IsAnyInvisibilityActive(); } return ShadowStepNetState.IsCloaked(player); } private static int GetTierFor(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return 0; } if (IsLocal(player)) { return ShadowStepUpgrade.GetTier(); } return ShadowStepNetState.GetTier(player); } private static float GetDetectionMultiplierFor(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || !player.isPlayerControlled) { return 1f; } if (IsPlayerCloaked(player)) { return 0f; } switch (GetTierFor(player)) { case 1: if (!player.isCrouching) { return 1f; } return 0.75f; case 2: case 3: if (!player.isSprinting) { return 0.75f; } return 1f; default: return 1f; } } private static float DetectionDistance(EnemyAI enemy, PlayerControllerB player) { //IL_003e: 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) Transform obj = (((Object)(object)enemy.eye != (Object)null) ? enemy.eye : ((Component)enemy).transform); Transform val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((Component)player).transform); return Vector3.Distance(obj.position, val.position); } private static bool ShouldDropFromSight(EnemyAI enemy, PlayerControllerB player, float baseRange) { float detectionMultiplierFor = GetDetectionMultiplierFor(player); if (detectionMultiplierFor >= 1f) { return false; } if (detectionMultiplierFor <= 0f) { return true; } if (baseRange <= 0f) { return false; } return DetectionDistance(enemy, player) > baseRange * detectionMultiplierFor; } [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForPlayer")] [HarmonyPostfix] private static void PostCheckLineOfSightForPlayer(EnemyAI __instance, ref PlayerControllerB __result, int range) { try { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__result == (Object)null) && ShouldDropFromSight(__instance, __result, range)) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] CheckLineOfSightForPlayer patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "CheckLineOfSightForClosestPlayer")] [HarmonyPostfix] private static void PostCheckLineOfSightForClosestPlayer(EnemyAI __instance, ref PlayerControllerB __result, int range) { try { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__result == (Object)null) && ShouldDropFromSight(__instance, __result, range)) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] CheckLineOfSightForClosestPlayer patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "GetAllPlayersInLineOfSight")] [HarmonyPostfix] private static void PostGetAllPlayersInLineOfSight(EnemyAI __instance, ref PlayerControllerB[] __result, int range) { try { if ((Object)(object)__instance == (Object)null || __result == null || __result.Length == 0) { return; } bool flag = false; for (int i = 0; i < __result.Length; i++) { if ((Object)(object)__result[i] != (Object)null && ShouldDropFromSight(__instance, __result[i], range)) { flag = true; break; } } if (!flag) { return; } List list = new List(__result.Length); for (int j = 0; j < __result.Length; j++) { if ((Object)(object)__result[j] != (Object)null && !ShouldDropFromSight(__instance, __result[j], range)) { list.Add(__result[j]); } } __result = list.ToArray(); } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] GetAllPlayersInLineOfSight patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "GetClosestPlayer")] [HarmonyPostfix] private static void PostGetClosestPlayer(EnemyAI __instance, ref PlayerControllerB __result, bool requireLineOfSight, bool cannotBeInShip, bool cannotBeNearShip) { //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_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)__instance == (Object)null || (Object)(object)__result == (Object)null || GetDetectionMultiplierFor(__result) >= 1f) { return; } PlayerControllerB[] array = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.allPlayerScripts : null); if (array == null) { return; } PlayerControllerB val = null; float num = float.MaxValue; float mostOptimalDistance = 0f; foreach (PlayerControllerB val2 in array) { if ((Object)(object)val2 == (Object)null || !__instance.PlayerIsTargetable(val2, cannotBeInShip, false, true) || (cannotBeNearShip && (val2.isInElevator || IsNearSpawnDenialPoint(val2))) || (requireLineOfSight && Physics.Linecast(((Component)__instance).transform.position + Vector3.up * 0.25f, ((Component)val2).transform.position, 256))) { continue; } float detectionMultiplierFor = GetDetectionMultiplierFor(val2); if (!(detectionMultiplierFor <= 0f)) { float num2 = Vector3.Distance(((Component)__instance).transform.position, ((Component)val2).transform.position); float num3 = num2 / detectionMultiplierFor; if (num3 < num) { num = num3; mostOptimalDistance = num2; val = val2; } } } __result = val; if ((Object)(object)val != (Object)null) { __instance.mostOptimalDistance = mostOptimalDistance; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] GetClosestPlayer patch error: {arg}"); } } private static bool IsNearSpawnDenialPoint(PlayerControllerB player) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) GameObject[] array = (((Object)(object)RoundManager.Instance != (Object)null) ? RoundManager.Instance.spawnDenialPoints : null); if (array == null) { return false; } for (int i = 0; i < array.Length; i++) { if (!((Object)(object)array[i] == (Object)null) && Vector3.Distance(array[i].transform.position, ((Component)player).transform.position) < 10f) { return true; } } return false; } [HarmonyPatch(typeof(EnemyAI), "PlayerIsTargetable")] [HarmonyPostfix] private static void PostPlayerIsTargetable(ref bool __result, PlayerControllerB playerScript) { try { if (__result && !((Object)(object)playerScript == (Object)null) && IsPlayerCloaked(playerScript)) { __result = false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] PlayerIsTargetable patch error: {arg}"); } } [HarmonyPatch(typeof(EnemyAI), "MeetsStandardPlayerCollisionConditions")] [HarmonyPostfix] private static void PostMeetsStandardPlayerCollisionConditions(ref PlayerControllerB __result) { try { if (!((Object)(object)__result == (Object)null) && IsPlayerCloaked(__result)) { __result = null; } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] MeetsStandardPlayerCollisionConditions patch error: {arg}"); } } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && IsLocal(__instance)) { CamoShellCloak.Tick(); ReconcileRemoteCloakVisuals(); if (((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled) { PublishLocalState(force: false); PollKeybind(__instance); UpdateInvisibilityTimer(__instance); UpdateExternalInvisibilityTimer(__instance); UpdateHUD(); UpdateCloakVignette(); } } } internal static void PublishLocalState(bool force) { byte b = (byte)Mathf.Clamp(ShadowStepUpgrade.GetTier(), 0, 3); bool flag = IsAnyInvisibilityActive(); if (force || !_publishedOnce || b != _publishedTier || flag != _publishedCloak) { _publishedTier = b; _publishedCloak = flag; _publishedOnce = true; ShadowStepNetState.PublishLocalState(b, flag); } } private static void ReconcileRemoteCloakVisuals() { if (Time.time < _nextRemoteReconcile) { return; } _nextRemoteReconcile = Time.time + 0.25f; PlayerControllerB[] array = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.allPlayerScripts : null); if (array == null) { return; } foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && !IsLocal(val)) { bool flag = val.isPlayerControlled && !val.isPlayerDead && ShadowStepNetState.IsCloaked(val); if (CamoShellCloak.IsCloaked(val) != flag) { CamoShellCloak.SetCloaked(val, flag); } } } } private static void PollKeybind(PlayerControllerB player) { if (ShadowStepUpgrade.HasActiveAbility() && !player.isPlayerDead && (!((Object)(object)player.quickMenuManager != (Object)null) || !player.quickMenuManager.isMenuOpen) && !player.isTypingChat && !player.inSpecialInteractAnimation && !player.inTerminalMenu && UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.ShadowStep)) { ActivateInvisibility(player); } } private static void ActivateInvisibility(PlayerControllerB player) { //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!ShadowStepUpgrade.HasActiveAbility() || ShadowStepUpgrade.IsInvisible) { return; } if (Time.time < ShadowStepUpgrade.CooldownEndTime) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("SHADOW STEP", "Still on cooldown.", true, false, "LC_Tip1"); } return; } ShadowStepUpgrade.IsInvisible = true; ShadowStepUpgrade.InvisibilityEndTime = Time.time + 6f; ShadowStepUpgrade.CooldownEndTime = ShadowStepUpgrade.InvisibilityEndTime + 120f; PublishLocalState(force: true); ForceDeaggroForPlayer(player); PlayLocalShadowStepClip(GetActivationClip(), ((Component)player).transform.position, 0.75f); StartCloakEffects(); Plugin.Log.LogInfo((object)$"[Shadow Step] Invisibility ACTIVATED - duration={6f}s, IsInvisible={ShadowStepUpgrade.IsInvisible}"); } internal static void ActivateExternalInvisibility(PlayerControllerB player, float seconds, string sourceLabel) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player == (Object)null) && !(seconds <= 0f) && IsLocal(player) && !player.isPlayerDead) { bool num = IsAnyInvisibilityActive(); _externalInvisibilityActive = true; _externalInvisibilityEndTime = Mathf.Max(_externalInvisibilityEndTime, Time.time + seconds); PublishLocalState(force: true); ForceDeaggroForPlayer(player); if (!num) { PlayLocalShadowStepClip(GetActivationClip(), ((Component)player).transform.position, 0.75f); } StartCloakEffects(); Plugin.Log.LogInfo((object)string.Format("[Shadow Step] External invisibility from {0} active for {1:F1}s.", sourceLabel ?? "upgrade", seconds)); } } private static void UpdateInvisibilityTimer(PlayerControllerB player) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if (ShadowStepUpgrade.IsInvisible && !(Time.time < ShadowStepUpgrade.InvisibilityEndTime)) { ShadowStepUpgrade.IsInvisible = false; if (!IsAnyInvisibilityActive()) { PublishLocalState(force: true); PlayLocalShadowStepClip(GetDeactivationClip(), ((Component)player).transform.position, 0.7f); StopCloakEffects(); } Plugin.Log.LogInfo((object)"[Shadow Step] Invisibility ENDED - cooldown active."); } } private static void UpdateExternalInvisibilityTimer(PlayerControllerB player) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) if (!_externalInvisibilityActive || Time.time < _externalInvisibilityEndTime) { return; } _externalInvisibilityActive = false; _externalInvisibilityEndTime = 0f; if (!ShadowStepUpgrade.IsInvisible) { PublishLocalState(force: true); if ((Object)(object)player != (Object)null) { PlayLocalShadowStepClip(GetDeactivationClip(), ((Component)player).transform.position, 0.7f); } StopCloakEffects(); } } internal static void ForceDeaggroForPlayer(PlayerControllerB player) { try { if ((Object)(object)player == (Object)null) { return; } NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } EnemyAI[] array = Object.FindObjectsOfType(); int num = 0; foreach (EnemyAI val in array) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead && !((Object)(object)val.targetPlayer != (Object)(object)player)) { val.targetPlayer = null; val.movingTowardsTargetPlayer = false; if (val.currentBehaviourStateIndex != 0) { val.SwitchToBehaviourState(0); } num++; } } if (num > 0) { Plugin.Log.LogInfo((object)$"[Shadow Step] Host de-aggroed {num} enemies from player {player.playerClientId}."); } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] ForceDeaggroForPlayer error: {arg}"); } } private static void EnsureSpriteHUD() { if (!((Object)(object)UpgradeHUDManager.GetHUDElement("shadow_hud") != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null)) { Canvas val = (((Object)(object)HUDManager.Instance.playerScreenTexture != (Object)null) ? ((Graphic)HUDManager.Instance.playerScreenTexture).canvas : null); if (!((Object)(object)val == (Object)null)) { UpgradeHUDManager.CreateHUDElement("shadow_hud", 2, ((Component)val).transform); } } } private static void UpdateHUD() { if (!ShadowStepUpgrade.IsUnlocked() || !ShadowStepUpgrade.HasActiveAbility()) { GameObject hUDElement = UpgradeHUDManager.GetHUDElement("shadow_hud"); if ((Object)(object)hUDElement != (Object)null) { hUDElement.SetActive(false); } return; } EnsureSpriteHUD(); GameObject hUDElement2 = UpgradeHUDManager.GetHUDElement("shadow_hud"); if (!((Object)(object)hUDElement2 == (Object)null)) { hUDElement2.SetActive(true); if (ShadowStepUpgrade.IsInvisible) { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: false); } else if (Time.time < ShadowStepUpgrade.CooldownEndTime) { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: true); float num = ShadowStepUpgrade.CooldownEndTime - Time.time; UpgradeHUDManager.UpdateFillBar("shadow_hud", num / 120f); } else { UpgradeHUDManager.SetCooldownActive("shadow_hud", active: false); } } } private static void StartCloakEffects() { if (!_cloakEffectsActive) { _cloakEffectsActive = true; PlayerControllerB localPlayer = LocalPlayer; if ((Object)(object)localPlayer != (Object)null) { CamoShellCloak.Cloak(localPlayer); StartAudioDampening(localPlayer); _hissSource = ((Component)(((Object)(object)localPlayer.gameplayCamera != (Object)null) ? ((Component)localPlayer.gameplayCamera).transform : ((Component)localPlayer).transform)).gameObject.AddComponent(); _hissSource.clip = GetHissClip(); _hissSource.loop = true; _hissSource.volume = 0.09f; _hissSource.spatialBlend = 0f; _hissSource.playOnAwake = false; _hissSource.Play(); } CreateCloakVignette(); } } private static void StopCloakEffects() { _cloakEffectsActive = false; PlayerControllerB localPlayer = LocalPlayer; if ((Object)(object)localPlayer != (Object)null) { CamoShellCloak.Decloak(localPlayer); } if (_audioVolumeCaptured) { AudioListener.volume = _originalAudioVolume; _audioVolumeCaptured = false; } StopAudioDampening(); if ((Object)(object)_hissSource != (Object)null) { _hissSource.Stop(); Object.Destroy((Object)(object)_hissSource); _hissSource = null; } DestroyCloakVignette(); } private static void StartAudioDampening(PlayerControllerB player) { if (!_audioVolumeCaptured) { _originalAudioVolume = AudioListener.volume; _audioVolumeCaptured = true; } AudioListener.volume = Mathf.Clamp01(_originalAudioVolume * 0.72f); GameObject val = null; AudioListener val2 = Object.FindObjectOfType(); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).gameObject; } if ((Object)(object)val == (Object)null && (Object)(object)player != (Object)null && (Object)(object)player.gameplayCamera != (Object)null) { val = ((Component)player.gameplayCamera).gameObject; } if (!((Object)(object)val == (Object)null)) { _cloakLowPassFilter = val.GetComponent(); _cloakLowPassWasAdded = (Object)(object)_cloakLowPassFilter == (Object)null; if ((Object)(object)_cloakLowPassFilter == (Object)null) { _cloakLowPassFilter = val.AddComponent(); } else { _originalLowPassCutoff = _cloakLowPassFilter.cutoffFrequency; _originalLowPassResonance = _cloakLowPassFilter.lowpassResonanceQ; } _cloakLowPassFilter.cutoffFrequency = 850f; _cloakLowPassFilter.lowpassResonanceQ = 1.15f; } } private static void StopAudioDampening() { if ((Object)(object)_cloakLowPassFilter != (Object)null) { if (_cloakLowPassWasAdded) { Object.Destroy((Object)(object)_cloakLowPassFilter); } else { _cloakLowPassFilter.cutoffFrequency = _originalLowPassCutoff; _cloakLowPassFilter.lowpassResonanceQ = _originalLowPassResonance; } } _cloakLowPassFilter = null; _cloakLowPassWasAdded = false; _originalLowPassCutoff = 22000f; _originalLowPassResonance = 1f; } private static void PlayLocalShadowStepClip(AudioClip clip, Vector3 position, float volume) { //IL_006f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)clip == (Object)null) { return; } AudioSource val = HUDManager.Instance?.UIAudio; if ((Object)(object)val != (Object)null) { val.PlayOneShot(clip, volume); } PlayerControllerB localPlayer = LocalPlayer; if ((Object)(object)localPlayer != (Object)null && (Object)(object)localPlayer.gameplayCamera != (Object)null) { AudioSource component = ((Component)localPlayer.gameplayCamera).GetComponent(); if ((Object)(object)component != (Object)null) { component.PlayOneShot(clip, volume * 0.65f); } } else { AudioSource.PlayClipAtPoint(clip, position, volume * 0.5f); } } private static Texture2D GetVignetteTexture() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteTexture != (Object)null) { return _vignetteTexture; } int num = 256; _vignetteTexture = new Texture2D(num, num, (TextureFormat)4, false); Color[] array = (Color[])(object)new Color[num * num]; float num2 = (float)num / 2f; for (int i = 0; i < num; i++) { for (int j = 0; j < num; j++) { float num3 = ((float)j - num2) / num2; float num4 = ((float)i - num2) / num2; float num5 = Mathf.Clamp01((Mathf.Sqrt(num3 * num3 + num4 * num4) - 0.38f) / 0.62f); num5 = num5 * num5 * (3f - 2f * num5); array[i * num + j] = new Color(0f, 0f, 0f, num5); } } _vignetteTexture.SetPixels(array); _vignetteTexture.Apply(); return _vignetteTexture; } private static void CreateCloakVignette() { //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown if (!((Object)(object)_cloakVignetteObj != (Object)null)) { Canvas val = null; if ((Object)(object)HUDManager.Instance != (Object)null && (Object)(object)HUDManager.Instance.playerScreenTexture != (Object)null) { val = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; } if ((Object)(object)val == (Object)null) { GameObject val2 = new GameObject("Y4NGZ_ShadowStep_OverlayCanvas"); _cloakOverlayCanvas = val2.AddComponent(); _cloakOverlayCanvas.renderMode = (RenderMode)0; _cloakOverlayCanvas.sortingOrder = 320; val2.AddComponent(); val2.AddComponent(); Object.DontDestroyOnLoad((Object)val2); val = _cloakOverlayCanvas; } _cloakVignetteObj = new GameObject("ShadowStepCloakVignette"); _cloakVignetteObj.transform.SetParent(((Component)val).transform, false); RectTransform obj = _cloakVignetteObj.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _cloakVignette = _cloakVignetteObj.AddComponent(); _cloakVignette.texture = (Texture)(object)GetVignetteTexture(); ((Graphic)_cloakVignette).color = new Color(0f, 0.02f, 0.015f, 0.55f); ((Graphic)_cloakVignette).raycastTarget = false; _cloakVignetteObj.transform.SetAsLastSibling(); Plugin.Log.LogInfo((object)"[Shadow Step] Cloak vignette created."); } } private static void DestroyCloakVignette() { if ((Object)(object)_cloakVignetteObj != (Object)null) { Object.Destroy((Object)(object)_cloakVignetteObj); _cloakVignetteObj = null; _cloakVignette = null; } if ((Object)(object)_cloakOverlayCanvas != (Object)null) { Object.Destroy((Object)(object)((Component)_cloakOverlayCanvas).gameObject); _cloakOverlayCanvas = null; } } private static void UpdateCloakVignette() { //IL_008b: Unknown result type (might be due to invalid IL or missing references) if (_cloakEffectsActive && !((Object)(object)_cloakVignette == (Object)null)) { GameObject cloakVignetteObj = _cloakVignetteObj; if (cloakVignetteObj != null) { cloakVignetteObj.transform.SetAsLastSibling(); } float num = GetCurrentInvisibilityEndTime() - Time.time; float num2 = 2f; float num3 = 0.05f; float num4 = 0.55f; if (num < 2f) { num2 = 6f; num3 = 0.09f; num4 = 0.68f; } float num5 = num4 + Mathf.Sin(Time.time * num2) * num3; ((Graphic)_cloakVignette).color = new Color(0f, 0.02f, 0.015f, Mathf.Clamp01(num5)); } } private static bool IsAnyInvisibilityActive() { bool isInvisible = ShadowStepUpgrade.IsInvisible; bool flag = _externalInvisibilityActive && Time.time < _externalInvisibilityEndTime; return isInvisible || flag; } private static float GetCurrentInvisibilityEndTime() { float num = 0f; if (ShadowStepUpgrade.IsInvisible) { num = Mathf.Max(num, ShadowStepUpgrade.InvisibilityEndTime); } if (_externalInvisibilityActive) { num = Mathf.Max(num, _externalInvisibilityEndTime); } return num; } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { try { ShadowStepNetState.RegisterNetworkHandlers(); PublishLocalState(force: true); ShadowStepNetState.RequestAllFromServer(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Shadow Step] ConnectClientToPlayerObject hook failed: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void PostResetShip() { try { ShadowStepNetState.ResetForNewCycle(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Shadow Step] ResetShip hook failed: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "OnPlayerDC")] [HarmonyPostfix] private static void PostOnPlayerDC(int playerObjectNumber, ulong clientId) { try { PlayerControllerB val = ShadowStepNetState.ResolvePlayer(clientId); if ((Object)(object)val == (Object)null && (Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.allPlayerScripts != null && playerObjectNumber >= 0 && playerObjectNumber < StartOfRound.Instance.allPlayerScripts.Length) { val = StartOfRound.Instance.allPlayerScripts[playerObjectNumber]; } ShadowStepNetState.RemoveClient(clientId); if ((Object)(object)val != (Object)null) { CamoShellCloak.ForgetPlayer(val); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"[Shadow Step] OnPlayerDC cleanup failed: {arg}"); } } } internal static void SpawnSmokePoof(Vector3 position) { //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Expected O, but got Unknown //IL_00da: 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_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_011b: 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_0147: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01db: 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_01ec: Unknown result type (might be due to invalid IL or missing references) //IL_01f1: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: 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_025f: Unknown result type (might be due to invalid IL or missing references) //IL_028f: Expected O, but got Unknown //IL_0013: 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) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0294: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_0071: 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_0096: Unknown result type (might be due to invalid IL or missing references) GameObject val = FindSmokeParticleSystem(); if ((Object)(object)val != (Object)null) { GameObject obj = Object.Instantiate(val, position + Vector3.up, Quaternion.identity); obj.transform.localScale = Vector3.one * 0.4f; ParticleSystem component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { MainModule main = component.main; ((MainModule)(ref main)).startLifetime = MinMaxCurve.op_Implicit(0.6f); ((MainModule)(ref main)).startSize = MinMaxCurve.op_Implicit(1.5f); ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(new Color(0.3f, 0.3f, 0.3f, 0.5f)); ((MainModule)(ref main)).duration = 0.3f; ((MainModule)(ref main)).loop = false; component.Play(); } Object.Destroy((Object)(object)obj, 2f); } else { GameObject val2 = new GameObject("Y4NGZ_ShadowStep_ProceduralPoof"); val2.transform.position = position + Vector3.up; ParticleSystem val3 = val2.AddComponent(); MainModule main2 = val3.main; ((MainModule)(ref main2)).duration = 0.28f; ((MainModule)(ref main2)).loop = false; ((MainModule)(ref main2)).startLifetime = new MinMaxCurve(0.38f, 0.72f); ((MainModule)(ref main2)).startSpeed = new MinMaxCurve(0.25f, 0.85f); ((MainModule)(ref main2)).startSize = new MinMaxCurve(0.45f, 1.2f); ((MainModule)(ref main2)).startColor = new MinMaxGradient(new Color(0.08f, 0.14f, 0.13f, 0.42f), new Color(0.28f, 0.42f, 0.36f, 0.34f)); ((MainModule)(ref main2)).simulationSpace = (ParticleSystemSimulationSpace)1; ((MainModule)(ref main2)).gravityModifier = MinMaxCurve.op_Implicit(-0.03f); EmissionModule emission = val3.emission; ((EmissionModule)(ref emission)).enabled = true; ((EmissionModule)(ref emission)).rateOverTime = MinMaxCurve.op_Implicit(0f); ((EmissionModule)(ref emission)).SetBursts((Burst[])(object)new Burst[1] { new Burst(0f, (short)18) }); ShapeModule shape = val3.shape; ((ShapeModule)(ref shape)).enabled = true; ((ShapeModule)(ref shape)).shapeType = (ParticleSystemShapeType)0; ((ShapeModule)(ref shape)).radius = 0.35f; val3.Play(true); Object.Destroy((Object)(object)val2, 1.4f); GameObject val4 = new GameObject("Y4NGZ_ShadowStep_PoofLight"); val4.transform.position = position + Vector3.up; Light obj2 = val4.AddComponent(); obj2.type = (LightType)2; obj2.color = new Color(0.35f, 0.95f, 0.72f); obj2.intensity = 7f; obj2.range = 5f; obj2.shadows = (LightShadows)0; Object.Destroy((Object)val4, 0.25f); } PlayLocalShadowStepClip(GetActivationClip(), position, 0.5f); } private static GameObject FindSmokeParticleSystem() { if (_smokePrefabSearched) { if (!((Object)(object)_smokePrefab != (Object)null)) { return null; } return _smokePrefab; } _smokePrefabSearched = true; ParticleSystem[] array = Resources.FindObjectsOfTypeAll(); foreach (ParticleSystem val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)((Component)val).gameObject == (Object)null)) { string text = ((Object)((Component)val).gameObject).name.ToLowerInvariant(); if (text.Contains("smoke") || text.Contains("poof") || text.Contains("stun")) { _smokePrefab = ((Component)val).gameObject; break; } } } return _smokePrefab; } internal static void OnRoundStarted() { ShadowStepUpgrade.IsInvisible = false; ShadowStepUpgrade.CooldownEndTime = 0f; ShadowStepUpgrade.InvisibilityEndTime = 0f; _externalInvisibilityActive = false; _externalInvisibilityEndTime = 0f; StopCloakEffects(); DestroyCloakVignette(); CamoShellCloak.CleanupAll(); PublishLocalState(force: true); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { Cleanup(); } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPostfix] private static void PostKillPlayer(PlayerControllerB __instance) { try { if (!((Object)(object)__instance == (Object)null)) { CamoShellCloak.ForgetPlayer(__instance); if (IsLocal(__instance)) { ShadowStepUpgrade.IsInvisible = false; _externalInvisibilityActive = false; _externalInvisibilityEndTime = 0f; StopCloakEffects(); PublishLocalState(force: true); } } } catch (Exception arg) { Plugin.Log.LogError((object)$"[Shadow Step] KillPlayer cleanup error: {arg}"); } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { Cleanup(); ShadowStepNetState.Clear(); } private static void Cleanup() { UpgradeHUDManager.DestroyHUDElement("shadow_hud"); StopCloakEffects(); DestroyCloakVignette(); ShadowStepUpgrade.IsInvisible = false; ShadowStepUpgrade.CooldownEndTime = 0f; ShadowStepUpgrade.InvisibilityEndTime = 0f; _externalInvisibilityActive = false; _externalInvisibilityEndTime = 0f; _publishedOnce = false; _publishedTier = byte.MaxValue; _publishedCloak = false; _smokePrefab = null; _smokePrefabSearched = false; CamoShellCloak.CleanupAll(); } } [HarmonyPatch] internal static class ShoulderCheckPatch { private const float IMPACT_LOCKOUT_SECONDS = 0.25f; private const int DOOR_MASK = -1; private static float _sprintSeconds; private static bool _chargeReady; private static float _lastImpactTime; private static DoorLock _lastDoor; private static float _lastDoorTime; private static GameObject _windRoot; private static Image[] _windLines; private static Sprite _pixelSprite; private static bool _doorReflectionResolved; private static MethodInfo _openDoorAsEnemy; private static FieldInfo _doorOpenedField; private static PropertyInfo _doorOpenedProperty; [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!IsLocalPlayer(__instance)) { return; } if (!CanMaintainSprintCharge(__instance)) { ResetCharge(); UpdateVignette(ready: false); return; } _sprintSeconds += Time.deltaTime; _chargeReady = _sprintSeconds >= ShoulderCheckUpgrade.GetArmSeconds(); UpdateVignette(_chargeReady); if (_chargeReady) { TrySlamDoor(__instance); } } [HarmonyPatch(typeof(EnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static bool PreEnemyCollideWithPlayer(EnemyAI __instance, Collider other) { if ((Object)(object)__instance == (Object)null || (Object)(object)other == (Object)null || !_chargeReady) { return true; } if (__instance.isEnemyDead) { return true; } PlayerControllerB player = ((Component)other).GetComponent() ?? ((Component)other).GetComponentInParent(); if (!IsLocalPlayer(player)) { return true; } if (Time.time < _lastImpactTime + 0.25f) { return true; } ApplyEnemyImpact(__instance, player); ConsumeCharge(); return false; } internal static void OnRoundStarted() { ResetCharge(); HideVignette(); _lastImpactTime = 0f; _lastDoor = null; _lastDoorTime = 0f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ResetCharge(); HideVignette(); } private static bool CanMaintainSprintCharge(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || !ShoulderCheckUpgrade.IsUnlocked()) { return false; } if (!player.isSprinting || player.isCrouching) { return false; } if (player.sprintMeter < 0.12f) { return false; } if ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) { return false; } if (player.isTypingChat || player.inTerminalMenu || player.inSpecialInteractAnimation) { return false; } return true; } private static void TrySlamDoor(PlayerControllerB player) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) Transform val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((Component)player).transform); Vector3 val2 = Vector3.ProjectOnPlane(val.forward, Vector3.up); if (((Vector3)(ref val2)).sqrMagnitude < 0.01f) { val2 = ((Component)player).transform.forward; } ((Vector3)(ref val2)).Normalize(); RaycastHit val3 = default(RaycastHit); if (!Physics.SphereCast(new Ray(val.position + Vector3.down * 0.1f, val2), 0.45f, ref val3, 1.35f, -1, (QueryTriggerInteraction)2)) { return; } DoorLock val4 = (((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null) ? ((Component)((RaycastHit)(ref val3)).collider).GetComponentInParent() : null); if (!IsUsableDoor(val4) || ((Object)(object)val4 == (Object)(object)_lastDoor && Time.time < _lastDoorTime + 0.7f)) { return; } ResolveDoorReflection(); if (_openDoorAsEnemy == null) { return; } try { _openDoorAsEnemy.Invoke(val4, null); _lastDoor = val4; _lastDoorTime = Time.time; HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ShakeCamera((ScreenShakeType)0); } ConsumeCharge(); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Shoulder Check] Door slam skipped: " + ex.Message)); } } } private static bool IsUsableDoor(DoorLock door) { if ((Object)(object)door != (Object)null && !door.isLocked) { return !DoorIsOpen(door); } return false; } private static bool DoorIsOpen(DoorLock door) { if ((Object)(object)door == (Object)null) { return false; } ResolveDoorReflection(); try { if (_doorOpenedField != null && _doorOpenedField.GetValue(door) is bool result) { return result; } if (_doorOpenedProperty != null && _doorOpenedProperty.GetValue(door, null) is bool result2) { return result2; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Shoulder Check] Door state check skipped: " + ex.Message)); } } return false; } private static void ResolveDoorReflection() { if (!_doorReflectionResolved) { _doorReflectionResolved = true; _openDoorAsEnemy = typeof(DoorLock).GetMethod("OpenDoorAsEnemyServerRpc", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _doorOpenedField = typeof(DoorLock).GetField("isDoorOpened", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(DoorLock).GetField("isDoorOpen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); _doorOpenedProperty = typeof(DoorLock).GetProperty("isDoorOpened", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(DoorLock).GetProperty("isDoorOpen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } private static void ApplyEnemyImpact(EnemyAI enemy, PlayerControllerB player) { //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_0025: 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_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) _lastImpactTime = Time.time; Vector3 val = ((Component)enemy).transform.position - ((Component)player).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform : ((Component)player).transform).forward; val.y = 0f; } ((Vector3)(ref val)).Normalize(); try { enemy.HitEnemyOnLocalClient(ShoulderCheckUpgrade.GetDamage(), val, (PlayerControllerB)null, false, -1); enemy.SetEnemyStunned(true, 0.65f, player); ((MonoBehaviour)player).StartCoroutine(ApplyEnemyKnockback(enemy, val, ShoulderCheckUpgrade.GetKnockbackMeters())); HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ShakeCamera((ScreenShakeType)0); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[Shoulder Check] Enemy impact skipped: " + ex.Message)); } } } private static IEnumerator ApplyEnemyKnockback(EnemyAI enemy, Vector3 direction, float meters) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null || ((Vector3)(ref direction)).sqrMagnitude < 0.01f || meters <= 0f) { yield break; } Vector3 start = ((Component)enemy).transform.position; Vector3 end = start + ((Vector3)(ref direction)).normalized * meters; float duration = 0.24f; float elapsed = 0f; while (elapsed < duration && (Object)(object)enemy != (Object)null && !enemy.isEnemyDead) { float num = Mathf.SmoothStep(0f, 1f, elapsed / duration); Vector3 val = Vector3.Lerp(start, end, num); if ((Object)(object)enemy.agent != (Object)null && ((Behaviour)enemy.agent).enabled) { enemy.agent.Warp(val); } else { ((Component)enemy).transform.position = val; } elapsed += Time.deltaTime; yield return null; } } private static void ConsumeCharge() { ResetCharge(); UpdateVignette(ready: false); } private static void ResetCharge() { _sprintSeconds = 0f; _chargeReady = false; } private static void UpdateVignette(bool ready) { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) if (!ready) { HideVignette(); return; } EnsureVignette(); if ((Object)(object)_windRoot == (Object)null || _windLines == null) { return; } _windRoot.SetActive(true); float num = ((ShoulderCheckUpgrade.GetTier() >= 3) ? 0.025f : 0f); float num2 = Mathf.Abs(Mathf.Sin(Time.unscaledTime * 6.5f)) * 0.025f; for (int i = 0; i < _windLines.Length; i++) { Image val = _windLines[i]; if (!((Object)(object)val == (Object)null)) { float num3 = 0.055f + num + num2 + (float)(i % 3) * 0.012f; ((Graphic)val).color = new Color(0.72f, 0.94f, 1f, Mathf.Clamp(num3, 0.035f, 0.13f)); } } } private static void EnsureVignette() { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0078: 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_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_0175: 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_01ad: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_0203: Unknown result type (might be due to invalid IL or missing references) //IL_022c: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) //IL_024a: 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_0282: Unknown result type (might be due to invalid IL or missing references) //IL_0291: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02d8: Unknown result type (might be due to invalid IL or missing references) //IL_0301: Unknown result type (might be due to invalid IL or missing references) //IL_0310: Unknown result type (might be due to invalid IL or missing references) //IL_031f: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_0358: Unknown result type (might be due to invalid IL or missing references) //IL_0367: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_windRoot != (Object)null) && !((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null)) { Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if (!((Object)(object)canvas == (Object)null)) { _windRoot = new GameObject("Y4NGZ_ShoulderCheckWindEdges"); _windRoot.transform.SetParent(((Component)canvas).transform, false); RectTransform obj = _windRoot.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _windRoot.SetActive(false); _windLines = (Image[])(object)new Image[10]; CreateWindLine(0, "LeftTop", new Vector2(0f, 0.72f), new Vector2(0f, 0.72f), new Vector2(16f, 0f), 72f, 2.5f, -8f); CreateWindLine(1, "LeftMidA", new Vector2(0f, 0.58f), new Vector2(0f, 0.58f), new Vector2(10f, 0f), 58f, 2.2f, -4f); CreateWindLine(2, "LeftMidB", new Vector2(0f, 0.43f), new Vector2(0f, 0.43f), new Vector2(20f, 0f), 64f, 2.2f, 5f); CreateWindLine(3, "LeftLow", new Vector2(0f, 0.29f), new Vector2(0f, 0.29f), new Vector2(12f, 0f), 76f, 2.5f, 9f); CreateWindLine(4, "LeftFarLow", new Vector2(0f, 0.18f), new Vector2(0f, 0.18f), new Vector2(24f, 0f), 48f, 2f, 4f); CreateWindLine(5, "RightTop", new Vector2(1f, 0.72f), new Vector2(1f, 0.72f), new Vector2(-16f, 0f), 72f, 2.5f, 8f); CreateWindLine(6, "RightMidA", new Vector2(1f, 0.58f), new Vector2(1f, 0.58f), new Vector2(-10f, 0f), 58f, 2.2f, 4f); CreateWindLine(7, "RightMidB", new Vector2(1f, 0.43f), new Vector2(1f, 0.43f), new Vector2(-20f, 0f), 64f, 2.2f, -5f); CreateWindLine(8, "RightLow", new Vector2(1f, 0.29f), new Vector2(1f, 0.29f), new Vector2(-12f, 0f), 76f, 2.5f, -9f); CreateWindLine(9, "RightFarLow", new Vector2(1f, 0.18f), new Vector2(1f, 0.18f), new Vector2(-24f, 0f), 48f, 2f, -4f); } } } private static void CreateWindLine(int index, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 anchoredPosition, float width, float height, float rotation) { //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_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_0080: 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_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_windRoot == (Object)null) && index >= 0 && index < _windLines.Length) { GameObject val = new GameObject(name); val.transform.SetParent(_windRoot.transform, false); RectTransform obj = val.AddComponent(); obj.anchorMin = anchorMin; obj.anchorMax = anchorMax; obj.pivot = ((anchorMin.x < 0.5f) ? new Vector2(0f, 0.5f) : new Vector2(1f, 0.5f)); obj.anchoredPosition = anchoredPosition; obj.sizeDelta = new Vector2(width, height); ((Transform)obj).localRotation = Quaternion.Euler(0f, 0f, rotation); Image val2 = val.AddComponent(); val2.sprite = GetPixelSprite(); ((Graphic)val2).raycastTarget = false; ((Graphic)val2).color = new Color(0.72f, 0.94f, 1f, 0.06f); _windLines[index] = val2; } } private static void HideVignette() { if ((Object)(object)_windRoot != (Object)null) { _windRoot.SetActive(false); } } private static Sprite GetPixelSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0024: 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_004d: 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_0066: Expected O, but got Unknown if ((Object)(object)_pixelSprite != (Object)null) { return _pixelSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false) { hideFlags = (HideFlags)61 }; val.SetPixel(0, 0, Color.white); val.Apply(false, true); _pixelSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); ((Object)_pixelSprite).hideFlags = (HideFlags)61; return _pixelSprite; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } [HarmonyPatch] internal static class SixthSensePatch { private struct ObjectiveCandidate { internal Component Component; internal GameObject Root; internal Vector3 Position; internal int RootKey; } private struct RenderableTargetCacheEntry { internal GameObject Root; internal Vector3 CenterOffset; } private const float ObjectiveRescanInterval = 5f; private const float StaticRescanInterval = 5f; private const float ItemRescanInterval = 1f; private const int ObjectiveTypesPerRefreshTick = 3; private const float StaticRescanPhaseOffset = 2.5f; private const string CompanyAssemblyName = "Y4NGZCompany"; private const string ShipSystemsAssemblyName = "Y4NGZShipSystems"; private const string MonitorTakeoverAssemblyName = "Y4NGZMonitorTakeover"; private const int MaxRenderableCacheEntries = 1024; private static readonly string[] ObjectiveNeedles = new string[9] { "mainframe", "stash", "company", "bomb", "shipping", "container", "breaker", "blackout", "survey" }; private static readonly Dictionary ActiveOutlines = new Dictionary(); private static readonly Dictionary RenderableTargetCache = new Dictionary(); private static readonly List ObjectiveCandidates = new List(); private static readonly List PendingObjectiveCandidates = new List(); private static readonly HashSet SeenThisRefresh = new HashSet(); private static readonly HashSet SeenObjectiveRootsThisRefresh = new HashSet(); private static EntranceTeleport[] _cachedEntrances = Array.Empty(); private static Turret[] _cachedTurrets = Array.Empty(); private static Landmine[] _cachedMines = Array.Empty(); private static GrabbableObject[] _cachedItems = Array.Empty(); private static Type[] _objectiveTypes; private static bool _objectiveTypesResolved; private static bool _sceneCacheInvalidationHooked; private static float _nextRefreshTime; private static float _nextObjectiveRescanTime; private static float _nextStaticRescanTime; private static float _nextItemRescanTime; private static int _objectiveRebuildNextTypeIndex; private static bool _objectiveRebuildInProgress; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { EnsureSceneCacheInvalidationHooked(); if (IsLocalPlayer(__instance)) { if (!IsActiveRound()) { ClearAll(); } else if (!SixthSenseUpgrade.IsUnlocked() || __instance.isPlayerDead) { ClearAll(); } else if (!(Time.time < _nextRefreshTime)) { _nextRefreshTime = Time.time + 0.25f; RefreshTargets(__instance); } } } internal static void OnRoundStarted() { EnsureSceneCacheInvalidationHooked(); ClearRenderableTargetCache(); ClearAll(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ClearRenderableTargetCache(); ClearAll(); } private static void RefreshTargets(PlayerControllerB player) { SeenThisRefresh.Clear(); ScanEntrances(player); ScanObjectives(player); ScanTurrets(player); ScanMines(player); if (SixthSenseUpgrade.ShowsItems()) { ScanItems(player); } if (SixthSenseUpgrade.ShowsEnemies()) { ScanEnemies(player); } ClearStale(); } private static void ScanEntrances(PlayerControllerB player) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) EnsureStaticTargetCacheFresh(); EntranceTeleport[] cachedEntrances = _cachedEntrances; foreach (EntranceTeleport val in cachedEntrances) { if (!((Object)(object)val == (Object)null)) { ResolveRenderableTarget(((Component)val).gameObject, ((Component)val).gameObject, ResolveEntranceCenter(val), out var root, out var center); ConsiderTarget(player, root, center, 15f, UpgradeOutlineChannel.Utility); } } } private static void ScanObjectives(PlayerControllerB player) { //IL_007e: Unknown result type (might be due to invalid IL or missing references) if (!_objectiveRebuildInProgress && Time.time >= _nextObjectiveRescanTime) { BeginObjectiveCacheRebuild(); } ContinueObjectiveCacheRebuild(); SeenObjectiveRootsThisRefresh.Clear(); for (int i = 0; i < ObjectiveCandidates.Count; i++) { ObjectiveCandidate objectiveCandidate = ObjectiveCandidates[i]; if (!((Object)(object)objectiveCandidate.Component == (Object)null) && !((Object)(object)objectiveCandidate.Root == (Object)null) && !SeenObjectiveRootsThisRefresh.Contains(objectiveCandidate.RootKey)) { SeenObjectiveRootsThisRefresh.Add(objectiveCandidate.RootKey); ConsiderTarget(player, objectiveCandidate.Root, objectiveCandidate.Position, 15f, UpgradeOutlineChannel.Utility); } } } private static void ScanTurrets(PlayerControllerB player) { //IL_0036: 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) EnsureStaticTargetCacheFresh(); Turret[] cachedTurrets = _cachedTurrets; foreach (Turret val in cachedTurrets) { if (!((Object)(object)val == (Object)null) && val.turretActive) { ResolveRenderableTarget(((Component)val).gameObject, ((Component)val).gameObject, ((Component)val).transform.position, out var root, out var center); ConsiderTarget(player, root, center, 5f, UpgradeOutlineChannel.Danger); } } } private static void ScanMines(PlayerControllerB player) { //IL_0036: 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) EnsureStaticTargetCacheFresh(); Landmine[] cachedMines = _cachedMines; foreach (Landmine val in cachedMines) { if (!((Object)(object)val == (Object)null) && !val.hasExploded) { ResolveRenderableTarget(((Component)val).gameObject, ((Component)val).gameObject, ((Component)val).transform.position, out var root, out var center); ConsiderTarget(player, root, center, 5f, UpgradeOutlineChannel.Danger); } } } private static void ScanItems(PlayerControllerB player) { //IL_0068: 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) if (Time.time >= _nextItemRescanTime) { RebuildItemCache(); } GrabbableObject[] cachedItems = _cachedItems; foreach (GrabbableObject val in cachedItems) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.itemProperties == (Object)null) && val.grabbable && !val.deactivated && !val.isHeld && !val.isHeldByEnemy) { ResolveRenderableTarget(((Component)val).gameObject, ((Component)val).gameObject, ((Component)val).transform.position, out var root, out var center); ConsiderTarget(player, root, center, 10f, UpgradeOutlineChannel.Utility); } } } private static void ScanEnemies(PlayerControllerB player) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) RoundManager instance = RoundManager.Instance; List list = (((Object)(object)instance != (Object)null) ? instance.SpawnedEnemies : null); if (list == null) { return; } for (int i = 0; i < list.Count; i++) { EnemyAI val = list[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { ConsiderTarget(player, ((Component)val).gameObject, ResolveEnemyCenter(val), 15f, UpgradeOutlineChannel.Danger); } } } private static void ConsiderTarget(PlayerControllerB player, GameObject root, Vector3 position, float range, UpgradeOutlineChannel channel) { //IL_001b: 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_003c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)root == (Object)null || range <= 0f) { return; } Vector3 val = position - ((Component)player).transform.position; if (!(((Vector3)(ref val)).sqrMagnitude > range * range) && !HasDirectLineOfSight(player, root, position)) { int instanceID = ((Object)root).GetInstanceID(); SeenThisRefresh.Add(instanceID); if (OutlineEffectBridge.Show(root, channel, 0.6f, UpgradeOutlineSource.SixthSense)) { ActiveOutlines[instanceID] = root; } } } private static bool HasDirectLineOfSight(PlayerControllerB player, GameObject root, Vector3 position) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)root == (Object)null || (Object)(object)player.gameplayCamera == (Object)null) { return false; } Vector3 position2 = ((Component)player.gameplayCamera).transform.position; Vector3 val = position - position2; if (((Vector3)(ref val)).sqrMagnitude <= 0.0001f) { return true; } int num = (((Object)(object)StartOfRound.Instance != (Object)null) ? StartOfRound.Instance.collidersAndRoomMaskAndDefault : (-1)); RaycastHit val2 = default(RaycastHit); if (!Physics.Linecast(position2, position, ref val2, num, (QueryTriggerInteraction)1)) { return true; } return IsIgnoredLineOfSightHit(((RaycastHit)(ref val2)).collider, root, player); } private static bool IsIgnoredLineOfSightHit(Collider collider, GameObject targetRoot, PlayerControllerB player) { if ((Object)(object)collider == (Object)null) { return false; } Transform transform = ((Component)collider).transform; if (BelongsToTransformRoot(transform, ((Object)(object)targetRoot != (Object)null) ? targetRoot.transform : null)) { return true; } if ((Object)(object)player != (Object)null) { return BelongsToTransformRoot(transform, ((Component)player).transform); } return false; } private static bool BelongsToTransformRoot(Transform hitTransform, Transform ownerTransform) { if ((Object)(object)hitTransform == (Object)null || (Object)(object)ownerTransform == (Object)null) { return false; } if ((Object)(object)hitTransform == (Object)(object)ownerTransform || hitTransform.IsChildOf(ownerTransform)) { return true; } Transform root = hitTransform.root; Transform root2 = ownerTransform.root; if ((Object)(object)root != (Object)null && (Object)(object)root2 != (Object)null) { return (Object)(object)root == (Object)(object)root2; } return false; } private static void BeginObjectiveCacheRebuild() { _nextObjectiveRescanTime = Time.time + 5f; _objectiveRebuildInProgress = true; _objectiveRebuildNextTypeIndex = 0; PendingObjectiveCandidates.Clear(); } private static void ContinueObjectiveCacheRebuild() { if (!_objectiveRebuildInProgress) { return; } Type[] array = ResolveObjectiveTypes(); if (array == null || array.Length == 0) { CompleteObjectiveCacheRebuild(); return; } int num = 0; while (_objectiveRebuildNextTypeIndex < array.Length && num < 3) { ScanObjectiveType(array[_objectiveRebuildNextTypeIndex], PendingObjectiveCandidates); _objectiveRebuildNextTypeIndex++; num++; } if (_objectiveRebuildNextTypeIndex >= array.Length) { CompleteObjectiveCacheRebuild(); } } private static void ScanObjectiveType(Type objectiveType, List candidates) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) if (objectiveType == null || candidates == null) { return; } Object[] array = Object.FindObjectsByType(objectiveType, (FindObjectsSortMode)0); foreach (Object obj in array) { Component val = (Component)(object)((obj is Component) ? obj : null); if (!((Object)(object)val == (Object)null) && ResolveObjectiveTarget(val, out var root, out var center)) { candidates.Add(new ObjectiveCandidate { Component = val, Root = root, Position = center, RootKey = ((Object)root).GetInstanceID() }); } } } private static void CompleteObjectiveCacheRebuild() { ObjectiveCandidates.Clear(); ObjectiveCandidates.AddRange(PendingObjectiveCandidates); PendingObjectiveCandidates.Clear(); _objectiveRebuildInProgress = false; _objectiveRebuildNextTypeIndex = 0; } private static void EnsureStaticTargetCacheFresh() { if (!(Time.time < _nextStaticRescanTime)) { if (ObjectiveScanDueThisFrame()) { _nextStaticRescanTime = Time.time + 2.5f; } else { RebuildStaticTargetCaches(); } } } private static bool ObjectiveScanDueThisFrame() { if (!_objectiveRebuildInProgress) { return Time.time >= _nextObjectiveRescanTime; } return true; } private static void RebuildStaticTargetCaches() { _nextStaticRescanTime = Time.time + 5f; _cachedEntrances = Object.FindObjectsByType((FindObjectsSortMode)0); _cachedTurrets = Object.FindObjectsByType((FindObjectsSortMode)0); _cachedMines = Object.FindObjectsByType((FindObjectsSortMode)0); } private static void RebuildItemCache() { _nextItemRescanTime = Time.time + 1f; _cachedItems = Object.FindObjectsByType((FindObjectsSortMode)0); } private static Type[] ResolveObjectiveTypes() { if (_objectiveTypesResolved) { return _objectiveTypes; } _objectiveTypesResolved = true; List list = FindCompanyAssemblies(); if (list.Count == 0) { _objectiveTypes = Array.Empty(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Sixth Sense] No Y4NGZCompany assembly loaded; objective scan disabled."); } return _objectiveTypes; } List list2 = new List(); for (int i = 0; i < list.Count; i++) { Type[] loadableTypes = GetLoadableTypes(list[i]); foreach (Type type in loadableTypes) { if (LooksLikeY4ngzCompanyObjectiveType(type)) { list2.Add(type); } } } _objectiveTypes = list2.ToArray(); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[Sixth Sense] Resolved {_objectiveTypes.Length} Y4NGZCompany objective component type(s) across {list.Count} assembly/assemblies."); } return _objectiveTypes; } private static List FindCompanyAssemblies() { List list = new List(); Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { switch (assembly?.GetName().Name) { case "Y4NGZCompany": case "Y4NGZShipSystems": case "Y4NGZMonitorTakeover": case "LethalCCTV": case "Y4NGZCore": case "Y4NGZBloodFX": case "Y4NGZAtmosphere": list.Add(assembly); break; } } return list; } private static Type[] GetLoadableTypes(Assembly assembly) { try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException ex) { return ex.Types ?? Array.Empty(); } catch { return Array.Empty(); } } private static bool LooksLikeY4ngzCompanyObjectiveType(Type type) { if (type == null || type.IsAbstract || !typeof(Component).IsAssignableFrom(type)) { return false; } if (type.Namespace == null || !type.Namespace.StartsWith("Y4NGZCompany.", StringComparison.Ordinal)) { return false; } string name = type.Name; if (string.IsNullOrEmpty(name)) { return false; } for (int i = 0; i < ObjectiveNeedles.Length; i++) { if (name.IndexOf(ObjectiveNeedles[i], StringComparison.OrdinalIgnoreCase) >= 0) { return true; } } return false; } private static bool ResolveObjectiveTarget(Component component, out GameObject root, out Vector3 center) { //IL_0004: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) root = null; center = Vector3.zero; if ((Object)(object)component == (Object)null) { return false; } ResolveRenderableTarget(component.gameObject, component.gameObject, component.transform.position, out root, out center); if ((Object)(object)root != (Object)null) { return true; } NetworkObject componentInParent = component.GetComponentInParent(); root = (((Object)(object)componentInParent != (Object)null) ? ((Component)componentInParent).gameObject : component.gameObject); center = (((Object)(object)root != (Object)null) ? root.transform.position : component.transform.position); return (Object)(object)root != (Object)null; } private static void ResolveRenderableTarget(GameObject preferredRoot, GameObject fallbackRoot, Vector3 fallbackCenter, out GameObject root, out Vector3 center) { //IL_001c: 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_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) GameObject val = (((Object)(object)preferredRoot != (Object)null) ? preferredRoot : fallbackRoot); if ((Object)(object)val == (Object)null) { root = null; center = fallbackCenter; return; } int instanceID = ((Object)val).GetInstanceID(); if (RenderableTargetCache.TryGetValue(instanceID, out var value)) { if ((Object)(object)value.Root != (Object)null) { root = value.Root; center = root.transform.position + value.CenterOffset; return; } RenderableTargetCache.Remove(instanceID); } if (RenderableTargetCache.Count >= 1024) { RenderableTargetCache.Clear(); } root = ResolveRenderableRootUncached(preferredRoot, fallbackRoot); if ((Object)(object)root == (Object)null) { center = fallbackCenter; return; } center = ResolveRendererCenterUncached(root, fallbackCenter); RenderableTargetCache[instanceID] = new RenderableTargetCacheEntry { Root = root, CenterOffset = center - root.transform.position }; } private static GameObject ResolveRenderableRootUncached(GameObject preferredRoot, GameObject fallbackRoot) { if (HasUsableRenderer(preferredRoot)) { return preferredRoot; } if (HasUsableRenderer(fallbackRoot)) { return fallbackRoot; } Transform val = (((Object)(object)preferredRoot != (Object)null) ? preferredRoot.transform.parent : null); while ((Object)(object)val != (Object)null) { if (HasUsableRenderer(((Component)val).gameObject)) { return ((Component)val).gameObject; } if ((Object)(object)((Component)val).GetComponent() != (Object)null) { return ((Component)val).gameObject; } val = val.parent; } if (!((Object)(object)preferredRoot != (Object)null)) { return fallbackRoot; } return preferredRoot; } private static bool HasUsableRenderer(GameObject root) { if ((Object)(object)root == (Object)null) { return false; } Renderer[] componentsInChildren = root.GetComponentsInChildren(false); foreach (Renderer val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && !(val is ParticleSystemRenderer) && !(val is LineRenderer) && !(val is TrailRenderer)) { return true; } } return false; } private static Vector3 ResolveRendererCenterUncached(GameObject root, Vector3 fallback) { //IL_0015: 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_0082: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null) { return fallback; } Renderer[] componentsInChildren = root.GetComponentsInChildren(false); Bounds val = default(Bounds); bool flag = false; foreach (Renderer val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2.enabled && !(val2 is ParticleSystemRenderer) && !(val2 is LineRenderer) && !(val2 is TrailRenderer)) { if (!flag) { val = val2.bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(val2.bounds); } } } if (!flag) { return fallback; } return ((Bounds)(ref val)).center; } private static void EnsureSceneCacheInvalidationHooked() { if (!_sceneCacheInvalidationHooked) { _sceneCacheInvalidationHooked = true; SceneManager.activeSceneChanged += OnActiveSceneChanged; SceneManager.sceneUnloaded += OnSceneUnloaded; } } private static void OnActiveSceneChanged(Scene previousScene, Scene nextScene) { ClearRenderableTargetCache(); ClearTargetDiscoveryCaches(); } private static void OnSceneUnloaded(Scene scene) { ClearRenderableTargetCache(); ClearTargetDiscoveryCaches(); } private static void ClearRenderableTargetCache() { RenderableTargetCache.Clear(); } private static void ClearTargetDiscoveryCaches() { ObjectiveCandidates.Clear(); PendingObjectiveCandidates.Clear(); _objectiveRebuildInProgress = false; _objectiveRebuildNextTypeIndex = 0; _cachedEntrances = Array.Empty(); _cachedTurrets = Array.Empty(); _cachedMines = Array.Empty(); _cachedItems = Array.Empty(); _nextObjectiveRescanTime = 0f; _nextStaticRescanTime = Time.time + 2.5f; _nextItemRescanTime = 0f; } private static Vector3 ResolveEntranceCenter(EntranceTeleport entrance) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_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) if ((Object)(object)entrance == (Object)null) { return Vector3.zero; } if (!((Object)(object)entrance.entrancePoint != (Object)null)) { return ((Component)entrance).transform.position + Vector3.up * 1.2f; } return entrance.entrancePoint.position + Vector3.up * 1.2f; } private static Vector3 ResolveEnemyCenter(EnemyAI enemy) { //IL_0009: 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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return Vector3.zero; } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position; } Renderer val = null; if (enemy.skinnedMeshRenderers != null) { for (int i = 0; i < enemy.skinnedMeshRenderers.Length; i++) { if (!((Object)(object)enemy.skinnedMeshRenderers[i] == (Object)null)) { val = (Renderer)(object)enemy.skinnedMeshRenderers[i]; break; } } } if ((Object)(object)val == (Object)null && enemy.meshRenderers != null) { for (int j = 0; j < enemy.meshRenderers.Length; j++) { if (!((Object)(object)enemy.meshRenderers[j] == (Object)null)) { val = (Renderer)(object)enemy.meshRenderers[j]; break; } } } if (!((Object)(object)val != (Object)null)) { return ((Component)enemy).transform.position + Vector3.up * 1.2f; } Bounds bounds = val.bounds; return ((Bounds)(ref bounds)).center; } private static void ClearStale() { List list = null; foreach (KeyValuePair activeOutline in ActiveOutlines) { if (!((Object)(object)activeOutline.Value != (Object)null) || !SeenThisRefresh.Contains(activeOutline.Key)) { if (list == null) { list = new List(); } list.Add(activeOutline.Key); } } if (list == null) { return; } for (int i = 0; i < list.Count; i++) { int key = list[i]; if (ActiveOutlines.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { OutlineEffectBridge.Clear(value, UpgradeOutlineSource.SixthSense); } ActiveOutlines.Remove(key); } } private static void ClearAll() { foreach (KeyValuePair activeOutline in ActiveOutlines) { if ((Object)(object)activeOutline.Value != (Object)null) { OutlineEffectBridge.Clear(activeOutline.Value, UpgradeOutlineSource.SixthSense); } } ActiveOutlines.Clear(); SeenThisRefresh.Clear(); SeenObjectiveRootsThisRefresh.Clear(); ClearTargetDiscoveryCaches(); _nextRefreshTime = 0f; } private static bool IsActiveRound() { StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance != (Object)null && !instance.inShipPhase) { return instance.shipDoorsEnabled; } return false; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } } [HarmonyPatch] internal static class SquadSightPatch { private const float TargetRefreshInterval = 0.2f; private const int ScannerLineOfSightMask = 134217984; private const float FogOutlineDistance = 10f; private static readonly Dictionary ActiveOutlines = new Dictionary(); private static readonly HashSet SeenThisRefresh = new HashSet(); private static float _nextRefreshTime; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostLateUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { if (!BuddySystemUpgrade.IsUnlocked() || __instance.isPlayerDead) { ClearAll(); } else if (!(Time.time < _nextRefreshTime)) { _nextRefreshTime = Time.time + 0.2f; RefreshTargets(__instance); } } } private static void RefreshTargets(PlayerControllerB localPlayer) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0099: Unknown result type (might be due to invalid IL or missing references) SeenThisRefresh.Clear(); float range = BuddySystemUpgrade.GetRange(); if (range <= 0f) { ClearAll(); return; } float num = range * range; PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array != null) { foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val == (Object)(object)localPlayer) && val.isPlayerControlled && !val.isPlayerDead) { Vector3 val2 = ResolvePlayerCenter(val); Vector3 val3 = val2 - ((Component)localPlayer).transform.position; if (!(((Vector3)(ref val3)).sqrMagnitude > num)) { RefreshOneTarget(localPlayer, (Component)(object)val, ((Component)val).gameObject, val2); } } } } List list = null; foreach (KeyValuePair activeOutline in ActiveOutlines) { if (!((Object)(object)activeOutline.Key != (Object)null) || !SeenThisRefresh.Contains(activeOutline.Key)) { if (list == null) { list = new List(); } list.Add(activeOutline.Key); } } if (list != null) { for (int j = 0; j < list.Count; j++) { RemoveOutline(list[j]); } } } private static void RefreshOneTarget(PlayerControllerB localPlayer, Component key, GameObject targetRoot, Vector3 targetCenter) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) SeenThisRefresh.Add(key); float distance = Vector3.Distance(((Component)localPlayer).transform.position, targetCenter); if (HasReliableDirectVisibility(localPlayer, targetRoot, targetCenter, distance)) { RemoveOutline(key); } else if (OutlineEffectBridge.Show(targetRoot, UpgradeOutlineChannel.Friendly, 0.6f, UpgradeOutlineSource.BuddySystem)) { ActiveOutlines[key] = targetRoot; } } private static bool HasReliableDirectVisibility(PlayerControllerB localPlayer, GameObject targetRoot, Vector3 targetCenter, float distance) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003c: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)localPlayer.gameplayCamera != (Object)null) ? localPlayer.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return false; } Vector3 val2 = val.WorldToViewportPoint(targetCenter); if (val2.z <= 0f || val2.x < 0f || val2.x > 1f || val2.y < 0f || val2.y > 1f) { return false; } if (FogLikelyObscures(localPlayer, distance)) { return false; } RaycastHit val3 = default(RaycastHit); if (!Physics.Linecast(((Component)val).transform.position, targetCenter, ref val3, 134217984, (QueryTriggerInteraction)1)) { return true; } if ((Object)(object)((RaycastHit)(ref val3)).collider != (Object)null && (Object)(object)targetRoot != (Object)null) { return ((Component)((RaycastHit)(ref val3)).collider).transform.IsChildOf(targetRoot.transform); } return false; } private static bool FogLikelyObscures(PlayerControllerB localPlayer, float distance) { if ((Object)(object)localPlayer == (Object)null || !localPlayer.isInsideFactory) { return false; } if ((Object)(object)RoundManager.Instance == (Object)null || (Object)(object)RoundManager.Instance.indoorFog == (Object)null) { return false; } if (((Component)RoundManager.Instance.indoorFog).gameObject.activeSelf) { return distance >= 10f; } return false; } private static Vector3 ResolvePlayerCenter(PlayerControllerB player) { //IL_0009: 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_005d: 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_006c: 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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return Vector3.zero; } if ((Object)(object)player.playerGlobalHead != (Object)null) { return player.playerGlobalHead.position; } if ((Object)(object)player.thisPlayerBody != (Object)null) { return player.thisPlayerBody.position + Vector3.up * 1.4f; } return ((Component)player).transform.position + Vector3.up * 1.4f; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void RemoveOutline(Component key) { if (ActiveOutlines.TryGetValue(key, out var value) && (Object)(object)value != (Object)null) { OutlineEffectBridge.Clear(value, UpgradeOutlineSource.BuddySystem); } ActiveOutlines.Remove(key); } private static void ClearAll() { foreach (KeyValuePair activeOutline in ActiveOutlines) { if ((Object)(object)activeOutline.Value != (Object)null) { OutlineEffectBridge.Clear(activeOutline.Value, UpgradeOutlineSource.BuddySystem); } } ActiveOutlines.Clear(); SeenThisRefresh.Clear(); _nextRefreshTime = 0f; } internal static void OnRoundStarted() { ClearAll(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { ClearAll(); } } [HarmonyPatch] internal static class StormyWeatherPatch { internal static bool IsLightningStrike; [HarmonyPrefix] [HarmonyPatch(typeof(StormyWeather), "LightningStrike")] private static void LightningStrikePrefix() { IsLightningStrike = true; } [HarmonyPostfix] [HarmonyPatch(typeof(StormyWeather), "LightningStrike")] private static void LightningStrikePostfix() { IsLightningStrike = false; } [HarmonyFinalizer] [HarmonyPatch(typeof(StormyWeather), "LightningStrike")] private static Exception LightningStrikeFinalizer(Exception __exception) { IsLightningStrike = false; return __exception; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] private static bool PreventLightningKill(PlayerControllerB __instance) { try { if (IsLightningStrike && (Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController && LightFeetUpgrade.HasTier(3)) { Plugin.Log.LogDebug((object)"Light Feet T3: Prevented lightning kill on local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"StormyWeatherPatch.PreventLightningKill failed: {arg}"); } return true; } [HarmonyPrefix] [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] private static bool PreventLightningDamage(PlayerControllerB __instance) { try { if (IsLightningStrike && (Object)(object)__instance == (Object)(object)GameNetworkManager.Instance.localPlayerController && LightFeetUpgrade.HasTier(3)) { Plugin.Log.LogDebug((object)"Light Feet T3: Prevented lightning damage on local player."); return false; } } catch (Exception arg) { Plugin.Log.LogError((object)$"StormyWeatherPatch.PreventLightningDamage failed: {arg}"); } return true; } } [HarmonyPatch] internal static class TurretHackerPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveHack; } private const string MSG_TURRET_HACK = "TechnicianTurretHack"; private const string DoorHackPromptKey = "FieldMechanic.DoorHack"; private const string TurretHackPromptKey = "FieldMechanic.TurretHack"; private const float MAX_HACK_DURATION_SECONDS = 90f; private static readonly Dictionary HackedTurrets = new Dictionary(); private static bool _handlersRegistered; private static float _cooldownEnd; private static float _doorHackHold; private static float _turretHackHold; private static readonly RaycastHit[] TurretHackHits = (RaycastHit[])(object)new RaycastHit[16]; private static readonly RaycastHit[] DoorHackHits = (RaycastHit[])(object)new RaycastHit[16]; private const int HACK_PAYLOAD_BYTES = 12; [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; HackedTurrets.Clear(); _doorHackHold = 0f; _turretHackHold = 0f; ClearDoorHackPrompt(); ClearTurretHackPrompt(); } internal static void OnRoundStarted() { HackedTurrets.Clear(); _cooldownEnd = 0f; _doorHackHold = 0f; _turretHackHold = 0f; ClearDoorHackPrompt(); ClearTurretHackPrompt(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { HackedTurrets.Clear(); _doorHackHold = 0f; _turretHackHold = 0f; ClearDoorHackPrompt(); ClearTurretHackPrompt(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (IsLocalPlayer(__instance)) { TickDoorHack(__instance); TickTurretHack(__instance); } } [HarmonyPatch(typeof(Turret), "Update")] [HarmonyPrefix] private static bool PreTurretUpdate(Turret __instance) { if ((Object)(object)__instance == (Object)null) { return true; } if (!HackedTurrets.TryGetValue(((NetworkBehaviour)__instance).NetworkObjectId, out var value)) { return true; } if (Time.time >= value) { HackedTurrets.Remove(((NetworkBehaviour)__instance).NetworkObjectId); return true; } UpdateHackedTurret(__instance); return false; } internal static bool TryHackFromTablet(Turret turret) { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)turret == (Object)null || (Object)(object)val == (Object)null || val.isPlayerDead || val.isTypingChat || !FieldOperationsUpgrade.IsUnlocked() || !TurretHackerUpgrade.CanHackTurrets()) { return false; } return TryApplyHack(turret); } private static void TickTurretHack(PlayerControllerB player) { if (!TurretHackerUpgrade.CanHackTurrets() || !CanUse(player) || player.inTerminalMenu || FieldOperationsTabletPatch.IsTabletActive) { _turretHackHold = 0f; ClearTurretHackPrompt(); return; } float range = ((player.grabDistance > 0f) ? player.grabDistance : 4f); Turret val = FindLookedAtTurret(player, range); if ((Object)(object)val == (Object)null || Time.time < _cooldownEnd) { _turretHackHold = 0f; ClearTurretHackPrompt(); return; } string text = UpgradeInteractInput.DisplayLabel(); Y4ngzPromptOverlay.SetPersistentPrompt("FieldMechanic.TurretHack", "Disable turret: Hold [" + text + "]"); if (UpgradeInteractInput.IsHeld()) { _turretHackHold += Time.deltaTime; if (_turretHackHold >= 1.2f) { _turretHackHold = 0f; if (TryApplyHack(val)) { EmployeeStatistics.RecordDeviceHacked((Object)(object)val); } ClearTurretHackPrompt(); } } else { _turretHackHold = Mathf.MoveTowards(_turretHackHold, 0f, Time.deltaTime * 2f); } } private static bool TryApplyHack(Turret turret) { if ((Object)(object)turret == (Object)null || Time.time < _cooldownEnd) { return false; } float duration = TurretHackerUpgrade.GetDuration(); ApplyHack(((NetworkBehaviour)turret).NetworkObjectId, duration); BroadcastHack(((NetworkBehaviour)turret).NetworkObjectId, duration); _cooldownEnd = Time.time + 20f; return true; } private static Turret FindLookedAtTurret(PlayerControllerB player, float range) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return null; } int num = Physics.RaycastNonAlloc(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), TurretHackHits, range, -1, (QueryTriggerInteraction)2); Turret result = null; float num2 = float.MaxValue; for (int i = 0; i < num; i++) { Turret val2 = (((Object)(object)((RaycastHit)(ref TurretHackHits[i])).collider != (Object)null) ? ((Component)((RaycastHit)(ref TurretHackHits[i])).collider).GetComponentInParent() : null); if (!((Object)(object)val2 == (Object)null) && !(((RaycastHit)(ref TurretHackHits[i])).distance >= num2)) { result = val2; num2 = ((RaycastHit)(ref TurretHackHits[i])).distance; } } return result; } private static void ClearTurretHackPrompt() { Y4ngzPromptOverlay.ClearPersistentPrompt("FieldMechanic.TurretHack"); } private static void ApplyHack(ulong turretNetworkId, float duration) { if (!HackedTurrets.TryGetValue(turretNetworkId, out var value)) { value = 0f; } HackedTurrets[turretNetworkId] = Mathf.Max(value, Time.time + duration); Turret val = ResolveTurret(turretNetworkId); if ((Object)(object)val != (Object)null) { val.targetPlayerWithRotation = null; val.targetTransform = null; } } private static Turret ResolveTurret(ulong networkId) { if ((Object)(object)NetworkManager.Singleton != (Object)null && NetworkManager.Singleton.SpawnManager.SpawnedObjects.TryGetValue(networkId, out var value) && (Object)(object)value != (Object)null) { return ((Component)value).GetComponent(); } Turret[] array = Object.FindObjectsOfType(); for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && ((NetworkBehaviour)array[i]).NetworkObjectId == networkId) { return array[i]; } } return null; } private static void UpdateHackedTurret(Turret turret) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) if (turret.turretActive) { turret.targetPlayerWithRotation = null; turret.targetTransform = null; turret.turretMode = (TurretMode)0; if ((Object)(object)turret.turretAnimator != (Object)null) { turret.turretAnimator.SetInteger("TurretMode", 0); } } } private static void TickDoorHack(PlayerControllerB player) { if (!TurretHackerUpgrade.CanHackDoors()) { _doorHackHold = 0f; ClearDoorHackPrompt(); return; } if (!CanUse(player) || player.inTerminalMenu) { _doorHackHold = 0f; ClearDoorHackPrompt(); return; } DoorLock val = FindLookedAtLockedDoor(player); if ((Object)(object)val == (Object)null) { _doorHackHold = 0f; ClearDoorHackPrompt(); return; } string text = UpgradeInteractInput.DisplayLabel(); Y4ngzPromptOverlay.SetPersistentPrompt("FieldMechanic.DoorHack", "Bypass lock: Hold [" + text + "]"); if (UpgradeInteractInput.IsHeld()) { _doorHackHold += Time.deltaTime; if (_doorHackHold >= 1.2f) { _doorHackHold = 0f; val.UnlockDoorSyncWithServer(); EmployeeStatistics.RecordDeviceHacked((Object)(object)val); ClearDoorHackPrompt(); } } else { _doorHackHold = Mathf.MoveTowards(_doorHackHold, 0f, Time.deltaTime * 2f); } } private static void ClearDoorHackPrompt() { Y4ngzPromptOverlay.ClearPersistentPrompt("FieldMechanic.DoorHack"); } private static DoorLock FindLookedAtLockedDoor(PlayerControllerB player) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) Camera val = (((Object)(object)player.gameplayCamera != (Object)null) ? player.gameplayCamera : Camera.main); if ((Object)(object)val == (Object)null) { return null; } float num = ((player.grabDistance > 0f) ? player.grabDistance : 4f); int num2 = Physics.RaycastNonAlloc(new Ray(((Component)val).transform.position, ((Component)val).transform.forward), DoorHackHits, num, -1, (QueryTriggerInteraction)2); DoorLock val2 = null; float num3 = float.MaxValue; for (int i = 0; i < num2; i++) { DoorLock val3 = (((Object)(object)((RaycastHit)(ref DoorHackHits[i])).collider != (Object)null) ? ((Component)((RaycastHit)(ref DoorHackHits[i])).collider).GetComponentInParent() : null); if (!((Object)(object)val3 == (Object)null) && !(((RaycastHit)(ref DoorHackHits[i])).distance >= num3)) { num3 = ((RaycastHit)(ref DoorHackHits[i])).distance; val2 = val3; } } if ((Object)(object)val2 == (Object)null) { return null; } if (!val2.isLocked || val2.isPickingLock) { return null; } return val2; } private static bool CanUse(PlayerControllerB player) { if ((Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat) { return false; } if ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen) { return false; } if (player.inSpecialInteractAnimation) { return false; } return true; } private static bool IsLocalPlayer(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)player == (Object)(object)val)) { if ((Object)(object)val == (Object)null && ((NetworkBehaviour)player).IsOwner) { return player.isPlayerControlled; } return false; } return true; } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveHack; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveHack; <>O.<0>__OnReceiveHack = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("TechnicianTurretHack", (HandleNamedMessageDelegate)obj); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("TurretHackerPatch: RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void BroadcastHack(ulong turretNetworkId, float duration) { //IL_0034: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref turretNetworkId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref duration, default(ForPrimitives)); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("TechnicianTurretHack", val, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("TechnicianTurretHack", 0uL, val, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("TurretHackerPatch: hack send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RelayHack(ulong excludeClientId, ulong turretNetworkId, float duration) { //IL_005e: 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_0071: 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_0085: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref val2))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref turretNetworkId, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref duration, default(ForPrimitives)); val.SendNamedMessage("TechnicianTurretHack", connectedClientsId, val2, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"TurretHackerPatch: hack relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref val2)).Dispose(); } } } private static void OnReceiveHack(ulong senderClientId, FastBufferReader reader) { //IL_0022: 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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)NetworkManager.Singleton != (Object)null && senderClientId == NetworkManager.Singleton.LocalClientId) { return; } try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { if (!(num2 > 0f) || (Object)(object)ResolveTurret(num) == (Object)null) { return; } num2 = Mathf.Min(num2, 90f); RelayHack(senderClientId, num, num2); } ApplyHack(num, num2); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("TurretHackerPatch: malformed hack sync: " + ex.Message)); } } } } [HarmonyPatch(typeof(Turret))] internal static class TurretPatch { private const float VanillaChargingSeconds = 1.5f; private const float ChargingClampPadding = 0.05f; private static readonly Dictionary LightFeetDelayUntilByTurret = new Dictionary(); [HarmonyPrefix] [HarmonyPatch("Update")] private static void DelayLightFeetFiringPrefix(Turret __instance) { try { if (!ShouldDelayForLocalPlayer(__instance)) { ClearDelay(__instance); return; } int instanceID = ((Object)__instance).GetInstanceID(); if (!LightFeetDelayUntilByTurret.TryGetValue(instanceID, out var value)) { value = Time.time + 2.5f; LightFeetDelayUntilByTurret[instanceID] = value; } if (Time.time < value) { __instance.turretInterval = Mathf.Min(__instance.turretInterval, 1.45f); } } catch (Exception arg) { Plugin.Log.LogError((object)$"TurretPatch.DelayLightFeetFiringPrefix failed: {arg}"); } } private static bool ShouldDelayForLocalPlayer(Turret turret) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if ((Object)(object)turret == (Object)null || (int)turret.turretMode != 1) { return false; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)turret.targetPlayerWithRotation == (Object)(object)val) { return LightFeetUpgrade.HasTier(2); } return false; } private static void ClearDelay(Turret turret) { if (!((Object)(object)turret == (Object)null)) { LightFeetDelayUntilByTurret.Remove(((Object)turret).GetInstanceID()); } } } internal static class UpgradeInteractInput { internal static bool IsHeld() { InputAction val = ResolveAction(); if (val != null) { return val.IsPressed(); } Keyboard current = Keyboard.current; if (current != null) { return ((ButtonControl)current.eKey).isPressed; } return false; } internal static string DisplayLabel() { InputAction obj = ResolveAction(); string text = ((obj != null) ? InputActionRebindingExtensions.GetBindingDisplayString(obj, (DisplayStringOptions)0, (string)null) : null); if (string.IsNullOrWhiteSpace(text)) { return "E"; } return text.Trim().ToUpperInvariant(); } private static InputAction ResolveAction() { IngamePlayerSettings instance = IngamePlayerSettings.Instance; object obj; if (instance == null) { obj = null; } else { PlayerInput playerInput = instance.playerInput; obj = ((playerInput != null) ? playerInput.actions : null); } if (obj == null) { return null; } return ((InputActionAsset)obj).FindAction("Interact", false); } } internal static class UpgradeTierSync { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSetTierServerRpc; public static HandleNamedMessageDelegate <1>__OnRequestAllServerRpc; public static HandleNamedMessageDelegate <2>__OnSetTierClientRpc; public static HandleNamedMessageDelegate <3>__OnSyncAllClientRpc; public static Action <4>__BroadcastLocalTiers; } private const string MSG_SET_SERVER = "Y4NGZUpgradeTier.SetServerRpc"; private const string MSG_SET_CLIENT = "Y4NGZUpgradeTier.SetClientRpc"; private const string MSG_REQUEST_ALL_SERVER = "Y4NGZUpgradeTier.RequestAllServerRpc"; private const string MSG_SYNC_ALL_CLIENT = "Y4NGZUpgradeTier.SyncAllClientRpc"; private const byte MaxSyncedTier = 3; private static readonly string[] SyncedUpgradeIds = new string[6] { "chameleon", "scavenger", "quota_guard", "turret_hacker", "field_operations", "lethal_hands_training" }; private static readonly Dictionary<(ulong, int), byte> tiersByClient = new Dictionary<(ulong, int), byte>(); private static bool handlersRegistered; private static NetworkManager registeredNetworkManager; private static bool upgradesChangedHooked; public static int GetTier(ulong clientId, string upgradeId) { int num = IndexOf(upgradeId); if (num < 0) { return 0; } PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && val.actualClientId == clientId) { return GetLocalTier(num); } if (!tiersByClient.TryGetValue((clientId, num), out var value)) { return 0; } return value; } public static void RegisterNetworkHandlers() { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Expected O, but got Unknown //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Expected O, but got Unknown //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown //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: Expected O, but got Unknown NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || (handlersRegistered && registeredNetworkManager == singleton)) { return; } if (handlersRegistered) { UnregisterNetworkHandlers(); } try { if (singleton.IsServer) { object obj = <>O.<0>__OnSetTierServerRpc; if (obj == null) { HandleNamedMessageDelegate val2 = OnSetTierServerRpc; <>O.<0>__OnSetTierServerRpc = val2; obj = (object)val2; } val.RegisterNamedMessageHandler("Y4NGZUpgradeTier.SetServerRpc", (HandleNamedMessageDelegate)obj); object obj2 = <>O.<1>__OnRequestAllServerRpc; if (obj2 == null) { HandleNamedMessageDelegate val3 = OnRequestAllServerRpc; <>O.<1>__OnRequestAllServerRpc = val3; obj2 = (object)val3; } val.RegisterNamedMessageHandler("Y4NGZUpgradeTier.RequestAllServerRpc", (HandleNamedMessageDelegate)obj2); } object obj3 = <>O.<2>__OnSetTierClientRpc; if (obj3 == null) { HandleNamedMessageDelegate val4 = OnSetTierClientRpc; <>O.<2>__OnSetTierClientRpc = val4; obj3 = (object)val4; } val.RegisterNamedMessageHandler("Y4NGZUpgradeTier.SetClientRpc", (HandleNamedMessageDelegate)obj3); object obj4 = <>O.<3>__OnSyncAllClientRpc; if (obj4 == null) { HandleNamedMessageDelegate val5 = OnSyncAllClientRpc; <>O.<3>__OnSyncAllClientRpc = val5; obj4 = (object)val5; } val.RegisterNamedMessageHandler("Y4NGZUpgradeTier.SyncAllClientRpc", (HandleNamedMessageDelegate)obj4); handlersRegistered = true; registeredNetworkManager = singleton; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"UpgradeTierSync: network handlers registered."); } } catch (Exception arg) { handlersRegistered = false; registeredNetworkManager = null; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogError((object)$"UpgradeTierSync: handler registration failed: {arg}"); } } if (!upgradesChangedHooked) { Y4NGZUpgradeManager.UpgradesChanged += BroadcastLocalTiers; upgradesChangedHooked = true; } } public static void BroadcastLocalTiers() { try { if (!handlersRegistered) { return; } PlayerControllerB val = StartOfRound.Instance?.localPlayerController; NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)val == (Object)null) && !((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null) { for (int i = 0; i < SyncedUpgradeIds.Length; i++) { SendTier(val.actualClientId, i, (byte)GetLocalTier(i)); } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSync: BroadcastLocalTiers failed: {arg}"); } } } public static void RequestAllFromServer() { //IL_0037: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (!((Object)(object)singleton == (Object)null) && singleton.CustomMessagingManager != null && !singleton.IsServer) { FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(1, (Allocator)2, -1); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZUpgradeTier.RequestAllServerRpc", 0uL, val, (NetworkDelivery)4); } } public static void Clear() { tiersByClient.Clear(); UnregisterNetworkHandlers(); } public static void ResetForNewCycle() { tiersByClient.Clear(); RegisterNetworkHandlers(); BroadcastLocalTiers(); RequestAllFromServer(); } private static int IndexOf(string upgradeId) { for (int i = 0; i < SyncedUpgradeIds.Length; i++) { if (string.Equals(SyncedUpgradeIds[i], upgradeId, StringComparison.OrdinalIgnoreCase)) { return i; } } return -1; } private static int GetLocalTier(int index) { return SyncedUpgradeIds[index] switch { "chameleon" => ChameleonUpgrade.GetTier(), "scavenger" => ScavengerUpgrade.GetTier(), "quota_guard" => QuotaGuardUpgrade.GetTier(), "turret_hacker" => TurretHackerUpgrade.GetTier(), "field_operations" => FieldOperationsUpgrade.GetTier(), "lethal_hands_training" => NativeFistsUpgrade.GetTier(), _ => 0, }; } private static void SendTier(ulong clientId, int index, byte tier) { //IL_003a: 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_004f: 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_0061: 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_007a: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (singleton.IsServer) { tiersByClient[(clientId, index)] = tier; SendSetToAllClients(clientId, index, tier); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(10, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref clientId, default(ForPrimitives)); byte b = (byte)index; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZUpgradeTier.SetServerRpc", 0uL, val, (NetworkDelivery)4); } private static void SendSetToAllClients(ulong clientId, int index, byte tier) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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_0053: Unknown result type (might be due to invalid IL or missing references) FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(10, (Allocator)2, -1); ((FastBufferWriter)(ref val)).WriteValueSafe(ref clientId, default(ForPrimitives)); byte b = (byte)index; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref tier, default(ForPrimitives)); NetworkManager.Singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZUpgradeTier.SetClientRpc", val, (NetworkDelivery)4); } private static void OnSetTierServerRpc(ulong senderId, FastBufferReader reader) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0038: 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) if (!NetworkManager.Singleton.IsServer) { return; } try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b2, default(ForPrimitives)); if (num == senderId && b < SyncedUpgradeIds.Length && b2 <= 3) { tiersByClient[(num, b)] = b2; SendSetToAllClients(num, b, b2); } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSync: OnSetTierServerRpc failed: {arg}"); } } } private static void OnSetTierClientRpc(ulong senderId, FastBufferReader reader) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_0048: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer || senderId != 0L) { return; } try { ulong item = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref item, default(ForPrimitives)); byte b = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); byte b2 = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b2, default(ForPrimitives)); if (b < SyncedUpgradeIds.Length && b2 <= 3) { tiersByClient[(item, b)] = b2; } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSync: OnSetTierClientRpc failed: {arg}"); } } } private static void OnRequestAllServerRpc(ulong senderId, FastBufferReader reader) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: 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_00d9: Unknown result type (might be due to invalid IL or missing references) if (!NetworkManager.Singleton.IsServer) { return; } try { int count = tiersByClient.Count; FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(2 + count * 10, (Allocator)2, -1); short num = (short)count; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); foreach (KeyValuePair<(ulong, int), byte> item in tiersByClient) { (ulong, int) key = item.Key; ((FastBufferWriter)(ref val)).WriteValueSafe(ref key.Item1, default(ForPrimitives)); byte b = (byte)item.Key.Item2; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); b = item.Value; ((FastBufferWriter)(ref val)).WriteValueSafe(ref b, default(ForPrimitives)); } NetworkManager.Singleton.CustomMessagingManager.SendNamedMessage("Y4NGZUpgradeTier.SyncAllClientRpc", senderId, val, (NetworkDelivery)4); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSync: OnRequestAllServerRpc failed: {arg}"); } } } private static void OnSyncAllClientRpc(ulong senderId, FastBufferReader reader) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003a: 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_004c: 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_005e: 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) if ((Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.IsServer || senderId != 0L) { return; } try { short num = default(short); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); ulong item = default(ulong); byte b = default(byte); byte b2 = default(byte); for (int i = 0; i < num; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref item, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref b2, default(ForPrimitives)); if (b < SyncedUpgradeIds.Length && b2 <= 3) { tiersByClient[(item, b)] = b2; } } } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSync: OnSyncAllClientRpc failed: {arg}"); } } } private static void UnregisterNetworkHandlers() { if (!handlersRegistered) { return; } NetworkManager val = registeredNetworkManager ?? NetworkManager.Singleton; CustomMessagingManager val2 = ((val != null) ? val.CustomMessagingManager : null); if (val2 != null) { try { if (val.IsServer) { val2.UnregisterNamedMessageHandler("Y4NGZUpgradeTier.SetServerRpc"); val2.UnregisterNamedMessageHandler("Y4NGZUpgradeTier.RequestAllServerRpc"); } val2.UnregisterNamedMessageHandler("Y4NGZUpgradeTier.SetClientRpc"); val2.UnregisterNamedMessageHandler("Y4NGZUpgradeTier.SyncAllClientRpc"); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("UpgradeTierSync: handler unregister failed: " + ex.Message)); } } } handlersRegistered = false; registeredNetworkManager = null; } } [HarmonyPatch] internal static class UpgradeTierSyncPatch { [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void AfterConnectClientToPlayerObject() { try { UpgradeTierSync.RegisterNetworkHandlers(); UpgradeTierSync.BroadcastLocalTiers(); UpgradeTierSync.RequestAllFromServer(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSyncPatch.AfterConnectClientToPlayerObject: {arg}"); } } } [HarmonyPatch(typeof(StartOfRound), "ResetShip")] [HarmonyPostfix] private static void AfterResetShip() { try { UpgradeTierSync.ResetForNewCycle(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSyncPatch.AfterResetShip: {arg}"); } } } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void AfterDisconnect() { try { UpgradeTierSync.Clear(); } catch (Exception arg) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)$"UpgradeTierSyncPatch.AfterDisconnect: {arg}"); } } } } [HarmonyPatch] internal static class WorklightBeaconPatch { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnReceiveThrowEvent; public static HandleNamedMessageDelegate <1>__OnReceivePickupEvent; } private const string MSG_THROW_SYNC = "WorklightBeacon_Throw"; private const string MSG_PICKUP_SYNC = "WorklightBeacon_Pickup"; private const string HUD_KEY = "worklight_beacon"; private const string PROMPT_KEY = "worklight_beacon"; private const float THROW_RELEASE_DELAY = 4f / 15f; private const string PackId = "y4ngz.upgrades.worklight_beacon"; private const string InteractionId = "y4ngz.worklight_beacon.throw"; private const string ManifestFileName = "y4ngz-interactions-worklightbeacon-livebody.manifest.json"; private const string THROW_ANIMATION = "PullGrenadePin"; private const string THROW_ANIMATION_FULL_PATH = "UpperBodyEmotes.PullGrenadePin"; private const int UPPER_BODY_EMOTES_LAYER = 3; private const float UPPER_BODY_SECONDS = 1.16f; private const string STOW_REASON = "worklight-beacon-throw"; private const float STOW_TIMEOUT_SECONDS = 4f; private static readonly int ThrowAnimationHash = Animator.StringToHash("PullGrenadePin"); private static readonly int ThrowAnimationFullPathHash = Animator.StringToHash("UpperBodyEmotes.PullGrenadePin"); private static int _chargesRemaining; private static float _cooldownTimer; private static bool _handlersRegistered; private static bool _roundChargeGranted; private static bool _packRegistered; private static bool _missingManifestLogged; private static float _nextRegistrationAttemptAt; private static uint _nextBeaconId = 1u; private const int THROW_PAYLOAD_BYTES = 40; private const int PICKUP_PAYLOAD_BYTES = 12; private static string _cachedPromptText; private static string _cachedPromptPath; private static int _cachedPromptCharges = -1; private static int _cachedPromptMax = -1; internal static void OnRoundStarted() { _roundChargeGranted = (_chargesRemaining = WorklightBeaconUpgrade.GetMaxCharges()) > 0; _cooldownTimer = 0f; _nextBeaconId = 1u; UpgradeHUDManager.DestroyHUDElement("worklight_beacon"); EnsurePackRegistered(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { WorklightBeaconProjectile.DestroyAllActive(); UpgradeHUDManager.DestroyHUDElement("worklight_beacon"); Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("worklight_beacon"); _chargesRemaining = 0; _roundChargeGranted = false; _cooldownTimer = 0f; } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { _handlersRegistered = false; _packRegistered = false; _missingManifestLogged = false; _nextRegistrationAttemptAt = 0f; Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("worklight_beacon"); } [HarmonyPatch(typeof(PlayerControllerB), "ConnectClientToPlayerObject")] [HarmonyPostfix] private static void PostConnectClientToPlayerObject() { RegisterNetworkHandlers(); } [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && ((NetworkBehaviour)__instance).IsOwner && __instance.isPlayerControlled && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { if (_cooldownTimer > 0f) { _cooldownTimer = Mathf.Max(0f, _cooldownTimer - Time.deltaTime); } UpdatePrompt(__instance); if (!__instance.isPlayerDead && (!((Object)(object)__instance.quickMenuManager != (Object)null) || !__instance.quickMenuManager.isMenuOpen) && !__instance.isTypingChat && !__instance.inTerminalMenu && !__instance.inSpecialInteractAnimation && UpgradeInput.WasPressed(Y4NGZUpgrades.Gui.Plugin.Keybinds?.WorklightBeacon)) { TryThrow(__instance); } } } [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")] [HarmonyPrefix] private static bool PreInteractPerformed(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController || !WorklightBeaconProjectile.TryGetAimedBeacon(__instance, out var beacon)) { return true; } TryPickupBeacon(beacon, __instance); return false; } private static void TryThrow(PlayerControllerB player) { //IL_00bc: 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_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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_0107: 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_010c: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)StartOfRound.Instance == (Object)null) && WorklightBeaconUpgrade.IsUnlocked() && !player.isInHangarShipRoom && !StartOfRound.Instance.inShipPhase && !(_cooldownTimer > 0f)) { EnsureRoundChargeAvailable(WorklightBeaconUpgrade.GetMaxCharges()); if (_chargesRemaining > 0) { _chargesRemaining--; _cooldownTimer = 0.35f; PlayThrowAnimation(player); Vector3 position = (((Object)(object)player.gameplayCamera != (Object)null) ? (((Component)player.gameplayCamera).transform.position + ((Component)player.gameplayCamera).transform.forward * 0.4f) : (((Component)player).transform.position + ((Component)player).transform.forward * 0.4f + Vector3.up * 1.2f)); Vector3 direction = (((Object)(object)player.gameplayCamera != (Object)null) ? ((Component)player.gameplayCamera).transform.forward : ((Component)player).transform.forward); ulong networkObjectId = ((NetworkBehaviour)player).NetworkObjectId; uint beaconId = _nextBeaconId++; int tier = WorklightBeaconUpgrade.GetTier(); ((MonoBehaviour)player).StartCoroutine(DelayedSpawn(networkObjectId, beaconId, tier, position, direction, isLocalThrower: true)); BroadcastThrow(networkObjectId, beaconId, tier, position, direction); } } } private static void WriteThrow(FastBufferWriter writer, ulong playerNetObjId, uint beaconId, int tier, Vector3 position, Vector3 direction) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_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_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref playerNetObjId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref beaconId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref tier, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.x, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.y, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref position.z, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref direction.x, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref direction.y, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref direction.z, default(ForPrimitives)); } private static void BroadcastThrow(ulong playerNetObjId, uint beaconId, int tier, Vector3 position, Vector3 direction) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(40, (Allocator)2, -1); try { WriteThrow(val, playerNetObjId, beaconId, tier, position, direction); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("WorklightBeacon_Throw", val, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("WorklightBeacon_Throw", 0uL, val, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] throw send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RelayThrow(ulong excludeClientId, ulong playerNetObjId, uint beaconId, int tier, Vector3 position, Vector3 direction) { //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_005c: 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) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref val2))..ctor(40, (Allocator)2, -1); try { WriteThrow(val2, playerNetObjId, beaconId, tier, position, direction); val.SendNamedMessage("WorklightBeacon_Throw", connectedClientsId, val2, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[WorklightBeacon] throw relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref val2)).Dispose(); } } } private static PlayerControllerB ResolvePlayerByActualClientId(ulong clientId) { PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return null; } for (int i = 0; i < array.Length; i++) { if ((Object)(object)array[i] != (Object)null && array[i].actualClientId == clientId) { return array[i]; } } return null; } private static void OnReceiveThrowEvent(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_003f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_007e: 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_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) //IL_00a4: 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_0102: 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_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) try { ulong networkObjectId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref networkObjectId, default(ForPrimitives)); uint beaconId = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref beaconId, default(ForPrimitives)); int tier = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref tier, default(ForPrimitives)); float num = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); float num4 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); float num5 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num5, default(ForPrimitives)); float num6 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num6, default(ForPrimitives)); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { PlayerControllerB val = ResolvePlayerByActualClientId(senderClientId); if ((Object)(object)val == (Object)null) { return; } networkObjectId = ((NetworkBehaviour)val).NetworkObjectId; RelayThrow(senderClientId, networkObjectId, beaconId, tier, new Vector3(num, num2, num3), new Vector3(num4, num5, num6)); } PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController; if (!((Object)(object)val2 != (Object)null) || ((NetworkBehaviour)val2).NetworkObjectId != networkObjectId) { MonoBehaviour val3 = (MonoBehaviour)(((Object)(object)HUDManager.Instance != (Object)null) ? ((object)HUDManager.Instance) : ((object)Object.FindObjectOfType())); if ((Object)(object)val3 == (Object)null) { SpawnRemoteAnimationAndBeacon(networkObjectId, beaconId, tier, new Vector3(num, num2, num3), new Vector3(num4, num5, num6)); } else { val3.StartCoroutine(DelayedSpawn(networkObjectId, beaconId, tier, new Vector3(num, num2, num3), new Vector3(num4, num5, num6), isLocalThrower: false)); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] malformed throw sync: " + ex.Message)); } } } private static IEnumerator DelayedSpawn(ulong playerNetObjId, uint beaconId, int tier, Vector3 position, Vector3 direction, bool isLocalThrower) { //IL_001c: 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_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!isLocalThrower) { TriggerRemoteThrowAnimation(playerNetObjId); } yield return (object)new WaitForSeconds(4f / 15f); ResolveReleasePose(playerNetObjId, ref position, ref direction); WorklightBeaconProjectile.Spawn(position, direction, 28f, playerNetObjId, beaconId, tier); } private static void ResolveReleasePose(ulong playerNetObjId, ref Vector3 position, ref Vector3 direction) { //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: 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_0141: 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_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: 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) PlayerControllerB[] array = StartOfRound.Instance?.allPlayerScripts; if (array == null) { return; } foreach (PlayerControllerB val in array) { if (!((Object)(object)val == (Object)null) && ((NetworkBehaviour)val).NetworkObjectId == playerNetObjId) { bool flag = (Object)(object)val == (Object)(object)GameNetworkManager.Instance?.localPlayerController; object root; if (!flag || !((Object)(object)val.playerModelArmsMetarig != (Object)null)) { Animator playerBodyAnimator = val.playerBodyAnimator; root = ((playerBodyAnimator != null) ? ((Component)playerBodyAnimator).transform : null); } else { root = val.playerModelArmsMetarig; } Transform val2 = FindChildRecursive((Transform)root, "hand.R"); direction = ((flag && (Object)(object)val.gameplayCamera != (Object)null) ? ((Component)val.gameplayCamera).transform.forward : ((Component)val).transform.forward); if ((Object)(object)val2 != (Object)null) { position = val2.position + ((Vector3)(ref direction)).normalized * 0.12f; } else if (flag && (Object)(object)val.gameplayCamera != (Object)null) { position = ((Component)val.gameplayCamera).transform.position + ((Vector3)(ref direction)).normalized * 0.35f; } else { position = ((Component)val).transform.position + Vector3.up * 1.2f + ((Vector3)(ref direction)).normalized * 0.25f; } break; } } } private static Transform FindChildRecursive(Transform root, string childName) { if ((Object)(object)root == (Object)null || string.IsNullOrWhiteSpace(childName)) { return null; } if (string.Equals(((Object)root).name, childName, StringComparison.OrdinalIgnoreCase)) { return root; } for (int i = 0; i < root.childCount; i++) { Transform val = FindChildRecursive(root.GetChild(i), childName); if ((Object)(object)val != (Object)null) { return val; } } return null; } private static void SpawnRemoteAnimationAndBeacon(ulong playerNetObjId, uint beaconId, int tier, Vector3 position, Vector3 direction) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) TriggerRemoteThrowAnimation(playerNetObjId); WorklightBeaconProjectile.Spawn(position, direction, 28f, playerNetObjId, beaconId, tier); } private static void RegisterNetworkHandlers() { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //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_007c: Expected O, but got Unknown if (_handlersRegistered || (Object)(object)NetworkManager.Singleton == (Object)null || NetworkManager.Singleton.CustomMessagingManager == null) { return; } try { CustomMessagingManager customMessagingManager = NetworkManager.Singleton.CustomMessagingManager; object obj = <>O.<0>__OnReceiveThrowEvent; if (obj == null) { HandleNamedMessageDelegate val = OnReceiveThrowEvent; <>O.<0>__OnReceiveThrowEvent = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("WorklightBeacon_Throw", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = NetworkManager.Singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnReceivePickupEvent; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnReceivePickupEvent; <>O.<1>__OnReceivePickupEvent = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("WorklightBeacon_Pickup", (HandleNamedMessageDelegate)obj2); _handlersRegistered = true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] RegisterNamedMessageHandler failed: " + ex.Message)); } } } private static void UpdatePrompt(PlayerControllerB player) { if (!WorklightBeaconUpgrade.IsUnlocked() || (Object)(object)player == (Object)null || player.isPlayerDead || player.isTypingChat || player.inTerminalMenu || player.isInHangarShipRoom || ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.inShipPhase) || ((Object)(object)player.quickMenuManager != (Object)null && player.quickMenuManager.isMenuOpen)) { Y4ngzPromptOverlay.ClearPostPlayerMenuPrompt("worklight_beacon"); return; } int maxCharges = WorklightBeaconUpgrade.GetMaxCharges(); EnsureRoundChargeAvailable(maxCharges); string text = UpgradeInput.EffectivePath(Y4NGZUpgrades.Gui.Plugin.Keybinds?.WorklightBeacon); if (_cachedPromptText == null || !string.Equals(_cachedPromptPath, text, StringComparison.Ordinal) || _cachedPromptCharges != _chargesRemaining || _cachedPromptMax != maxCharges) { _cachedPromptPath = text; _cachedPromptCharges = _chargesRemaining; _cachedPromptMax = maxCharges; string arg = UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.WorklightBeacon, "V"); _cachedPromptText = $"Worklights: [{arg}] {_chargesRemaining}/{maxCharges}"; } Y4ngzPromptOverlay.SetPostPlayerMenuPrompt("worklight_beacon", _cachedPromptText); } internal static void TryPickupBeacon(WorklightBeaconProjectile beacon, PlayerControllerB player) { if ((Object)(object)beacon == (Object)null || (Object)(object)player == (Object)null) { return; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if (((Object)(object)val != (Object)null && (Object)(object)player != (Object)(object)val) || !WorklightBeaconUpgrade.IsUnlocked()) { return; } int maxCharges = WorklightBeaconUpgrade.GetMaxCharges(); EnsureRoundChargeAvailable(maxCharges); if (!RefundChargeFromPickup(maxCharges)) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("WORKLIGHT BEACON", "Beacon harness is full.", true, false, "LC_Tip1"); } } else { ulong throwerNetObjId = beacon.ThrowerNetObjId; uint beaconId = beacon.BeaconId; WorklightBeaconProjectile.DestroySynced(throwerNetObjId, beaconId); BroadcastPickup(throwerNetObjId, beaconId); } } private static bool RefundChargeFromPickup(int maxCharges) { if (maxCharges <= 0 || _chargesRemaining >= maxCharges) { return false; } _chargesRemaining = Mathf.Min(maxCharges, _chargesRemaining + 1); return true; } private static void BroadcastPickup(ulong playerNetObjId, uint beaconId) { //IL_0034: 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_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0071: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; if (customMessagingManager == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref playerNetObjId, default(ForPrimitives)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref beaconId, default(ForPrimitives)); if (singleton.IsServer) { customMessagingManager.SendNamedMessageToAll("WorklightBeacon_Pickup", val, (NetworkDelivery)3); } else { customMessagingManager.SendNamedMessage("WorklightBeacon_Pickup", 0uL, val, (NetworkDelivery)3); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] pickup send failed: " + ex.Message)); } } finally { ((FastBufferWriter)(ref val)).Dispose(); } } private static void RelayPickup(ulong excludeClientId, ulong playerNetObjId, uint beaconId) { //IL_005e: 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_0071: 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_0085: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; CustomMessagingManager val = ((singleton != null) ? singleton.CustomMessagingManager : null); if ((Object)(object)singleton == (Object)null || val == null || !singleton.IsServer) { return; } FastBufferWriter val2 = default(FastBufferWriter); foreach (ulong connectedClientsId in singleton.ConnectedClientsIds) { if (connectedClientsId == excludeClientId || connectedClientsId == singleton.LocalClientId) { continue; } ((FastBufferWriter)(ref val2))..ctor(12, (Allocator)2, -1); try { ((FastBufferWriter)(ref val2)).WriteValueSafe(ref playerNetObjId, default(ForPrimitives)); ((FastBufferWriter)(ref val2)).WriteValueSafe(ref beaconId, default(ForPrimitives)); val.SendNamedMessage("WorklightBeacon_Pickup", connectedClientsId, val2, (NetworkDelivery)3); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)$"[WorklightBeacon] pickup relay to {connectedClientsId} failed: {ex.Message}"); } } finally { ((FastBufferWriter)(ref val2)).Dispose(); } } } private static void OnReceivePickupEvent(ulong senderClientId, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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) try { ulong num = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); uint beaconId = default(uint); ((FastBufferReader)(ref reader)).ReadValueSafe(ref beaconId, default(ForPrimitives)); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsServer && senderClientId != singleton.LocalClientId) { RelayPickup(senderClientId, num, beaconId); } WorklightBeaconProjectile.DestroySynced(num, beaconId); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] malformed pickup sync: " + ex.Message)); } } } private static void EnsureRoundChargeAvailable(int maxCharges) { if (!_roundChargeGranted && maxCharges > 0) { _chargesRemaining = maxCharges; _roundChargeGranted = true; } } private static void TriggerRemoteThrowAnimation(ulong playerNetObjId) { if ((Object)(object)StartOfRound.Instance == (Object)null) { return; } PlayerControllerB[] allPlayerScripts = StartOfRound.Instance.allPlayerScripts; foreach (PlayerControllerB val in allPlayerScripts) { if (!((Object)(object)val == (Object)null) && ((NetworkBehaviour)val).NetworkObjectId == playerNetObjId) { PlayThrowAnimation(val); break; } } } private static void PlayThrowAnimation(PlayerControllerB player) { StowHeldItemForThrow(player); if (TryPlayInteractionThrow(player, out var reason) || string.Equals(reason, "player_animator_owned_externally", StringComparison.OrdinalIgnoreCase) || (Object)(object)player == (Object)null || (Object)(object)player.playerBodyAnimator == (Object)null) { return; } try { player.doingUpperBodyEmote = Mathf.Max(player.doingUpperBodyEmote, 1.16f); player.playerBodyAnimator.SetTrigger("PullGrenadePin"); TryPlayThrowState(player.playerBodyAnimator); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] throw animation failed: " + ex.Message)); } } } private static void StowHeldItemForThrow(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return; } HeldItemStowHandle stow = HeldItemStowService.Begin(player, "worklight-beacon-throw", 4f, disableItemActions: false, force: true); if (!stow.IsActive) { return; } try { ((MonoBehaviour)player).StartCoroutine(ReleaseThrowStow(stow)); } catch (Exception ex) { stow.Dispose(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] throw stow release could not start: " + ex.Message)); } } } private static IEnumerator ReleaseThrowStow(HeldItemStowHandle stow) { yield return (object)new WaitForSeconds(1.16f); stow.Dispose(); } private static bool TryPlayInteractionThrow(PlayerControllerB player, out string reason) { //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: 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_00d1: Expected O, but got Unknown //IL_003d: Unknown result type (might be due to invalid IL or missing references) reason = string.Empty; if ((Object)(object)player == (Object)null) { reason = "player_missing"; return false; } InteractionAnimationHandle val3 = default(InteractionAnimationHandle); if ((Object)(object)player != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { InteractionAnimationHandle val = default(InteractionAnimationHandle); if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val)) { LCInteractionAnimationAPI.TryStopInteraction(val, (InteractionAnimationStopReason)2); } RuntimeAnimatorController val2 = StartOfRound.Instance?.otherClientsAnimatorController; if (!LCInteractionAnimationAPI.TryGetActiveInteraction(player, (InteractionAnimationPresentationKind)1, ref val3)) { if ((Object)(object)val2 != (Object)null) { Animator playerBodyAnimator = player.playerBodyAnimator; if ((Object)(object)((playerBodyAnimator != null) ? playerBodyAnimator.runtimeAnimatorController : null) != (Object)(object)val2) { goto IL_0085; } } reason = "remote_uses_vanilla_throw"; return false; } goto IL_0085; } if (!EnsurePackRegistered()) { reason = "interaction_pack_unavailable"; return false; } if (LCInteractionAnimationAPI.TryStartInteraction(new InteractionAnimationRequest { Player = player, PackId = "y4ngz.upgrades.worklight_beacon", InteractionId = "y4ngz.worklight_beacon.throw" }, ref val3, ref reason)) { return true; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] retargeted throw animation failed: " + reason)); } return false; IL_0085: reason = "player_animator_owned_externally"; return false; } private static bool EnsurePackRegistered() { //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Expected O, but got Unknown //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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown if (_packRegistered) { return true; } if (Time.realtimeSinceStartup < _nextRegistrationAttemptAt) { return false; } _nextRegistrationAttemptAt = Time.realtimeSinceStartup + 2f; string directoryName = Path.GetDirectoryName(typeof(Plugin).Assembly.Location); string text = Path.Combine(directoryName ?? string.Empty, "y4ngz-interactions-worklightbeacon-livebody.manifest.json"); if (!File.Exists(text)) { if (!_missingManifestLogged) { _missingManifestLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[WorklightBeacon] retargeted throw manifest not found: " + text)); } } return false; } string manifestJson; try { manifestJson = File.ReadAllText(text); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[WorklightBeacon] retargeted throw manifest read failed: " + ex.Message)); } return false; } InteractionAnimationPackDefinition val = new InteractionAnimationPackDefinition(); val.PackId = "y4ngz.upgrades.worklight_beacon"; val.Version = "1.0.0"; val.AssetRootPath = directoryName ?? string.Empty; val.Interactions = (InteractionAnimationDefinition[])(object)new InteractionAnimationDefinition[1] { new InteractionAnimationDefinition { InteractionId = "y4ngz.worklight_beacon.throw", PresentationKind = (InteractionAnimationPresentationKind)1, ManifestJson = manifestJson } }; string text2 = default(string); if (!LCInteractionAnimationAPI.TryRegisterInteractionPack(val, ref text2)) { if (string.Equals(text2, "pack_already_registered", StringComparison.OrdinalIgnoreCase)) { _packRegistered = true; return true; } ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[WorklightBeacon] retargeted throw pack registration failed: " + text2)); } return false; } _packRegistered = true; _missingManifestLogged = false; ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)"[WorklightBeacon] registered retargeted throw animation pack."); } return true; } private static void TryPlayThrowState(Animator animator) { if (!((Object)(object)animator == (Object)null) && animator.layerCount > 3) { if (animator.HasState(3, ThrowAnimationFullPathHash)) { animator.Play(ThrowAnimationFullPathHash, 3, 0f); } else if (animator.HasState(3, ThrowAnimationHash)) { animator.Play(ThrowAnimationHash, 3, 0f); } } } } } namespace Y4NGZUpgrades.Lucky8 { internal static class Lucky8ButtonPressAnimation { private const string PackId = "y4ngz.upgrades.lucky8"; private const string InteractionId = "y4ngz.lucky8.button_press"; private const string ManifestFile = "y4ngz-lucky8-button-press.manifest.json"; private static bool registered; private static bool playing; internal static void Initialize() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Expected O, but got Unknown //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_007a: 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_0089: Expected O, but got Unknown try { string text = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty; string path = Path.Combine(text, "y4ngz-lucky8-button-press.manifest.json"); if (!File.Exists(path)) { return; } string manifestJson = File.ReadAllText(path); InteractionAnimationPackDefinition val = new InteractionAnimationPackDefinition(); val.PackId = "y4ngz.upgrades.lucky8"; val.Version = "1.0.0"; val.AssetRootPath = text; val.Interactions = (InteractionAnimationDefinition[])(object)new InteractionAnimationDefinition[1] { new InteractionAnimationDefinition { InteractionId = "y4ngz.lucky8.button_press", PresentationKind = (InteractionAnimationPresentationKind)1, ManifestJson = manifestJson } }; string text2 = default(string); registered = LCInteractionAnimationAPI.TryRegisterInteractionPack(val, ref text2); if (!registered) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Button animation pack registration skipped: " + text2)); } } } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[LUCKY-8] Button animation initialization failed: " + ex.Message)); } } } internal static void Play(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !playing) { Y4NGZPersistentRunner.Run(PlayRoutine(player)); } } private static IEnumerator PlayRoutine(PlayerControllerB player) { playing = true; bool restoreMove = player.disableMoveInput; bool restoreLook = player.disableLookInput; bool restoreInteract = player.disableInteract; List disabledActions = new List(); InteractionAnimationHandle handle = InteractionAnimationHandle.Empty; try { disabledActions = DisableItemActions(); player.disableMoveInput = true; player.disableLookInput = true; player.disableInteract = true; string text = default(string); if (registered && !LCInteractionAnimationAPI.TryStartInteraction(new InteractionAnimationRequest { Player = player, PackId = "y4ngz.upgrades.lucky8", InteractionId = "y4ngz.lucky8.button_press" }, ref handle, ref text)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)("[LUCKY-8] Button animation unavailable for this press: " + text)); } } float until = Time.unscaledTime + Lucky8Manager.EffectivePressDuration; while (Time.unscaledTime < until && (Object)(object)player != (Object)null && !player.isPlayerDead) { yield return null; } } finally { if (((InteractionAnimationHandle)(ref handle)).IsValid && LCInteractionAnimationAPI.IsInteractionActive(handle)) { LCInteractionAnimationAPI.TryStopInteraction(handle, (InteractionAnimationStopReason)1); } if ((Object)(object)player != (Object)null) { player.disableMoveInput = restoreMove; player.disableLookInput = restoreLook; player.disableInteract = restoreInteract; } for (int i = 0; i < disabledActions.Count; i++) { InputAction obj = disabledActions[i]; if (obj != null) { obj.Enable(); } } playing = false; } } private static List DisableItemActions() { List list = new List(6); IngamePlayerSettings instance = IngamePlayerSettings.Instance; object obj; if (instance == null) { obj = null; } else { PlayerInput playerInput = instance.playerInput; obj = ((playerInput != null) ? playerInput.actions : null); } InputActionAsset val = (InputActionAsset)obj; if ((Object)(object)val == (Object)null) { return list; } string[] array = new string[6] { "ActivateItem", "ItemSecondaryUse", "ItemTertiaryUse", "SwitchItem", "UseUtilitySlot", "DiscardHeldObject" }; for (int i = 0; i < array.Length; i++) { InputAction val2 = val.FindAction(array[i], false); if (val2 != null && val2.enabled) { val2.Disable(); list.Add(val2); } } return list; } } internal sealed class Lucky8ClaimCapsule : MonoBehaviour { private NetworkObject networkObject; internal Lucky8RewardDefinition Reward { get; private set; } private void Start() { networkObject = ((Component)this).GetComponent(); Lucky8Manager.RegisterCapsule(this); } internal void SetReward(Lucky8RewardDefinition reward) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Expected O, but got Unknown //IL_0074: 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_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: 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_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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) Reward = reward; if (reward == null) { return; } MaterialPropertyBlock val = new MaterialPropertyBlock(); if (!Lucky8RewardPresentation.TryGetColor(reward, out var color)) { color = ((reward.Category == Lucky8RewardCategory.Suit) ? new Color(0.1f, 0.75f, 0.85f) : ((reward.Category == Lucky8RewardCategory.Emote) ? new Color(0.36f, 0.62f, 1f) : new Color(0.78f, 0.25f, 0.9f))); } val.SetColor("_BaseColor", color); val.SetColor("_Color", color); val.SetColor("_EmissiveColor", color * 0.8f); val.SetColor("_EmissionColor", color * 0.8f); Renderer[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Renderer val2 in componentsInChildren) { if (val2.enabled) { val2.SetPropertyBlock(val); } } } internal void TryClaimLocal(GrabbableObject item) { if ((Object)(object)item == (Object)null || (Object)(object)item.playerHeldBy == (Object)null || (Object)(object)item.playerHeldBy != (Object)(object)StartOfRound.Instance?.localPlayerController || Reward == null) { return; } if (!Lucky8RewardUnlockApi.TryClaim(Reward, out var reason)) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LUCKY-8", (reason == "already-owned") ? "You already own this reward. Give the capsule to another employee." : "The capsule could not be claimed.", true, false, "LC_Tip1"); } return; } HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { instance2.DisplayTip("LUCKY-8 PRIZE", Reward.DisplayName + " unlocked.", false, false, "LC_Tip1"); } if ((Object)(object)networkObject != (Object)null) { Lucky8Manager.RequestConsumeCapsule(networkObject.NetworkObjectId); } } private void OnDestroy() { Lucky8Manager.UnregisterCapsule(this); } } internal static class Lucky8CompanyBridge { private const string CompanyAssemblyName = "Y4NGZCompany"; private static Type routeApiType; private static Type placementApiType; private static MethodInfo getRouteCatalog; private static MethodInfo registerMarkerProvider; private static MethodInfo unregisterMarkerProvider; private static MethodInfo requestPlacement; private static bool resolved; internal static bool Initialize() { Resolve(); if (registerMarkerProvider == null) { return false; } try { return Convert.ToBoolean(registerMarkerProvider.Invoke(null, new object[2] { "lucky8", new Func(Lucky8Manager.IsRouteAssigned) })); } catch (Exception error) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Company route marker registration failed: " + Unwrap(error))); } return false; } } internal static void Shutdown() { try { unregisterMarkerProvider?.Invoke(null, new object[1] { "lucky8" }); } catch { } } internal static IReadOnlyList GetRoutes() { Resolve(); List list = new List(); if (getRouteCatalog == null) { return list; } try { if (!(getRouteCatalog.Invoke(null, null) is IEnumerable enumerable)) { return list; } foreach (object item in enumerable) { if (item != null) { Type type = item.GetType(); list.Add(new Lucky8RouteInfo { RouteIndex = Read(type, item, "RouteIndex"), LevelId = Read(type, item, "LevelId"), MoonName = (Read(type, item, "MoonName") ?? string.Empty), ConstellationKey = (Read(type, item, "ConstellationKey") ?? string.Empty), IsCompanyMoon = Read(type, item, "IsCompanyMoon"), HasFacility = Read(type, item, "HasFacility") }); } } } catch (Exception error) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Company route catalog read failed: " + Unwrap(error))); } } return list; } internal static bool RequestPlacement(Action callback) { Resolve(); if (requestPlacement == null || callback == null) { return false; } try { return Convert.ToBoolean(requestPlacement.Invoke(null, new object[7] { "com.y4ngz.upgrades", 1.4f, 2.42f, 0.76f, 1.45f, Mathf.Max(8f, Lucky8Manager.Config.MinEntranceDistance.Value), callback })); } catch (Exception error) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Company placement request failed: " + Unwrap(error))); } return false; } } private static void Resolve() { if (resolved) { return; } resolved = true; Assembly assembly = null; Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly2 in assemblies) { if (string.Equals(assembly2.GetName().Name, "Y4NGZCompany", StringComparison.Ordinal)) { assembly = assembly2; break; } } if (!(assembly == null)) { routeApiType = assembly.GetType("Y4NGZCompany.Core.RouteFeatureApi", throwOnError: false); placementApiType = assembly.GetType("Y4NGZCompany.Core.FacilityFeaturePlacementApi", throwOnError: false); getRouteCatalog = routeApiType?.GetMethod("GetRouteCatalog", BindingFlags.Static | BindingFlags.Public); registerMarkerProvider = routeApiType?.GetMethod("RegisterMarkerProvider", BindingFlags.Static | BindingFlags.Public); unregisterMarkerProvider = routeApiType?.GetMethod("UnregisterMarkerProvider", BindingFlags.Static | BindingFlags.Public); requestPlacement = placementApiType?.GetMethod("RequestLargeBackWallPlacement", BindingFlags.Static | BindingFlags.Public); } } private static T Read(Type type, object instance, string name) { object obj = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public)?.GetValue(instance); if (obj is T) { return (T)obj; } return default(T); } private static string Unwrap(Exception error) { return (error as TargetInvocationException)?.InnerException?.Message ?? error.Message; } } internal sealed class Lucky8Config { internal readonly ConfigEntry Enabled; internal readonly ConfigEntry ChancePerConstellation; internal readonly ConfigEntry TokensPerSpin; internal readonly ConfigEntry SpinsPerMachine; internal readonly ConfigEntry WheelDurationSeconds; internal readonly ConfigEntry ButtonHoldSeconds; internal readonly ConfigEntry ButtonPressSeconds; internal readonly ConfigEntry MinEntranceDistance; internal readonly ConfigEntry WeaponPool; internal readonly ConfigEntry AmmoPool; internal readonly ConfigEntry SuitPool; internal readonly ConfigEntry CosmeticPool; internal readonly ConfigEntry EmotePool; internal readonly ConfigEntry CommonWeight; internal readonly ConfigEntry UncommonWeight; internal readonly ConfigEntry RareWeight; internal readonly ConfigEntry LegendaryWeight; internal readonly ConfigEntry DebugLogging; internal const bool TemporarilyDisabled = true; internal bool FeatureEnabled => false; internal float AssignmentChance => Mathf.Clamp01(ChancePerConstellation.Value); internal int SpinCost => Mathf.Clamp(TokensPerSpin.Value, 1, 99); internal int SpinLimit => Mathf.Clamp(SpinsPerMachine.Value, 1, 8); internal float WheelDuration => Mathf.Clamp(WheelDurationSeconds.Value, 2f, 20f); internal float HoldDuration => Mathf.Clamp(ButtonHoldSeconds.Value, 0.1f, 3f); internal float PressDuration => Mathf.Clamp(ButtonPressSeconds.Value, 0.2f, 3f); internal Lucky8Config(Y4NGZConfigScope config) { Enabled = Bind(config, "General", "Enabled", defaultValue: true, "Spawn the LUCKY-8 facility token prize dispenser.", "Enabled"); ChancePerConstellation = Bind(config, "General", "Chance Per Constellation", 0.35f, "Daily chance that each constellation assigns LUCKY-8 to one eligible moon (0-1).", "Chance Per Constellation"); MinEntranceDistance = Bind(config, "General", "Minimum Entrance Distance", 24f, "Minimum facility path distance from an entrance.", "Minimum Entrance Distance"); TokensPerSpin = Bind(config, "Spin Rules", "Token Cost Per Spin", 3, "Upgrade tokens reserved and spent for an accepted spin.", "Tokens Per Spin"); SpinsPerMachine = Bind(config, "Spin Rules", "Spins Per Machine", 3, "Maximum accepted spins during one facility visit.", "Spins Per Machine"); WheelDurationSeconds = Bind(config, "Spin Rules", "Wheel Duration Seconds", 7.5f, "Time the clockwise selector runs before stopping.", "Wheel Duration Seconds"); ButtonHoldSeconds = Bind(config, "Spin Rules", "Button Hold Seconds", 0.75f, "Interaction hold time on the centre button.", "Button Hold Seconds"); ButtonPressSeconds = Bind(config, "Spin Rules", "Button Press Seconds", 1f, "First-person button press and input-lock duration.", "Button Press Seconds"); WeaponPool = Bind(config, "Reward Pools", "Weapon Pool", "*|Common;revolver|Uncommon;flame_thrower|Rare", "Semicolon-separated stableId|rarity entries. '*' includes all registered Y4NGZ weapons.", "Weapon Pool"); AmmoPool = Bind(config, "Reward Pools", "Ammo Pool", "*|Common", "Semicolon-separated stableId|rarity entries. '*' includes all registered Y4NGZ ammo pickups.", "Ammo Pool"); SuitPool = Bind(config, "Reward Pools", "Suit Pool", "*|Uncommon", "Semicolon-separated stableId|rarity entries. '*' includes all non-default suits.", "Suit Pool"); CosmeticPool = Bind(config, "Reward Pools", "Cosmetic Pool", "*|Uncommon", "Semicolon-separated stableId|rarity entries. '*' includes all MoreCompany cosmetics.", "Cosmetic Pool"); EmotePool = Bind(config, "Reward Pools", "Emote Pool", "*", "Semicolon-separated stableId|rarity entries. '*' includes all eligible unowned TooManyEmotes emotes.", "Emote Pool"); CommonWeight = Bind(config, "Rarity Weights", "Common", 100, "Relative win weight for Common rewards.", "Common Win Weight"); UncommonWeight = Bind(config, "Rarity Weights", "Uncommon", 50, "Relative win weight for Uncommon rewards.", "Uncommon Win Weight"); RareWeight = Bind(config, "Rarity Weights", "Rare", 20, "Relative win weight for Rare rewards.", "Rare Win Weight"); LegendaryWeight = Bind(config, "Rarity Weights", "Legendary", 5, "Relative win weight for Legendary rewards.", "Legendary Win Weight"); DebugLogging = Bind(config, "Troubleshooting", "Debug Logging", defaultValue: false, "Log assignment, lineup, transaction, and payout diagnostics.", "Debug Logging"); } private static ConfigEntry Bind(Y4NGZConfigScope config, string section, string key, T defaultValue, string description, string legacyKey) { return Y4NGZConfigFiles.BindMigrated(config, section, key, defaultValue, description, new LegacyConfigKey("LUCKY-8", legacyKey)); } internal int WeightFor(Lucky8Rarity rarity) { return rarity switch { Lucky8Rarity.Legendary => Mathf.Max(1, LegendaryWeight.Value), Lucky8Rarity.Rare => Mathf.Max(1, RareWeight.Value), Lucky8Rarity.Uncommon => Mathf.Max(1, UncommonWeight.Value), _ => Mathf.Max(1, CommonWeight.Value), }; } } internal sealed class Lucky8ResolvedIcon { internal readonly Texture2D Texture; internal readonly Sprite Sprite; internal Lucky8ResolvedIcon(Texture2D texture, Sprite sprite) { Texture = texture; Sprite = sprite; } } internal static class Lucky8IconResolver { private readonly struct PixelBuffer { internal readonly int Width; internal readonly int Height; internal readonly Color32[] Pixels; internal PixelBuffer(int width, int height, Color32[] pixels) { Width = width; Height = height; Pixels = pixels; } } private const int IconWidth = 256; private const int IconHeight = 184; private const int SourceLimit = 768; private const int PreviewLayer = 23; private const float VisibleAlpha = 0.045f; private static readonly Vector3 PreviewOrigin = new Vector3(0f, -1600f, 0f); private static readonly Dictionary IconCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly Dictionary FallbackCache = new Dictionary(); private static readonly Dictionary CosmeticSources = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly List<(string id, string label)> CosmeticCatalog = new List<(string, string)>(); private static bool cosmeticsDiscovered; private static bool cosmeticPreviewReflectionResolved; private static Type cosmeticApplicationType; private static MethodInfo clearCosmeticsMethod; private static MethodInfo applyCosmeticMethod; private static FieldInfo parentTypeField; private static FieldInfo spawnedCosmeticsField; private static object displayGuyParentType; internal static Lucky8ResolvedIcon Resolve(Lucky8RewardDefinition reward) { Lucky8RewardCategory lucky8RewardCategory = reward?.Category ?? Lucky8RewardCategory.Weapon; if (reward == null) { return GetFallback(lucky8RewardCategory); } string text = BuildCacheKey(reward); if (IconCache.TryGetValue(text, out var value) && (Object)(object)value?.Texture != (Object)null) { return value; } Texture2D val = null; try { switch (lucky8RewardCategory) { case Lucky8RewardCategory.Suit: val = ResolveSuit(reward); break; case Lucky8RewardCategory.Cosmetic: val = ResolveCosmetic(reward); break; case Lucky8RewardCategory.Emote: val = ResolveEmote(reward); break; case Lucky8RewardCategory.Weapon: case Lucky8RewardCategory.Ammo: val = ResolveItem(reward); break; } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Icon resolve failed safely for " + reward.StableId + ": " + ex.Message)); } } Lucky8ResolvedIcon lucky8ResolvedIcon = (((Object)(object)val != (Object)null) ? CreateResolved(val, text) : GetFallback(lucky8RewardCategory)); IconCache[text] = lucky8ResolvedIcon; reward.IconTexture = (Texture)(object)lucky8ResolvedIcon.Texture; return lucky8ResolvedIcon; } internal static IReadOnlyList<(string id, string label)> DiscoverMoreCompanyCosmetics() { if (cosmeticsDiscovered) { return CosmeticCatalog; } cosmeticsDiscovered = true; try { if (!(((FindAssembly("MoreCompany")?.GetType("MoreCompany.Cosmetics.CosmeticRegistry", throwOnError: false))?.GetField("cosmeticInstances", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic))?.GetValue(null) is IDictionary dictionary)) { return CosmeticCatalog; } foreach (DictionaryEntry item in dictionary) { string text = item.Key as string; if (!string.IsNullOrWhiteSpace(text) && item.Value != null) { text = text.Trim(); CosmeticSources[text] = item.Value; CosmeticCatalog.Add((text, Humanize(text))); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] MoreCompany cosmetic discovery failed safely: " + ex.Message)); } } return CosmeticCatalog; } private static Texture2D ResolveItem(Lucky8RewardDefinition reward) { Item val; GameObject prefab; if (reward.Category == Lucky8RewardCategory.Ammo) { val = ArmoryBridge.GetAmmoItem(reward.StableId); prefab = ArmoryBridge.GetAmmoPrizePrefab(reward.StableId); } else { val = ArmoryBridge.GetWeaponItem(reward.StableId); prefab = ArmoryBridge.GetWeaponPrizePrefab(reward.StableId); } if (TryPresentSprite(val?.itemIcon, reward, preserveColor: false, swatch: false, out var result)) { return result; } Texture2D val2 = RenderPrefabOnce(prefab, bust: false); if ((Object)(object)val2 == (Object)null) { return null; } try { return TryPresentTexture((Texture)(object)val2, null, reward, preserveColor: false, swatch: false, out result) ? result : null; } finally { Object.Destroy((Object)(object)val2); } } private static Texture2D ResolveSuit(Lucky8RewardDefinition reward) { Material val = FindSuitMaterial(reward); if (TryPresentTexture(((Object)(object)val != (Object)null) ? val.mainTexture : null, null, reward, preserveColor: true, swatch: true, out var result)) { return result; } Texture2D val2 = RenderEmployeeOnce(val, null); if ((Object)(object)val2 == (Object)null) { return null; } try { return TryPresentTexture((Texture)(object)val2, null, reward, preserveColor: true, swatch: false, out result) ? result : null; } finally { Object.Destroy((Object)(object)val2); } } private static Texture2D ResolveCosmetic(Lucky8RewardDefinition reward) { DiscoverMoreCompanyCosmetics(); if (CosmeticSources.TryGetValue(reward.StableId ?? string.Empty, out var value)) { object obj = GetMemberValue(value, "icon") ?? GetMemberValue(value, "Icon") ?? GetMemberValue(value, "iconTexture"); Sprite val = (Sprite)((obj is Sprite) ? obj : null); if (val != null && TryPresentSprite(val, reward, preserveColor: true, swatch: false, out var result)) { return result; } Texture val2 = (Texture)((obj is Texture) ? obj : null); if (val2 != null && TryPresentTexture(val2, null, reward, preserveColor: true, swatch: false, out result)) { return result; } } Texture2D val3 = RenderEmployeeOnce(null, reward.StableId); if ((Object)(object)val3 == (Object)null) { return null; } try { Texture2D result2; return TryPresentTexture((Texture)(object)val3, null, reward, preserveColor: true, swatch: false, out result2) ? result2 : null; } finally { Object.Destroy((Object)(object)val3); } } private static Texture2D ResolveEmote(Lucky8RewardDefinition reward) { object obj = reward.IconSource; if (obj == null) { obj = TooManyEmotesBridge.FindPurchasableEmote(reward.StableId)?.icon; } Sprite val = (Sprite)((obj is Sprite) ? obj : null); if (val != null && TryPresentSprite(val, reward, preserveColor: true, swatch: false, out var result)) { return result; } Texture val2 = (Texture)((obj is Texture) ? obj : null); if (val2 != null && TryPresentTexture(val2, null, reward, preserveColor: true, swatch: false, out result)) { return result; } return null; } private static Lucky8ResolvedIcon GetFallback(Lucky8RewardCategory category) { if (FallbackCache.TryGetValue(category, out var value) && (Object)(object)value?.Texture != (Object)null) { return value; } string fileName = category switch { Lucky8RewardCategory.Suit => "menu-icon-suits.png", Lucky8RewardCategory.Cosmetic => "menu-icon-cosmetics.png", Lucky8RewardCategory.Emote => "menu-icon-emotes.png", _ => "menu-icon-upgrades.png", }; Lucky8RewardDefinition reward = new Lucky8RewardDefinition { StableId = "category-fallback-" + category, DisplayName = category.ToString(), Category = category, Rarity = Lucky8Rarity.Common }; Texture2D result = null; try { TryPresentTexture((Texture)(object)PurchaseMenu.LoadMenuIconTexture(fileName), null, reward, preserveColor: false, swatch: false, out result); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Category icon asset failed safely for " + category.ToString() + ": " + ex.Message)); } } if ((Object)(object)result == (Object)null) { result = CreateProceduralFallback(reward); } value = CreateResolved(result, "fallback-" + category); FallbackCache[category] = value; return value; } private static bool TryPresentSprite(Sprite sprite, Lucky8RewardDefinition reward, bool preserveColor, bool swatch, out Texture2D result) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) result = null; if ((Object)(object)sprite == (Object)null || (Object)(object)sprite.texture == (Object)null) { return false; } Rect value; try { value = sprite.textureRect; } catch { value = sprite.rect; } return TryPresentTexture((Texture)(object)sprite.texture, value, reward, preserveColor, swatch, out result); } private static bool TryPresentTexture(Texture source, Rect? sourceRect, Lucky8RewardDefinition reward, bool preserveColor, bool swatch, out Texture2D result) { //IL_0079: Unknown result type (might be due to invalid IL or missing references) result = null; if ((Object)(object)source == (Object)null || source.width <= 0 || source.height <= 0) { return false; } if (!swatch && IsPlaceholderName(((Object)source).name)) { return false; } if (!TryReadPixels(source, sourceRect, out var buffer)) { return false; } if ((!swatch && (buffer.Width <= 4 || buffer.Height <= 4)) || !TryBuildMask(buffer, swatch, out var alpha, out var colors, out var content)) { return false; } result = BuildPresentation(alpha, colors, buffer.Width, buffer.Height, content, reward, preserveColor, swatch); return (Object)(object)result != (Object)null; } private static bool TryReadPixels(Texture source, Rect? requested, out PixelBuffer buffer) { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_01a6: Unknown result type (might be due to invalid IL or missing references) //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_01ba: Unknown result type (might be due to invalid IL or missing references) //IL_01c1: Expected O, but got Unknown //IL_01d1: Unknown result type (might be due to invalid IL or missing references) buffer = default(PixelBuffer); Rect val = (Rect)(((??)requested) ?? new Rect(0f, 0f, (float)source.width, (float)source.height)); ((Rect)(ref val)).x = Mathf.Clamp(((Rect)(ref val)).x, 0f, Mathf.Max(0f, (float)source.width - 1f)); ((Rect)(ref val)).y = Mathf.Clamp(((Rect)(ref val)).y, 0f, Mathf.Max(0f, (float)source.height - 1f)); ((Rect)(ref val)).width = Mathf.Clamp(((Rect)(ref val)).width, 1f, (float)source.width - ((Rect)(ref val)).x); ((Rect)(ref val)).height = Mathf.Clamp(((Rect)(ref val)).height, 1f, (float)source.height - ((Rect)(ref val)).y); float num = Mathf.Min(1f, 768f / Mathf.Max(((Rect)(ref val)).width, ((Rect)(ref val)).height)); int num2 = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref val)).width * num)); int num3 = Mathf.Max(1, Mathf.RoundToInt(((Rect)(ref val)).height * num)); RenderTexture val2 = null; RenderTexture active = RenderTexture.active; try { val2 = RenderTexture.GetTemporary(num2, num3, 0, (RenderTextureFormat)0); ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).filterMode = (FilterMode)1; Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(((Rect)(ref val)).width / (float)source.width, ((Rect)(ref val)).height / (float)source.height); Vector2 val4 = default(Vector2); ((Vector2)(ref val4))..ctor(((Rect)(ref val)).x / (float)source.width, ((Rect)(ref val)).y / (float)source.height); Graphics.Blit(source, val2, val3, val4); RenderTexture.active = val2; Texture2D val5 = new Texture2D(num2, num3, (TextureFormat)4, false); val5.ReadPixels(new Rect(0f, 0f, (float)num2, (float)num3), 0, 0, false); val5.Apply(false, false); buffer = new PixelBuffer(num2, num3, val5.GetPixels32()); Object.Destroy((Object)(object)val5); return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Icon pixels were unreadable: " + ex.Message)); } return false; } finally { RenderTexture.active = active; if ((Object)(object)val2 != (Object)null) { RenderTexture.ReleaseTemporary(val2); } } } private static bool TryBuildMask(PixelBuffer buffer, bool swatch, out float[] alpha, out Color32[] colors, out RectInt content) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0233: Unknown result type (might be due to invalid IL or missing references) //IL_0238: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) colors = buffer.Pixels; alpha = new float[colors.Length]; content = default(RectInt); if (colors.Length == 0) { return false; } Color val = AverageCorners(colors, buffer.Width, buffer.Height); int num = 0; for (int i = 0; i < colors.Length; i++) { if (colors[i].a >= 250) { num++; } } bool flag = (float)num >= (float)colors.Length * 0.985f; int num2 = buffer.Width; int num3 = buffer.Height; int num4 = -1; int num5 = -1; int num6 = 0; float num7 = 0f; for (int j = 0; j < buffer.Height; j++) { for (int k = 0; k < buffer.Width; k++) { int num8 = j * buffer.Width + k; Color val2 = Color32.op_Implicit(colors[num8]); float num9 = val2.a; if (flag && !swatch) { float num10 = Mathf.Max(Mathf.Abs(val2.r - val.r), Mathf.Max(Mathf.Abs(val2.g - val.g), Mathf.Abs(val2.b - val.b))); num9 *= Mathf.Clamp01((num10 - 0.025f) * 5.5f); num7 += num10; } else { num7 += Mathf.Max(val2.r, Mathf.Max(val2.g, val2.b)) - Mathf.Min(val2.r, Mathf.Min(val2.g, val2.b)); } alpha[num8] = num9; if (!(num9 < 0.045f)) { num6++; num2 = Mathf.Min(num2, k); num3 = Mathf.Min(num3, j); num4 = Mathf.Max(num4, k); num5 = Mathf.Max(num5, j); } } } if (num6 < Mathf.Max(12, colors.Length / 900)) { return false; } if (flag && !swatch && num7 / (float)colors.Length < 0.015f) { return false; } if (swatch && !IsRecognizableSwatch(colors, num7)) { return false; } content = new RectInt(num2, num3, num4 - num2 + 1, num5 - num3 + 1); if (((RectInt)(ref content)).width > 1) { return ((RectInt)(ref content)).height > 1; } return false; } private static bool IsRecognizableSwatch(Color32[] pixels, float colorEnergy) { //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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: 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_0061: 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_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) if (pixels.Length < 16) { return false; } Color val = Color.black; int num = Mathf.Max(1, pixels.Length / 512); int num2 = 0; for (int i = 0; i < pixels.Length; i += num) { if (pixels[i].a >= 32) { val += Color32.op_Implicit(pixels[i]); num2++; } } if (num2 == 0) { return false; } val /= (float)num2; float num3 = default(float); float num4 = default(float); float num5 = default(float); Color.RGBToHSV(val, ref num3, ref num4, ref num5); if (!(num4 > 0.035f) && (!(num5 > 0.055f) || !(num5 < 0.94f))) { return colorEnergy / (float)pixels.Length > 0.02f; } return true; } private static Texture2D BuildPresentation(float[] sourceAlpha, Color32[] sourceColors, int sourceWidth, int sourceHeight, RectInt content, Lucky8RewardDefinition reward, bool preserveColor, bool swatch) { //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_0194: 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_019b: 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) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) //IL_01ac: Unknown result type (might be due to invalid IL or missing references) //IL_0145: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0346: Unknown result type (might be due to invalid IL or missing references) //IL_034b: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0375: Unknown result type (might be due to invalid IL or missing references) //IL_037c: Unknown result type (might be due to invalid IL or missing references) //IL_0384: Unknown result type (might be due to invalid IL or missing references) //IL_038c: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Expected O, but got Unknown //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01e9: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_01f8: 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_020b: 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_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_030a: Unknown result type (might be due to invalid IL or missing references) //IL_030c: Unknown result type (might be due to invalid IL or missing references) //IL_0311: 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_0226: Unknown result type (might be due to invalid IL or missing references) //IL_022d: Unknown result type (might be due to invalid IL or missing references) //IL_0232: Unknown result type (might be due to invalid IL or missing references) int num = 150; float num2 = Mathf.Min(222f / (float)((RectInt)(ref content)).width, (float)num / (float)((RectInt)(ref content)).height); if (swatch) { num2 *= 0.82f; } int num3 = Mathf.Max(1, Mathf.RoundToInt((float)((RectInt)(ref content)).width * num2)); int num4 = Mathf.Max(1, Mathf.RoundToInt((float)((RectInt)(ref content)).height * num2)); int num5 = (256 - num3) / 2; int num6 = (184 - num4) / 2; float[] array = new float[47104]; Color32[] array2 = (Color32[])(object)new Color32[47104]; for (int i = 0; i < num4; i++) { int num7 = Mathf.Clamp(Mathf.RoundToInt((float)((RectInt)(ref content)).y + ((float)i + 0.5f) * (float)((RectInt)(ref content)).height / (float)num4 - 0.5f), ((RectInt)(ref content)).y, ((RectInt)(ref content)).yMax - 1); for (int j = 0; j < num3; j++) { int num8 = Mathf.Clamp(Mathf.RoundToInt((float)((RectInt)(ref content)).x + ((float)j + 0.5f) * (float)((RectInt)(ref content)).width / (float)num3 - 0.5f), ((RectInt)(ref content)).x, ((RectInt)(ref content)).xMax - 1); int num9 = num7 * sourceWidth + num8; int num10 = (num6 + i) * 256 + num5 + j; array[num10] = sourceAlpha[num9]; array2[num10] = sourceColors[num9]; } } Color val = IconTint(reward); Color val2 = Color.Lerp(new Color(0.96f, 0.97f, 0.94f, 1f), val, 0.28f); Color val3 = Color.Lerp(Color.black, val, 0.42f); Color32[] array3 = (Color32[])(object)new Color32[47104]; for (int k = 0; k < 184; k++) { for (int l = 0; l < 256; l++) { int num11 = k * 256 + l; float num12 = array[num11]; if (num12 >= 0.045f) { Color val4 = val2; if (preserveColor) { Color val5 = Color32.op_Implicit(array2[num11]); val5.a = 1f; val4 = Color.Lerp(val5, val, swatch ? 0.12f : 0.22f); val4 *= 1.12f; val4.a = 1f; } val4.a = Mathf.Clamp01(num12); array3[num11] = Color32.op_Implicit(val4); continue; } float num13 = 0f; for (int m = -3; m <= 3; m++) { if (!(num13 < 0.92f)) { break; } int num14 = k + m; if (num14 < 0 || num14 >= 184) { continue; } for (int n = -3; n <= 3; n++) { if (n * n + m * m <= 9) { int num15 = l + n; if (num15 >= 0 && num15 < 256) { num13 = Mathf.Max(num13, array[num14 * 256 + num15]); } } } } if (num13 >= 0.045f) { Color val6 = val3; val6.a = Mathf.Clamp01(num13 * 0.94f); array3[num11] = Color32.op_Implicit(val6); } } } Texture2D val7 = new Texture2D(256, 184, (TextureFormat)4, false) { name = "Lucky8Icon_" + SafeName(reward?.StableId), filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; val7.SetPixels32(array3); val7.Apply(false, true); return val7; } private static Texture2D CreateProceduralFallback(Lucky8RewardDefinition reward) { //IL_0274: Unknown result type (might be due to invalid IL or missing references) //IL_0279: Unknown result type (might be due to invalid IL or missing references) //IL_0284: Unknown result type (might be due to invalid IL or missing references) //IL_028c: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Unknown result type (might be due to invalid IL or missing references) //IL_02b0: Expected O, but got Unknown //IL_02b6: Expected O, but got Unknown //IL_02c5: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02d5: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Expected O, but got Unknown //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_02ee: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Unknown result type (might be due to invalid IL or missing references) //IL_02f6: 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_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_02ff: Unknown result type (might be due to invalid IL or missing references) //IL_0306: Unknown result type (might be due to invalid IL or missing references) //IL_0307: 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_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_0241: Unknown result type (might be due to invalid IL or missing references) //IL_0246: Unknown result type (might be due to invalid IL or missing references) //IL_024b: Unknown result type (might be due to invalid IL or missing references) Color32[] array = (Color32[])(object)new Color32[4096]; for (int i = 0; i < 64; i++) { for (int j = 0; j < 64; j++) { bool flag; switch (reward.Category) { case Lucky8RewardCategory.Suit: { float num = (float)j - 32f; float num2 = (float)i - 46f; flag = num * num + num2 * num2 <= 64f || (i >= 13 && i <= 38 && j >= 17 && j <= 47 && Mathf.Abs((float)j - 32f) <= 22f - Mathf.Abs((float)i - 24f) * 0.26f); break; } case Lucky8RewardCategory.Cosmetic: { float num6 = Mathf.Atan2((float)i - 32f, (float)j - 32f); float num7 = Vector2.Distance(new Vector2((float)j, (float)i), new Vector2(32f, 32f)); float num8 = 13f + 9f * Mathf.Abs(Mathf.Cos(num6 * 4f)); flag = num7 <= num8; break; } case Lucky8RewardCategory.Ammo: flag = ((j >= 13 && j <= 24) || (j >= 27 && j <= 38) || (j >= 41 && j <= 52)) && i >= 13 && i <= 50 && (i <= 44 || (j % 14 >= 3 && j % 14 <= 9)); break; case Lucky8RewardCategory.Emote: { float num3 = (float)j - 39f; float num4 = (float)j - 28f; float num5 = (float)i - 18f; flag = (num3 * num3 <= 25f && i >= 19 && i <= 48) || num4 * num4 + num5 * num5 <= 100f || (i >= 43 && i <= 49 && j >= 36 && j <= 53); break; } default: flag = (Mathf.Abs((float)i - 18f - ((float)j - 10f) * 0.58f) <= 4f && j >= 8 && j <= 55) || (j >= 10 && j <= 25 && i >= 12 && i <= 23); break; } if (flag) { array[i * 64 + j] = Color32.op_Implicit(Color.white); } } } Texture2D val = new Texture2D(64, 64, (TextureFormat)4, false) { name = "Lucky8ProceduralFallbackSource", hideFlags = (HideFlags)61 }; val.SetPixels32(array); val.Apply(false, false); TryPresentTexture((Texture)val, null, reward, preserveColor: false, swatch: false, out var result); Object.Destroy((Object)val); if ((Object)(object)result != (Object)null) { return result; } Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false) { name = "Lucky8EmergencyFallback", hideFlags = (HideFlags)61 }; Color val3 = IconTint(reward); val2.SetPixels((Color[])(object)new Color[4] { val3, val3, val3, val3 }); val2.Apply(false, true); return val2; } private static Texture2D RenderPrefabOnce(GameObject prefab, bool bust) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Expected O, but got Unknown //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)prefab == (Object)null) { return null; } GameObject val = null; try { val = new GameObject("Lucky8_OneShotItemPreview"); val.SetActive(false); val.transform.position = PreviewOrigin; GameObject obj = Object.Instantiate(prefab, val.transform, false); ((Object)obj).name = "Lucky8_ItemPreviewClone"; obj.transform.localPosition = Vector3.zero; obj.transform.localRotation = Quaternion.identity; DisableBehaviours(obj); SetLayerRecursively(val, 23); obj.SetActive(true); val.SetActive(true); return CaptureRoot(val, bust); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Item preview failed safely: " + ex.Message)); } return null; } finally { DestroyTemporaryRoot(val); } } private static Texture2D RenderEmployeeOnce(Material suitMaterial, string cosmeticId) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: 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) GameObject val = null; try { PlayerControllerB val2 = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val2 == (Object)null || (Object)(object)val2.thisPlayerModel == (Object)null) { return null; } val = new GameObject("Lucky8_OneShotEmployeePreview"); val.SetActive(false); val.transform.position = PreviewOrigin; GameObject val3 = Object.Instantiate(((Component)val2).gameObject, val.transform, false); ((Object)val3).name = "Lucky8_EmployeePreviewClone"; val3.transform.localPosition = Vector3.zero; val3.transform.localRotation = Quaternion.Euler(0f, 180f, 0f); val3.transform.localScale = Vector3.one; DisableBehaviours(val3); Renderer[] componentsInChildren = val3.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } Transform val4 = val3.transform.Find("ScavengerModel"); Transform val5 = (((Object)(object)val4 != (Object)null) ? val4.Find("metarig") : null); SkinnedMeshRenderer val6 = (((Object)(object)val2.thisPlayerModel != (Object)null) ? FindBodyRenderer(val4) : null); if ((Object)(object)val6 == (Object)null || (Object)(object)val5 == (Object)null) { return null; } ((Component)val6).gameObject.SetActive(true); ((Renderer)val6).enabled = true; val6.updateWhenOffscreen = true; ((Renderer)val6).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)val6).sharedMaterial = (((Object)(object)suitMaterial != (Object)null) ? suitMaterial : ((Renderer)val2.thisPlayerModel).sharedMaterial); SetLayerRecursively(val, 23); val.SetActive(true); if (!string.IsNullOrWhiteSpace(cosmeticId) && !TryApplySingleCosmetic(((Component)val5).gameObject, cosmeticId)) { return null; } SetLayerRecursively(val, 23); return CaptureRoot(val, bust: true); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Employee preview failed safely: " + ex.Message)); } return null; } finally { DestroyTemporaryRoot(val); } } private static Texture2D CaptureRoot(GameObject root, bool bust) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Expected O, but got Unknown //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: 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_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0216: 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_0221: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_022f: Unknown result type (might be due to invalid IL or missing references) //IL_0243: Unknown result type (might be due to invalid IL or missing references) //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0259: Unknown result type (might be due to invalid IL or missing references) //IL_0262: Unknown result type (might be due to invalid IL or missing references) //IL_0267: Unknown result type (might be due to invalid IL or missing references) //IL_026c: Unknown result type (might be due to invalid IL or missing references) //IL_0271: Unknown result type (might be due to invalid IL or missing references) //IL_0280: Unknown result type (might be due to invalid IL or missing references) //IL_0285: Unknown result type (might be due to invalid IL or missing references) //IL_0298: Unknown result type (might be due to invalid IL or missing references) //IL_02c0: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_036e: Unknown result type (might be due to invalid IL or missing references) //IL_0373: Unknown result type (might be due to invalid IL or missing references) //IL_037e: Unknown result type (might be due to invalid IL or missing references) //IL_0386: Unknown result type (might be due to invalid IL or missing references) //IL_039b: Unknown result type (might be due to invalid IL or missing references) //IL_03a8: Unknown result type (might be due to invalid IL or missing references) //IL_03b2: Expected O, but got Unknown //IL_007e: 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_00a7: 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) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) Renderer[] componentsInChildren = root.GetComponentsInChildren(true); List list = new List(componentsInChildren.Length); Bounds val = default(Bounds); bool flag = false; Vector3 val3; foreach (Renderer val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !val2.enabled || !((Component)val2).gameObject.activeInHierarchy || (!(val2 is MeshRenderer) && !(val2 is SkinnedMeshRenderer))) { continue; } Bounds bounds = val2.bounds; val3 = ((Bounds)(ref bounds)).size; if (((Vector3)(ref val3)).sqrMagnitude <= 1E-06f) { continue; } val3 = ((Bounds)(ref bounds)).size; if (!(((Vector3)(ref val3)).sqrMagnitude > 100000f)) { list.Add(val2); if (!flag) { val = bounds; flag = true; } else { ((Bounds)(ref val)).Encapsulate(bounds); } } } if (!flag || list.Count == 0) { return null; } GameObject val4 = new GameObject("Lucky8_OneShotPreviewCamera"); val4.transform.SetParent(root.transform, true); val4.layer = 23; Camera val5 = val4.AddComponent(); val5.cameraType = (CameraType)4; val5.clearFlags = (CameraClearFlags)2; val5.backgroundColor = new Color(0f, 0f, 0f, 0f); val5.cullingMask = 8388608; val5.nearClipPlane = 0.03f; val5.farClipPlane = 50f; val5.allowHDR = false; val5.allowMSAA = false; val5.orthographic = true; ((Behaviour)val5).enabled = false; Vector3 center = ((Bounds)(ref val)).center; float num = ((Bounds)(ref val)).size.y; if (bust) { center.y += ((Bounds)(ref val)).size.y * 0.19f; num *= 0.64f; } float num2 = 1.3913044f; val5.orthographicSize = Mathf.Max(num * 0.58f, ((Bounds)(ref val)).size.x / num2 * 0.64f); val5.orthographicSize = Mathf.Max(val5.orthographicSize, 0.08f); val3 = new Vector3(0.82f, 0.18f, -1f); Vector3 normalized = ((Vector3)(ref val3)).normalized; Transform transform = ((Component)val5).transform; Vector3 val6 = center; val3 = ((Bounds)(ref val)).extents; transform.position = val6 - normalized * Mathf.Max(2f, ((Vector3)(ref val3)).magnitude * 3.2f); ((Component)val5).transform.rotation = Quaternion.LookRotation(center - ((Component)val5).transform.position, Vector3.up); GameObject val7 = new GameObject("Lucky8_OneShotPreviewLight"); val7.transform.SetParent(val4.transform, false); val7.layer = 23; Light val8 = val7.AddComponent(); val8.type = (LightType)0; val8.color = new Color(1f, 0.92f, 0.82f); val8.intensity = 55f; val3 = ((Bounds)(ref val)).extents; val8.range = Mathf.Max(12f, ((Vector3)(ref val3)).magnitude * 8f); val8.innerSpotAngle = 80f; val8.spotAngle = 110f; val8.shadows = (LightShadows)0; RenderTexture val9 = null; RenderTexture active = RenderTexture.active; try { val9 = RenderTexture.GetTemporary(512, 368, 24, (RenderTextureFormat)0); ((Texture)val9).filterMode = (FilterMode)1; ((Texture)val9).wrapMode = (TextureWrapMode)1; val5.targetTexture = val9; val5.Render(); RenderTexture.active = val9; Texture2D val10 = new Texture2D(512, 368, (TextureFormat)4, false) { name = "Lucky8_OneShotPreviewCapture", hideFlags = (HideFlags)61 }; val10.ReadPixels(new Rect(0f, 0f, 512f, 368f), 0, 0, false); val10.Apply(false, false); return val10; } finally { val5.targetTexture = null; ((Behaviour)val5).enabled = false; RenderTexture.active = active; if ((Object)(object)val9 != (Object)null) { RenderTexture.ReleaseTemporary(val9); } ((Behaviour)val8).enabled = false; val4.SetActive(false); Object.Destroy((Object)(object)val4); } } private static bool TryApplySingleCosmetic(GameObject metarig, string cosmeticId) { //IL_00e6: 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) ResolveCosmeticPreviewReflection(); if ((Object)(object)metarig == (Object)null || cosmeticApplicationType == null || applyCosmeticMethod == null) { return false; } try { Component val = metarig.AddComponent(cosmeticApplicationType); if (parentTypeField != null && displayGuyParentType != null) { parentTypeField.SetValue(val, displayGuyParentType); } applyCosmeticMethod.Invoke(val, new object[2] { cosmeticId, true }); int num = 0; if (spawnedCosmeticsField?.GetValue(val) is IEnumerable enumerable) { foreach (object item in enumerable) { object obj = ((item is Component) ? item : null); object obj2 = ((obj != null) ? ((Component)obj).transform : null); if (obj2 == null) { object obj3 = ((item is GameObject) ? item : null); obj2 = ((obj3 != null) ? ((GameObject)obj3).transform : null); } Transform val2 = (Transform)obj2; if (!((Object)(object)val2 == (Object)null)) { val2.localScale *= 0.38f; num++; } } } Behaviour val3 = (Behaviour)(object)((val is Behaviour) ? val : null); if (val3 != null) { val3.enabled = false; } return num > 0; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] MoreCompany cosmetic preview failed safely: " + ex.Message)); } return false; } } private static void ResolveCosmeticPreviewReflection() { if (cosmeticPreviewReflectionResolved) { return; } cosmeticPreviewReflectionResolved = true; try { Assembly assembly = FindAssembly("MoreCompany"); cosmeticApplicationType = assembly?.GetType("MoreCompany.Cosmetics.CosmeticApplication", throwOnError: false); clearCosmeticsMethod = cosmeticApplicationType?.GetMethod("ClearCosmetics", Type.EmptyTypes); applyCosmeticMethod = cosmeticApplicationType?.GetMethod("ApplyCosmetic", new Type[2] { typeof(string), typeof(bool) }); parentTypeField = cosmeticApplicationType?.GetField("parentType", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); spawnedCosmeticsField = cosmeticApplicationType?.GetField("spawnedCosmetics", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Type type = assembly?.GetType("MoreCompany.Cosmetics.ParentType", throwOnError: false); if (type != null) { displayGuyParentType = Enum.Parse(type, "DisplayGuy"); } } catch { cosmeticApplicationType = null; } } private static void DisableBehaviours(GameObject root) { if ((Object)(object)root == (Object)null) { return; } ResolveCosmeticPreviewReflection(); Behaviour[] componentsInChildren = root.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } if (cosmeticApplicationType == null || clearCosmeticsMethod == null) { return; } try { Component[] componentsInChildren2 = root.GetComponentsInChildren(cosmeticApplicationType, true); foreach (Component obj in componentsInChildren2) { clearCosmeticsMethod.Invoke(obj, null); } } catch { } } private static SkinnedMeshRenderer FindBodyRenderer(Transform model) { if ((Object)(object)model == (Object)null) { return null; } SkinnedMeshRenderer[] componentsInChildren = ((Component)model).GetComponentsInChildren(true); foreach (SkinnedMeshRenderer val in componentsInChildren) { if (string.Equals(((Object)val).name, "LOD1", StringComparison.Ordinal)) { return val; } } return null; } private static Material FindSuitMaterial(Lucky8RewardDefinition reward) { List list = StartOfRound.Instance?.unlockablesList?.unlockables; if (list == null) { return null; } for (int i = 0; i < list.Count; i++) { UnlockableItem val = list[i]; if (val != null && val.unlockableType == 0 && !((Object)(object)val.suitMaterial == (Object)null)) { string text = (string.IsNullOrWhiteSpace(val.unlockableName) ? ("Suit " + i) : val.unlockableName.Trim()); if (string.Equals(text, reward.DisplayName, StringComparison.OrdinalIgnoreCase) || string.Equals(Slug(text), reward.StableId, StringComparison.OrdinalIgnoreCase)) { return val.suitMaterial; } } } return null; } private static Lucky8ResolvedIcon CreateResolved(Texture2D texture, string name) { //IL_0050: 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) if ((Object)(object)texture == (Object)null) { return null; } ((Object)texture).name = "Lucky8_" + SafeName(name); ((Object)texture).hideFlags = (HideFlags)61; ((Texture)texture).wrapMode = (TextureWrapMode)1; ((Texture)texture).filterMode = (FilterMode)1; Sprite val = Sprite.Create(texture, new Rect(0f, 0f, (float)((Texture)texture).width, (float)((Texture)texture).height), new Vector2(0.5f, 0.5f), 100f); ((Object)val).name = ((Object)texture).name + "_Sprite"; ((Object)val).hideFlags = (HideFlags)61; return new Lucky8ResolvedIcon(texture, val); } private static Color IconTint(Lucky8RewardDefinition reward) { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: 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_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) Lucky8RewardCategory lucky8RewardCategory = reward?.Category ?? Lucky8RewardCategory.Weapon; Color val = default(Color); switch (lucky8RewardCategory) { case Lucky8RewardCategory.Suit: ((Color)(ref val))..ctor(0.14f, 0.78f, 0.88f); break; case Lucky8RewardCategory.Cosmetic: ((Color)(ref val))..ctor(0.82f, 0.3f, 0.94f); break; case Lucky8RewardCategory.Ammo: ((Color)(ref val))..ctor(1f, 0.79f, 0.2f); break; case Lucky8RewardCategory.Emote: { val = (Color)(Lucky8RewardPresentation.TryGetColor(reward, out var color) ? color : new Color(0.36f, 0.62f, 1f)); break; } default: ((Color)(ref val))..ctor(1f, 0.47f, 0.1f); break; } Color val2 = Color.HSVToRGB((float)(StableHash(reward?.StableId) % 1000) / 1000f, 0.58f, 1f); float num = ((lucky8RewardCategory == Lucky8RewardCategory.Suit || lucky8RewardCategory == Lucky8RewardCategory.Cosmetic || lucky8RewardCategory == Lucky8RewardCategory.Emote) ? 0.22f : 0.08f); Color val3 = Color.Lerp(val, val2, num); float num2 = 0.92f + 0.08f * (float)(int)(reward?.Rarity ?? Lucky8Rarity.Common); return val3 * num2; } private static Color AverageCorners(Color32[] pixels, int width, int height) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (pixels.Length == 0) { return Color.clear; } int num = Mathf.Max(1, width / 12); int num2 = Mathf.Max(1, height / 12); Color val = Color.clear; int num3 = 0; for (int i = 0; i < height; i++) { if (i >= num2 && i < height - num2) { continue; } for (int j = 0; j < width; j++) { if (j < num || j >= width - num) { val += Color32.op_Implicit(pixels[i * width + j]); num3++; } } } if (num3 <= 0) { return Color32.op_Implicit(pixels[0]); } return val / (float)num3; } private static object GetMemberValue(object instance, string name) { if (instance == null) { return null; } try { Type type = instance.GetType(); return type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) ?? type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance, null); } catch { return null; } } private static Assembly FindAssembly(string name) { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); foreach (Assembly assembly in assemblies) { if (string.Equals(assembly.GetName().Name, name, StringComparison.Ordinal)) { return assembly; } } return null; } private static void SetLayerRecursively(GameObject root, int layer) { if (!((Object)(object)root == (Object)null)) { root.layer = layer; for (int i = 0; i < root.transform.childCount; i++) { SetLayerRecursively(((Component)root.transform.GetChild(i)).gameObject, layer); } } } private static void DestroyTemporaryRoot(GameObject root) { if (!((Object)(object)root == (Object)null)) { root.SetActive(false); Object.Destroy((Object)(object)root); } } private static string BuildCacheKey(Lucky8RewardDefinition reward) { return reward.Category.ToString() + ":" + (reward.StableId ?? string.Empty) + ":" + reward.Rarity; } private static bool IsPlaceholderName(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } if (value.IndexOf("placeholder", StringComparison.OrdinalIgnoreCase) < 0 && value.IndexOf("default", StringComparison.OrdinalIgnoreCase) < 0 && value.IndexOf("simpleicon", StringComparison.OrdinalIgnoreCase) < 0) { return value.IndexOf("missing", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } private static string Humanize(string value) { if (string.IsNullOrWhiteSpace(value)) { return "Cosmetic"; } return value.Replace('_', ' ').Replace('-', ' ').Trim(); } private static string Slug(string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } char[] array = value.ToLowerInvariant().ToCharArray(); for (int i = 0; i < array.Length; i++) { if (!char.IsLetterOrDigit(array[i])) { array[i] = '_'; } } return new string(array).Trim('_'); } private static string SafeName(string value) { if (string.IsNullOrWhiteSpace(value)) { return "Unknown"; } return value.Replace(':', '_').Replace('/', '_').Replace('\\', '_'); } private static uint StableHash(string value) { uint num = 2166136261u; string text = value ?? string.Empty; for (int i = 0; i < text.Length; i++) { num ^= text[i]; num *= 16777619; } return num; } } internal sealed class Lucky8MachineBehaviour : MonoBehaviour { private const float ScreenRampSeconds = 0.45f; private const float NearZeroEmission = 0.015f; private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor"); private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly int EmissiveColorId = Shader.PropertyToID("_EmissiveColor"); private static readonly int EmissionColorId = Shader.PropertyToID("_EmissionColor"); private static readonly int BaseColorMapId = Shader.PropertyToID("_BaseColorMap"); private static readonly int MainTexId = Shader.PropertyToID("_MainTex"); private readonly Renderer[] screens = (Renderer[])(object)new Renderer[8]; private readonly MaterialPropertyBlock[] screenBlocks = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[8]; private readonly Color[] authoredScreenEmission = (Color[])(object)new Color[8]; private readonly Renderer[] frames = (Renderer[])(object)new Renderer[8]; private readonly MaterialPropertyBlock[] frameBlocks = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[8]; private readonly Lucky8RewardDefinition[] resolvedRewardSources = new Lucky8RewardDefinition[8]; private readonly Lucky8ResolvedIcon[] resolvedIcons = new Lucky8ResolvedIcon[8]; private readonly TextMeshPro[] labels = (TextMeshPro[])(object)new TextMeshPro[8]; private readonly Renderer[] tokenLeds = (Renderer[])(object)new Renderer[3]; private readonly MaterialPropertyBlock[] tokenLedBlocks = (MaterialPropertyBlock[])(object)new MaterialPropertyBlock[3]; private NetworkObject networkObject; private InteractTrigger trigger; private AudioSource audioSource; private Light marqueeLight; private Light rewardBayLight; private int lastHighlight = -2; private byte lastSoldMask = byte.MaxValue; private int lastSpins = -1; private bool lastWasSpinning; private bool visualStateInitialized; private bool promptInitialized; private bool lastPromptSpinning; private byte lastPromptSoldMask; private int lastPromptSpins; private int lastPromptCost; private int lastPromptAvailableTokens; private float lastPromptHoldDuration; private float screenEmissionLevel; private float nextRefresh; internal Vector3 PrizeChutePosition { get { //IL_004b: 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_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_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003f: 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) Transform val = FindDeep(((Component)this).transform, "PrizeChute"); if (!((Object)(object)val != (Object)null)) { return ((Component)this).transform.position + ((Component)this).transform.forward + Vector3.up * 0.35f; } return val.position + ((Component)this).transform.forward * 0.55f + Vector3.up * 0.1f; } } private void Start() { networkObject = ((Component)this).GetComponent(); DiscoverParts(); ConfigureLights(); ConfigureInteraction(); ConfigureAudio(); Lucky8Manager.RegisterMachine(this); } private void Update() { if (!((Object)(object)networkObject == (Object)null) && networkObject.IsSpawned && Lucky8Manager.TryGetState(networkObject.NetworkObjectId, out var state)) { int num = ResolveHighlight(state); float num2 = (IsRewardLightingActive(state) ? 1f : 0f); float num3 = screenEmissionLevel; screenEmissionLevel = Mathf.MoveTowards(screenEmissionLevel, num2, Time.unscaledDeltaTime / 0.45f); if (!Mathf.Approximately(num3, screenEmissionLevel) || Time.unscaledTime >= nextRefresh || num != lastHighlight || state.SoldMask != lastSoldMask || state.SpinsRemaining != lastSpins) { nextRefresh = Time.unscaledTime + 0.2f; ApplyState(state, num); } UpdatePrompt(state); UpdateLights(state); } } internal void PlayTick() { if ((Object)(object)audioSource != (Object)null && (Object)(object)Lucky8ProceduralAudio.Tick != (Object)null) { audioSource.PlayOneShot(Lucky8ProceduralAudio.Tick, 0.42f); } } internal void PlayWin() { if ((Object)(object)audioSource != (Object)null && (Object)(object)Lucky8ProceduralAudio.Win != (Object)null) { audioSource.PlayOneShot(Lucky8ProceduralAudio.Win, 0.65f); } } private void DiscoverParts() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: 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) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_01dc: Unknown result type (might be due to invalid IL or missing references) //IL_01e2: Expected O, but got Unknown //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Expected O, but got Unknown for (int i = 0; i < 8; i++) { Transform val = FindDeep(((Component)this).transform, "RewardSlot_" + i); screens[i] = (((Object)(object)val != (Object)null) ? ((Component)val).GetComponentInChildren(true) : null); if ((Object)(object)screens[i] != (Object)null) { screenBlocks[i] = new MaterialPropertyBlock(); screens[i].GetPropertyBlock(screenBlocks[i]); authoredScreenEmission[i] = ReadAuthoredEmission(screens[i]); Color val2 = authoredScreenEmission[i] * 0.015f; screenBlocks[i].SetColor(EmissiveColorId, val2); screenBlocks[i].SetColor(EmissionColorId, val2); screens[i].SetPropertyBlock(screenBlocks[i]); } Transform val3 = FindDeep(((Component)this).transform, "RewardFrame_" + i); frames[i] = (((Object)(object)val3 != (Object)null) ? ((Component)val3).GetComponentInChildren(true) : null); if ((Object)(object)frames[i] != (Object)null) { frameBlocks[i] = new MaterialPropertyBlock(); frames[i].GetPropertyBlock(frameBlocks[i]); } if ((Object)(object)val != (Object)null) { labels[i] = CreateLabel(val, "RewardLabel_" + i, 1f); } } for (int j = 0; j < 3; j++) { Transform val4 = FindDeep(((Component)this).transform, "TokenLed_" + j); tokenLeds[j] = (((Object)(object)val4 != (Object)null) ? ((Component)val4).GetComponentInChildren(true) : null); if ((Object)(object)tokenLeds[j] != (Object)null) { tokenLedBlocks[j] = new MaterialPropertyBlock(); tokenLeds[j].GetPropertyBlock(tokenLedBlocks[j]); } } } private void ConfigureLights() { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) string text = null; marqueeLight = CreatePointLight(FindDeep(((Component)this).transform, "MarqueeLightAnchor"), new Color(1f, 0.38f, 0.3f), 2.5f, 85f, "marquee", out var issue); if (!string.IsNullOrEmpty(issue)) { text = issue; } rewardBayLight = CreatePointLight(FindDeep(((Component)this).transform, "RewardBayLightAnchor"), new Color(1f, 0.68f, 0.42f), 2f, 65f, "reward bay", out var issue2); if (!string.IsNullOrEmpty(issue2)) { text = (string.IsNullOrEmpty(text) ? issue2 : (text + "; " + issue2)); } if (!string.IsNullOrEmpty(text)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Light setup degraded: " + text)); } } } private static Light CreatePointLight(Transform anchor, Color color, float range, float lumens, string label, out string issue) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) issue = null; if ((Object)(object)anchor == (Object)null) { issue = label + " anchor is missing"; return null; } try { Light val = ((Component)anchor).GetComponent() ?? ((Component)anchor).gameObject.AddComponent(); val.type = (LightType)2; val.color = color; val.range = range; val.intensity = 1f; val.shadows = (LightShadows)0; val.bounceIntensity = 0f; ((Behaviour)val).enabled = false; HDAdditionalLightData val2 = ((Component)anchor).GetComponent() ?? ((Component)anchor).gameObject.AddComponent(); if ((Object)(object)val2 == (Object)null) { issue = label + " HDAdditionalLightData is missing"; return val; } val2.SetLightTypeAndShape((HDLightTypeAndShape)0); val2.SetRange(range); val2.SetIntensity(lumens, (LightUnit)0); val2.EnableShadows(false); return val; } catch (Exception ex) { issue = label + " HDRP light failed (" + ex.GetType().Name + ")"; return ((Component)anchor).GetComponent(); } } private void UpdateLights(Lucky8MachineState state) { if ((Object)(object)marqueeLight != (Object)null) { ((Behaviour)marqueeLight).enabled = IsMachinePowered(state); } if ((Object)(object)rewardBayLight != (Object)null) { ((Behaviour)rewardBayLight).enabled = IsRewardLightingActive(state); } } private static bool IsMachinePowered(Lucky8MachineState state) { if (state != null && !state.IsSpinning && state.SpinsRemaining > 0) { return state.SoldMask != byte.MaxValue; } return false; } private static bool IsRewardLightingActive(Lucky8MachineState state) { if (state != null) { if (!state.IsSpinning) { return state.WinnerIndex >= 0; } return true; } return false; } private void ConfigureInteraction() { //IL_0143: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Expected O, but got Unknown Transform val = FindDeep(((Component)this).transform, "CenterButton"); GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : ((Component)this).gameObject); int num = LayerMask.NameToLayer("InteractableObject"); val2.layer = ((num >= 0) ? num : 9); TrySetTag(val2, "InteractTrigger"); if ((Object)(object)val2.GetComponent() == (Object)null) { SphereCollider obj = val2.AddComponent(); obj.radius = 0.18f; ((Collider)obj).isTrigger = true; } trigger = val2.GetComponent() ?? val2.AddComponent(); trigger.interactable = true; trigger.oneHandedItemAllowed = true; trigger.twoHandedItemAllowed = true; trigger.holdInteraction = true; trigger.timeToHold = Lucky8Manager.EffectiveHoldDuration; trigger.timeToHoldSpeedMultiplier = 1f; trigger.interactCooldown = true; trigger.cooldownTime = 0.5f; trigger.hoverTip = "Insert 3 tokens : [" + UpgradeInteractInput.DisplayLabel() + "]"; trigger.disabledHoverTip = "[ LUCKY-8 unavailable ]"; trigger.disableTriggerMesh = true; if (trigger.onInteract == null) { trigger.onInteract = new InteractEvent(); } ((UnityEvent)(object)trigger.onInteract).RemoveListener((UnityAction)OnInteract); ((UnityEvent)(object)trigger.onInteract).AddListener((UnityAction)OnInteract); } private void ConfigureAudio() { Lucky8ProceduralAudio.Ensure(); audioSource = ((Component)this).gameObject.AddComponent(); audioSource.spatialBlend = 1f; audioSource.minDistance = 1.5f; audioSource.maxDistance = 14f; audioSource.rolloffMode = (AudioRolloffMode)1; audioSource.clip = Lucky8ProceduralAudio.Hum; audioSource.loop = true; audioSource.volume = 0.11f; audioSource.Play(); } private void OnInteract(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && !((Object)(object)player != (Object)(object)StartOfRound.Instance?.localPlayerController) && !((Object)(object)networkObject == (Object)null)) { Lucky8Manager.TryBeginLocalSpin(networkObject.NetworkObjectId, player); } } private int ResolveHighlight(Lucky8MachineState state) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!state.IsSpinning) { return state.WinnerIndex; } NetworkManager singleton = NetworkManager.Singleton; double num; if (singleton == null) { num = Time.timeAsDouble; } else { NetworkTime serverTime = singleton.ServerTime; num = ((NetworkTime)(ref serverTime)).Time; } float num2 = Mathf.Clamp01((float)((num - state.SpinStartedAt) / (double)Math.Max(0.1f, state.SpinDuration))); int num3 = Mathf.Clamp(state.WinnerIndex, 0, 7); int num4 = 24 + num3; float num5 = 1f - Mathf.Pow(1f - num2, 3f); return Mathf.Min(num4, Mathf.FloorToInt((float)num4 * num5)) % 8; } private void ApplyState(Lucky8MachineState state, int highlight) { //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_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_01e3: Unknown result type (might be due to invalid IL or missing references) //IL_01cd: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0179: Unknown result type (might be due to invalid IL or missing references) //IL_0163: Unknown result type (might be due to invalid IL or missing references) bool flag = !visualStateInitialized || state.SoldMask != lastSoldMask; if (state.IsSpinning && highlight != lastHighlight) { PlayTick(); } if (!state.IsSpinning && lastWasSpinning && highlight == state.WinnerIndex) { PlayWin(); } for (int i = 0; i < 8; i++) { Lucky8RewardDefinition lucky8RewardDefinition = state.Rewards[i]; bool flag2 = state.IsSold(i); bool flag3 = resolvedRewardSources[i] != lucky8RewardDefinition; if (flag3 || (Object)(object)resolvedIcons[i]?.Texture == (Object)null) { resolvedRewardSources[i] = lucky8RewardDefinition; resolvedIcons[i] = Lucky8IconResolver.Resolve(lucky8RewardDefinition); } bool highlighted = i == highlight; Color accent = FrameColor(lucky8RewardDefinition); ApplyScreen(screens[i], screenBlocks[i], authoredScreenEmission[i], (Texture)(object)resolvedIcons[i]?.Texture, accent, highlighted, flag2, screenEmissionLevel); ApplyFrame(frames[i], frameBlocks[i], accent, highlighted, flag2); if ((flag || flag3) && (Object)(object)labels[i] != (Object)null) { ((TMP_Text)labels[i]).text = (flag2 ? "SOLD\nOUT" : ShortLabel(lucky8RewardDefinition?.DisplayName)); ((Graphic)labels[i]).color = (Color)(flag2 ? new Color(0.9f, 0.16f, 0.1f) : Color.white); } } for (int j = 0; j < tokenLeds.Length; j++) { ApplyEmission(tokenLeds[j], tokenLedBlocks[j], j < Mathf.Min(3, Lucky8Manager.EffectiveSpinCost), (j < state.SpinsRemaining) ? new Color(1f, 0.55f, 0.08f) : new Color(0.15f, 0.05f, 0.03f)); } lastHighlight = highlight; lastSoldMask = state.SoldMask; lastSpins = state.SpinsRemaining; lastWasSpinning = state.IsSpinning; visualStateInitialized = true; } private void UpdatePrompt(Lucky8MachineState state) { if ((Object)(object)trigger == (Object)null) { return; } float effectiveHoldDuration = Lucky8Manager.EffectiveHoldDuration; int effectiveSpinCost = Lucky8Manager.EffectiveSpinCost; int availableTokens = ProgressionApi.AvailableTokens; if (!promptInitialized || lastPromptSpinning != state.IsSpinning || lastPromptSoldMask != state.SoldMask || lastPromptSpins != state.SpinsRemaining || lastPromptCost != effectiveSpinCost || lastPromptAvailableTokens != availableTokens || !Mathf.Approximately(lastPromptHoldDuration, effectiveHoldDuration)) { promptInitialized = true; lastPromptSpinning = state.IsSpinning; lastPromptSoldMask = state.SoldMask; lastPromptSpins = state.SpinsRemaining; lastPromptCost = effectiveSpinCost; lastPromptAvailableTokens = availableTokens; lastPromptHoldDuration = effectiveHoldDuration; trigger.timeToHold = effectiveHoldDuration; trigger.interactable = !state.IsSpinning && state.SpinsRemaining > 0 && state.SoldMask != byte.MaxValue; if (state.IsSpinning) { trigger.disabledHoverTip = "[ SELECTOR SPINNING ]"; } else if (state.SpinsRemaining <= 0 || state.SoldMask == byte.MaxValue) { trigger.disabledHoverTip = "[ MACHINE DEPLETED ]"; } else if (availableTokens < effectiveSpinCost) { trigger.hoverTip = $"Need {effectiveSpinCost} tokens ({availableTokens} available)"; } else { trigger.hoverTip = $"Insert {effectiveSpinCost} tokens - {state.SpinsRemaining} spin(s) left : [{UpgradeInteractInput.DisplayLabel()}]"; } } } private static void ApplyScreen(Renderer renderer, MaterialPropertyBlock block, Color authoredEmission, Texture icon, Color accent, bool highlighted, bool sold, float emissionLevel) { //IL_003c: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0070: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)renderer == (Object)null) && block != null) { Color val = (Color)(sold ? new Color(0.1f, 0.018f, 0.012f) : (Color.white * (highlighted ? 1.15f : 0.78f))); float num = Mathf.Lerp(0.015f, 1f, emissionLevel); Color val2 = authoredEmission * num; if (sold) { val2 *= 0.13f; } if (highlighted) { val2 += accent * (sold ? 1.55f : 2.2f); } block.SetColor(BaseColorId, val); block.SetColor(ColorId, val); block.SetColor(EmissiveColorId, val2); block.SetColor(EmissionColorId, val2); block.SetTexture(BaseColorMapId, icon); block.SetTexture(MainTexId, icon); renderer.SetPropertyBlock(block); } } private static void ApplyFrame(Renderer renderer, MaterialPropertyBlock block, Color accent, bool highlighted, bool sold) { //IL_0023: 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_0028: 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_002c: 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_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0075: 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_008d: 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) if (!((Object)(object)renderer == (Object)null) && block != null) { Color val = (Color)(sold ? new Color(0.18f, 0.025f, 0.018f) : accent); if (highlighted) { val *= (sold ? 1.2f : 1.28f); } Color val2 = val * ((!highlighted) ? (sold ? 0.025f : 0.1f) : (sold ? 1.5f : 2.35f)); block.SetColor(BaseColorId, val); block.SetColor(ColorId, val); block.SetColor(EmissiveColorId, val2); block.SetColor(EmissionColorId, val2); renderer.SetPropertyBlock(block); } } private static void ApplyEmission(Renderer renderer, MaterialPropertyBlock block, bool enabled, Color color) { //IL_0026: 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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002e: 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_0046: 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_0066: 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) if (!((Object)(object)renderer == (Object)null) && block != null) { Color val = (Color)(enabled ? color : new Color(0.04f, 0.025f, 0.015f)); block.SetColor(BaseColorId, val); block.SetColor(ColorId, val); block.SetColor(EmissiveColorId, val * (enabled ? 2f : 0.1f)); block.SetColor(EmissionColorId, val * (enabled ? 2f : 0.1f)); renderer.SetPropertyBlock(block); } } private static Color ReadAuthoredEmission(Renderer renderer) { //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Material val = (((Object)(object)renderer != (Object)null) ? renderer.sharedMaterial : null); if ((Object)(object)val != (Object)null) { if (val.HasProperty(EmissiveColorId)) { Color color = val.GetColor(EmissiveColorId); if (((Color)(ref color)).maxColorComponent > 0f) { return color; } } if (val.HasProperty(EmissionColorId)) { Color color2 = val.GetColor(EmissionColorId); if (((Color)(ref color2)).maxColorComponent > 0f) { return color2; } } } return new Color(1f, 0.74f, 0.45f) * 1.1f; } private static Color CategoryColor(Lucky8RewardCategory category) { //IL_0029: 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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) return (Color)(category switch { Lucky8RewardCategory.Suit => new Color(0.12f, 0.7f, 0.8f), Lucky8RewardCategory.Cosmetic => new Color(0.75f, 0.24f, 0.85f), Lucky8RewardCategory.Ammo => new Color(0.92f, 0.76f, 0.18f), Lucky8RewardCategory.Emote => new Color(0.36f, 0.62f, 1f), _ => new Color(0.94f, 0.45f, 0.08f), }); } private static Color FrameColor(Lucky8RewardDefinition reward) { //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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: 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_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_0091: 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_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: 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) Color val = CategoryColor(reward?.Category ?? Lucky8RewardCategory.Weapon); if (reward != null && reward.Category == Lucky8RewardCategory.Emote && Lucky8RewardPresentation.TryGetColor(reward, out var color)) { val = color; } return (Color)((reward?.Rarity ?? Lucky8Rarity.Common) switch { Lucky8Rarity.Uncommon => Color.Lerp(val, new Color(0.32f, 0.92f, 0.42f), 0.18f) * 0.92f, Lucky8Rarity.Rare => Color.Lerp(val, new Color(0.18f, 0.58f, 1f), 0.28f) * 1.08f, Lucky8Rarity.Legendary => Color.Lerp(val, new Color(1f, 0.82f, 0.24f), 0.4f) * 1.22f, _ => val * 0.72f, }); } private TextMeshPro CreateLabel(Transform slot, string name, float size) { //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_0018: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(((Component)this).transform, true); val.transform.position = slot.position + ((Component)this).transform.forward * 0.035f - ((Component)this).transform.up * 0.061f; val.transform.rotation = Quaternion.LookRotation(-((Component)this).transform.forward, ((Component)this).transform.up); val.transform.localScale = Vector3.one * 0.12f; TextMeshPro obj = val.AddComponent(); ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).enableWordWrapping = true; ((TMP_Text)obj).rectTransform.sizeDelta = new Vector2(2.25f, 0.72f); return obj; } private static string ShortLabel(string value) { if (string.IsNullOrWhiteSpace(value)) { return "?"; } value = value.Trim().ToUpperInvariant(); if (value.Length > 16) { return value.Substring(0, 15) + "…"; } return value; } private static Transform FindDeep(Transform root, string name) { if ((Object)(object)root == (Object)null) { return null; } Transform[] componentsInChildren = ((Component)root).GetComponentsInChildren(true); foreach (Transform val in componentsInChildren) { if (string.Equals(((Object)val).name, name, StringComparison.OrdinalIgnoreCase)) { return val; } } return null; } private static void TrySetTag(GameObject target, string tag) { try { target.tag = tag; } catch { } } private void OnDestroy() { if (trigger?.onInteract != null) { ((UnityEvent)(object)trigger.onInteract).RemoveListener((UnityAction)OnInteract); } Lucky8Manager.UnregisterMachine(this); } } internal static class Lucky8ProceduralAudio { internal static AudioClip Hum { get; private set; } internal static AudioClip Tick { get; private set; } internal static AudioClip Win { get; private set; } internal static void Ensure() { if (!((Object)(object)Hum != (Object)null)) { Hum = Tone("Lucky8_Hum", 2f, 56f, 0.08f, decay: false); Tick = Tone("Lucky8_Tick", 0.055f, 920f, 0.5f, decay: true); Win = WinTone(); } } private static AudioClip Tone(string name, float duration, float frequency, float volume, bool decay) { int num = Mathf.CeilToInt(duration * 22050f); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 22050f; float num3 = (decay ? (1f - (float)i / (float)num) : 1f); array[i] = Mathf.Sin(num2 * frequency * MathF.PI * 2f) * volume * num3; } AudioClip obj = AudioClip.Create(name, num, 1, 22050, false); obj.SetData(array, 0); return obj; } private static AudioClip WinTone() { int num = Mathf.CeilToInt(17640f); float[] array = new float[num]; float[] array2 = new float[4] { 523.25f, 659.25f, 783.99f, 1046.5f }; for (int i = 0; i < num; i++) { float num2 = (float)i / 22050f; int num3 = Mathf.Min(array2.Length - 1, Mathf.FloorToInt(num2 / (0.8f / (float)array2.Length))); array[i] = Mathf.Sin(num2 * array2[num3] * MathF.PI * 2f) * 0.34f * (1f - num2 / 0.8f); } AudioClip obj = AudioClip.Create("Lucky8_Win", num, 1, 22050, false); obj.SetData(array, 0); return obj; } } internal static class Lucky8Manager { [CompilerGenerated] private static class <>O { public static HandleNamedMessageDelegate <0>__OnSpinRequestServer; public static HandleNamedMessageDelegate <1>__OnSnapshotRequestServer; public static HandleNamedMessageDelegate <2>__OnCapsuleConsumeServer; public static HandleNamedMessageDelegate <3>__OnAssignmentRequestServer; public static HandleNamedMessageDelegate <4>__OnSpinResultClient; public static HandleNamedMessageDelegate <5>__OnStateClient; public static HandleNamedMessageDelegate <6>__OnCapsulePayloadClient; public static HandleNamedMessageDelegate <7>__OnAssignmentClient; } private const string SpinRequestServer = "Y4NGZ.Lucky8.SpinRequest.Server"; private const string SpinResultClient = "Y4NGZ.Lucky8.SpinResult.Client"; private const string StateClient = "Y4NGZ.Lucky8.State.Client"; private const string SnapshotRequestServer = "Y4NGZ.Lucky8.SnapshotRequest.Server"; private const string CapsulePayloadClient = "Y4NGZ.Lucky8.CapsulePayload.Client"; private const string CapsuleConsumeServer = "Y4NGZ.Lucky8.CapsuleConsume.Server"; private const string AssignmentRequestServer = "Y4NGZ.Lucky8.AssignmentRequest.Server"; private const string AssignmentClient = "Y4NGZ.Lucky8.Assignment.Client"; private const int AssignmentHeaderBytes = 17; private const int AssignmentRouteBytes = 8; private static readonly HashSet AssignedRoutes = new HashSet(); private static readonly Dictionary AssignedLevelIds = new Dictionary(); private static readonly Dictionary States = new Dictionary(); private static readonly Dictionary Machines = new Dictionary(); private static readonly Dictionary Capsules = new Dictionary(); private static readonly Dictionary CapsulePayloads = new Dictionary(); private static readonly Dictionary PendingCapsulePayloads = new Dictionary(); private static readonly HashSet PendingTransactions = new HashSet(StringComparer.Ordinal); private static NetworkManager registeredNetwork; private static string assignmentSignature = string.Empty; private static string assignmentInputSignature = string.Empty; private static float nextAssignmentRefresh; private const float InvalidPoolValidationRetrySeconds = 30f; private static float _nextInvalidPoolValidationAt; private static string _validatedPoolSignature = string.Empty; private static bool _cachedPoolsValid; private static bool _poolValidityKnown; private static bool spawnAttempted; private static bool placementPending; private static bool poolWarningLogged; private static bool initialized; private static int visitEpoch; private static bool hasHostAssignments; private static bool hostFeatureEnabled; private static int hostSpinCost = 3; private static float hostHoldDuration = 0.75f; private static float hostPressDuration = 1f; internal static Lucky8Config Config { get; private set; } internal static bool IsInitialized => initialized; internal static int EffectiveSpinCost { get { if (!UseHostConfiguration) { return Config.SpinCost; } return hostSpinCost; } } internal static float EffectiveHoldDuration { get { if (!UseHostConfiguration) { return Config.HoldDuration; } return hostHoldDuration; } } internal static float EffectivePressDuration { get { if (!UseHostConfiguration) { return Config.PressDuration; } return hostPressDuration; } } private static bool UseHostConfiguration { get { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsListening && singleton.IsClient && !singleton.IsServer) { return hasHostAssignments; } return false; } } internal static void Initialize(Y4NGZConfigScope config) { if (initialized) { return; } Config = new Lucky8Config(config); if (!Config.FeatureEnabled) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogMessage((object)"[LUCKY-8] Disabled; skipping runtime assets, Company bridge, animation, and network initialization."); } } else { hostSpinCost = Config.SpinCost; hostHoldDuration = Config.HoldDuration; hostPressDuration = Config.PressDuration; Lucky8RuntimeAssets.Initialize(); Lucky8CompanyBridge.Initialize(); Lucky8ButtonPressAnimation.Initialize(); initialized = true; } } internal static void Shutdown() { if (initialized) { Lucky8CompanyBridge.Shutdown(); UnregisterNetworkHandlers(); string[] array = PendingTransactions.ToArray(); for (int i = 0; i < array.Length; i++) { ProgressionApi.CancelTokenSpend(array[i]); } PendingTransactions.Clear(); States.Clear(); Machines.Clear(); Capsules.Clear(); CapsulePayloads.Clear(); PendingCapsulePayloads.Clear(); AssignedRoutes.Clear(); AssignedLevelIds.Clear(); assignmentSignature = string.Empty; assignmentInputSignature = string.Empty; nextAssignmentRefresh = 0f; _validatedPoolSignature = string.Empty; _nextInvalidPoolValidationAt = 0f; _cachedPoolsValid = false; _poolValidityKnown = false; hasHostAssignments = false; hostFeatureEnabled = false; Lucky8RuntimeAssets.Shutdown(); initialized = false; } } internal static bool IsRouteAssigned(int routeIndex) { RefreshAssignments(); NetworkManager singleton = NetworkManager.Singleton; bool featureEnabled; if (!((Object)(object)singleton != (Object)null) || !singleton.IsListening || !singleton.IsClient || singleton.IsServer) { Lucky8Config config = Config; if (config != null) { featureEnabled = config.FeatureEnabled; goto IL_004e; } } else if (hasHostAssignments) { featureEnabled = hostFeatureEnabled; goto IL_004e; } goto IL_005c; IL_005c: return false; IL_004e: if (featureEnabled) { return AssignedRoutes.Contains(routeIndex); } goto IL_005c; } internal static void UpdateRuntime() { if (!initialized) { return; } RegisterNetworkHandlers(); RefreshAssignments(); Lucky8RuntimeAssets.TryRegisterCapsulePrefab(); StartOfRound instance = StartOfRound.Instance; RoundManager instance2 = RoundManager.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null) { return; } if (instance.inShipPhase || instance.shipIsLeaving) { if (spawnAttempted || placementPending || States.Count > 0) { ResetVisit(); } } else { if (!((NetworkBehaviour)instance2).IsServer) { return; } Lucky8Config config = Config; if (config == null || !config.FeatureEnabled || spawnAttempted || placementPending || !instance2.bakedNavMesh || !instance2.dungeonFinishedGeneratingForAllPlayers) { return; } RuntimeDungeon dungeonGenerator = instance2.dungeonGenerator; object obj; if (dungeonGenerator == null) { obj = null; } else { DungeonGenerator generator = dungeonGenerator.Generator; if (generator == null) { obj = null; } else { Dungeon currentDungeon = generator.CurrentDungeon; obj = ((currentDungeon != null) ? currentDungeon.AllTiles : null); } } if (obj == null) { return; } if (!IsCurrentMoonAssigned()) { spawnAttempted = true; return; } if (!Lucky8RewardCatalog.HasMinimumPools(out var reason)) { spawnAttempted = true; if (!poolWarningLogged) { poolWarningLogged = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Assigned machine suppressed because the configured pools are incomplete: " + reason)); } } return; } int requestEpoch = visitEpoch; placementPending = Lucky8CompanyBridge.RequestPlacement(delegate(bool ok, Vector3 position, Quaternion rotation, Vector3 interactionPoint, string tier) { //IL_000f: 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_0011: Unknown result type (might be due to invalid IL or missing references) if (requestEpoch == visitEpoch) { OnPlacementReady(ok, position, rotation, interactionPoint, tier); } }); if (!placementPending) { spawnAttempted = true; ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)"[LUCKY-8] Facility placement API did not accept the machine request."); } } } } internal static void RegisterMachine(Lucky8MachineBehaviour machine) { NetworkObject val = ((machine != null) ? ((Component)machine).GetComponent() : null); if (!((Object)(object)val == (Object)null) && val.IsSpawned) { Machines[val.NetworkObjectId] = machine; } } internal static void UnregisterMachine(Lucky8MachineBehaviour machine) { NetworkObject val = ((machine != null) ? ((Component)machine).GetComponent() : null); if ((Object)(object)val != (Object)null) { Machines.Remove(val.NetworkObjectId); } } internal static void RegisterCapsule(Lucky8ClaimCapsule capsule) { NetworkObject val = ((capsule != null) ? ((Component)capsule).GetComponent() : null); if (!((Object)(object)val == (Object)null) && val.IsSpawned) { Capsules[val.NetworkObjectId] = capsule; if (PendingCapsulePayloads.TryGetValue(val.NetworkObjectId, out var value)) { capsule.SetReward(value); PendingCapsulePayloads.Remove(val.NetworkObjectId); } } } internal static void UnregisterCapsule(Lucky8ClaimCapsule capsule) { NetworkObject val = ((capsule != null) ? ((Component)capsule).GetComponent() : null); if ((Object)(object)val != (Object)null) { Capsules.Remove(val.NetworkObjectId); } } internal static bool TryGetState(ulong networkObjectId, out Lucky8MachineState state) { return States.TryGetValue(networkObjectId, out state); } internal unsafe static void TryBeginLocalSpin(ulong machineId, PlayerControllerB player) { //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_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_0107: 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_011a: 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_0135: Unknown result type (might be due to invalid IL or missing references) if (!States.TryGetValue(machineId, out var value) || value.IsSpinning || value.SpinsRemaining <= 0) { return; } int effectiveSpinCost = EffectiveSpinCost; ulong actualClientId = player.actualClientId; string text = $"lucky8:{actualClientId}:{BuildDaySignature()}:{Guid.NewGuid():N}"; if (!ProgressionApi.TryReserveTokenSpend(text, effectiveSpinCost)) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LUCKY-8", $"This spin needs {effectiveSpinCost} tokens. You have {ProgressionApi.AvailableTokens} available.", true, false, "LC_Tip1"); } return; } PendingTransactions.Add(text); Lucky8ButtonPressAnimation.Play(player); NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { RejectLocalTransaction(text, "network-unavailable"); return; } if (singleton.IsServer) { HandleSpinRequest(actualClientId, machineId, text, effectiveSpinCost); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref machineId, default(ForPrimitives)); FixedString128Bytes val2 = new FixedString128Bytes(text); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref effectiveSpinCost, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.SpinRequest.Server", 0uL, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } internal unsafe static void RequestConsumeCapsule(ulong capsuleId) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsClient) { return; } if (singleton.IsServer) { ConsumeCapsule(capsuleId, singleton.LocalClientId); return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(8, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref capsuleId, default(ForPrimitives)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.CapsuleConsume.Server", 0uL, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } internal static void ResetVisit() { visitEpoch++; spawnAttempted = false; placementPending = false; poolWarningLogged = false; States.Clear(); Machines.Clear(); Capsules.Clear(); CapsulePayloads.Clear(); PendingCapsulePayloads.Clear(); } private static void OnPlacementReady(bool ok, Vector3 position, Quaternion rotation, Vector3 interactionPoint, string tier) { //IL_0124: 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) placementPending = false; spawnAttempted = true; NetworkManager singleton = NetworkManager.Singleton; StartOfRound instance = StartOfRound.Instance; if (!ok || (Object)(object)singleton == (Object)null || !singleton.IsServer || (Object)(object)Lucky8RuntimeAssets.MachinePrefab == (Object)null || (Object)(object)instance == (Object)null || instance.inShipPhase || instance.shipIsLeaving || !IsCurrentMoonAssigned()) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Placement failed: " + tier)); } return; } IReadOnlyList weapons = Lucky8RewardCatalog.BuildWeapons(); IReadOnlyList suits = Lucky8RewardCatalog.BuildSuits(); IReadOnlyList cosmetics = Lucky8RewardCatalog.BuildCosmetics(); IReadOnlyList ammo; try { ammo = Lucky8RewardCatalog.BuildAmmo(); } catch (Exception ex) { ammo = Array.Empty(); ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[LUCKY-8] Ammo bonus pool failed safely: " + ex.Message)); } } IReadOnlyList emotes = Lucky8RewardCatalog.BuildEmotes(); int seed = StableHash(BuildDaySignature() + ":lineup:" + StartOfRound.Instance.currentLevel.levelID); if (!Lucky8LineupGenerator.TryCreate(weapons, suits, cosmetics, ammo, emotes, seed, out var lineup, out var reason)) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[LUCKY-8] Lineup generation failed: " + reason)); } return; } GameObject val = Object.Instantiate(Lucky8RuntimeAssets.MachinePrefab, position, rotation); val.SetActive(true); NetworkObject component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return; } component.Spawn(false); Lucky8MachineState lucky8MachineState = new Lucky8MachineState { NetworkObjectId = component.NetworkObjectId, SpinsRemaining = Config.SpinLimit, SpinDuration = Config.WheelDuration }; for (int i = 0; i < lineup.Length; i++) { lucky8MachineState.Rewards[i] = lineup[i]; } States[lucky8MachineState.NetworkObjectId] = lucky8MachineState; BroadcastState(lucky8MachineState); LogDebug(string.Format("spawned id={0} tier={1} lineup={2}", lucky8MachineState.NetworkObjectId, tier, string.Join(",", lineup.Select((Lucky8RewardDefinition reward) => reward.StableId)))); } private static void HandleSpinRequest(ulong senderClientId, ulong machineId, string transaction, int cost) { //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsServer) { return; } if (!States.TryGetValue(machineId, out var value)) { SendSpinResult(senderClientId, transaction, accepted: false, "machine-not-found"); return; } if (cost != Config.SpinCost || value.IsSpinning || value.SpinsRemaining <= 0 || value.SoldMask == byte.MaxValue) { SendSpinResult(senderClientId, transaction, accepted: false, value.IsSpinning ? "machine-busy" : "machine-depleted"); return; } int seed = StableHash(transaction + ":winner:" + value.SpinsRemaining + ":" + value.SoldMask); int num = Lucky8LineupGenerator.PickWinner(value, seed); if (num < 0) { SendSpinResult(senderClientId, transaction, accepted: false, "no-prizes-left"); return; } value.IsSpinning = true; value.WinnerIndex = num; Lucky8MachineState lucky8MachineState = value; NetworkTime serverTime = singleton.ServerTime; lucky8MachineState.SpinStartedAt = ((NetworkTime)(ref serverTime)).Time + 0.15; value.SpinDuration = Config.WheelDuration; value.SpinsRemaining--; SendSpinResult(senderClientId, transaction, accepted: true, "accepted"); BroadcastState(value); Y4NGZPersistentRunner.Run(FinishSpin(value.NetworkObjectId, num)); LogDebug($"spin accepted machine={machineId} client={senderClientId} winner={num} tx={transaction}"); } private static IEnumerator FinishSpin(ulong machineId, int winner) { yield return (object)new WaitForSecondsRealtime(Config.WheelDuration + 0.18f); if (States.TryGetValue(machineId, out var value) && value.IsSpinning && value.WinnerIndex == winner) { value.IsSpinning = false; value.SoldMask = (byte)(value.SoldMask | (1 << winner)); BroadcastState(value); Payout(value, winner); } } private static void Payout(Lucky8MachineState state, int winner) { //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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0121: 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) Lucky8RewardDefinition reward = state.Rewards[winner]; if (reward == null || !Machines.TryGetValue(state.NetworkObjectId, out var value)) { return; } Vector3 prizeChutePosition = value.PrizeChutePosition; if (reward.Category == Lucky8RewardCategory.Weapon) { GameObject weaponPrizePrefab = ArmoryBridge.GetWeaponPrizePrefab(reward.StableId); if ((Object)(object)weaponPrizePrefab == (Object)null) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Weapon prize '" + reward.StableId + "' has no prefab; it was not delivered.")); } } else { SpawnNetworkPrize(weaponPrizePrefab, prizeChutePosition, delegate(GameObject instance) { ArmoryBridge.InitializeWeaponPrize(instance, reward.StableId); }); } } else if (reward.Category == Lucky8RewardCategory.Ammo) { GameObject ammoPrizePrefab = ArmoryBridge.GetAmmoPrizePrefab(reward.StableId); if ((Object)(object)ammoPrizePrefab == (Object)null) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[LUCKY-8] Ammo prize '" + reward.StableId + "' has no prefab; it was not delivered.")); } } else { SpawnNetworkPrize(ammoPrizePrefab, prizeChutePosition); } } else if (!Lucky8RuntimeAssets.TryRegisterCapsulePrefab()) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogWarning((object)"[LUCKY-8] Claim capsule was not registered; payout could not spawn."); } } else { NetworkObject val = SpawnNetworkPrize(Lucky8RuntimeAssets.CapsulePrefab, prizeChutePosition); if ((Object)(object)val != (Object)null) { CapsulePayloads[val.NetworkObjectId] = reward; PendingCapsulePayloads[val.NetworkObjectId] = reward; ((Component)val).GetComponent()?.SetReward(reward); BroadcastCapsulePayload(val.NetworkObjectId, reward); } } } private static NetworkObject SpawnNetworkPrize(GameObject prefab, Vector3 position, Action configure = null) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)prefab == (Object)null)) { NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { GameObject val = Object.Instantiate(prefab, position, Quaternion.identity); val.SetActive(true); configure?.Invoke(val); NetworkObject component = val.GetComponent(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return null; } component.Spawn(false); return component; } } return null; } private static void RefreshAssignments() { if (Config == null || Time.unscaledTime < nextAssignmentRefresh) { return; } nextAssignmentRefresh = Time.unscaledTime + 1f; NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton != (Object)null && singleton.IsListening && singleton.IsClient && !singleton.IsServer) { if (!hasHostAssignments) { AssignedRoutes.Clear(); AssignedLevelIds.Clear(); } return; } if (!Config.FeatureEnabled) { AssignedRoutes.Clear(); AssignedLevelIds.Clear(); assignmentInputSignature = string.Empty; if (singleton != null && singleton.IsServer) { BroadcastAssignments(); } return; } string text = BuildDaySignature() + ":" + Config.AssignmentChance.ToString("0.000") + ":" + Config.SpinCost + ":" + Config.HoldDuration.ToString("0.000") + ":" + Config.PressDuration.ToString("0.000") + ":p" + StableHash(Config.WeaponPool.Value + "|" + Config.SuitPool.Value + "|" + Config.CosmeticPool.Value + "|" + Config.AmmoPool.Value) + ":l" + (StartOfRound.Instance?.levels?.Length).GetValueOrDefault(); bool flag = text != assignmentInputSignature; bool flag2 = !string.Equals(BuildPoolValidationSignature(), _validatedPoolSignature, StringComparison.Ordinal); bool flag3 = _poolValidityKnown && !_cachedPoolsValid && Time.unscaledTime >= _nextInvalidPoolValidationAt; if (!_poolValidityKnown || flag2 || flag3) { _cachedPoolsValid = Lucky8RewardCatalog.HasMinimumPools(out var _); _poolValidityKnown = true; _validatedPoolSignature = BuildPoolValidationSignature(); _nextInvalidPoolValidationAt = (_cachedPoolsValid ? float.PositiveInfinity : (Time.unscaledTime + 30f)); } if (!_cachedPoolsValid) { AssignedRoutes.Clear(); AssignedLevelIds.Clear(); assignmentInputSignature = string.Empty; if (singleton != null && singleton.IsServer) { BroadcastAssignments(); } } else { if (!flag) { return; } IReadOnlyList routes = Lucky8CompanyBridge.GetRoutes(); if (routes.Count == 0) { return; } assignmentInputSignature = text; string text2 = text + ":" + routes.Count; if (text2 == assignmentSignature) { return; } assignmentSignature = text2; AssignedRoutes.Clear(); AssignedLevelIds.Clear(); foreach (IGrouping item in routes.Where((Lucky8RouteInfo route) => route.HasFacility && !route.IsCompanyMoon).GroupBy((Lucky8RouteInfo route) => route.ConstellationKey ?? string.Empty, StringComparer.OrdinalIgnoreCase)) { Lucky8RouteInfo[] array = item.OrderBy((Lucky8RouteInfo route) => route.RouteIndex).ToArray(); StableRandom stableRandom = new StableRandom(StableHash(text2 + ":" + item.Key)); if (!(stableRandom.NextDouble() >= (double)Config.AssignmentChance)) { Lucky8RouteInfo lucky8RouteInfo = array[stableRandom.Next(array.Length)]; AssignedRoutes.Add(lucky8RouteInfo.RouteIndex); AssignedLevelIds[lucky8RouteInfo.RouteIndex] = lucky8RouteInfo.LevelId; } } LogDebug("daily assignments=" + string.Join(",", AssignedRoutes.OrderBy((int value) => value))); if (singleton != null && singleton.IsServer) { BroadcastAssignments(); } } } private static string BuildPoolValidationSignature() { return StableHash(Config.WeaponPool.Value + "|" + Config.SuitPool.Value + "|" + Config.CosmeticPool.Value) + ":" + Lucky8RewardCatalog.MinimumPoolSourceFingerprint(); } private static bool IsCurrentMoonAssigned() { int levelId = StartOfRound.Instance?.currentLevel?.levelID ?? int.MinValue; return AssignedLevelIds.Any((KeyValuePair pair) => pair.Value == levelId && AssignedRoutes.Contains(pair.Key)); } private static string BuildDaySignature() { SaveKey.TryGetCurrentOrSlot(out var key); TimeOfDay instance = TimeOfDay.Instance; int num = ReadInt(instance, "timesFulfilledQuota"); int num2 = ReadInt(instance, "daysUntilDeadline"); int num3 = ReadInt(instance, "deadlineDaysAmount"); return (key ?? "unknown") + ":q" + num + ":d" + num2 + ":m" + num3; } private static int ReadInt(object instance, string name) { if (instance == null) { return 0; } Type type = instance.GetType(); object value = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance) ?? type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(instance); try { return Convert.ToInt32(value); } catch { return 0; } } private static int StableHash(string value) { uint num = 2166136261u; string text = value ?? string.Empty; foreach (char c in text) { num ^= c; num *= 16777619; } return (int)num; } private unsafe static void RegisterNetworkHandlers() { //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_013a: Expected O, but got Unknown //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown //IL_015a: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Expected O, but got Unknown //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Expected O, but got Unknown //IL_0185: Unknown result type (might be due to invalid IL or missing references) //IL_018a: Unknown result type (might be due to invalid IL or missing references) //IL_0190: Expected O, but got Unknown //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Expected O, but got Unknown //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01df: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null || !singleton.IsListening || singleton.CustomMessagingManager == null || (Object)(object)registeredNetwork == (Object)(object)singleton) { return; } UnregisterNetworkHandlers(); try { if (singleton.IsServer) { CustomMessagingManager customMessagingManager = singleton.CustomMessagingManager; object obj = <>O.<0>__OnSpinRequestServer; if (obj == null) { HandleNamedMessageDelegate val = OnSpinRequestServer; <>O.<0>__OnSpinRequestServer = val; obj = (object)val; } customMessagingManager.RegisterNamedMessageHandler("Y4NGZ.Lucky8.SpinRequest.Server", (HandleNamedMessageDelegate)obj); CustomMessagingManager customMessagingManager2 = singleton.CustomMessagingManager; object obj2 = <>O.<1>__OnSnapshotRequestServer; if (obj2 == null) { HandleNamedMessageDelegate val2 = OnSnapshotRequestServer; <>O.<1>__OnSnapshotRequestServer = val2; obj2 = (object)val2; } customMessagingManager2.RegisterNamedMessageHandler("Y4NGZ.Lucky8.SnapshotRequest.Server", (HandleNamedMessageDelegate)obj2); CustomMessagingManager customMessagingManager3 = singleton.CustomMessagingManager; object obj3 = <>O.<2>__OnCapsuleConsumeServer; if (obj3 == null) { HandleNamedMessageDelegate val3 = OnCapsuleConsumeServer; <>O.<2>__OnCapsuleConsumeServer = val3; obj3 = (object)val3; } customMessagingManager3.RegisterNamedMessageHandler("Y4NGZ.Lucky8.CapsuleConsume.Server", (HandleNamedMessageDelegate)obj3); CustomMessagingManager customMessagingManager4 = singleton.CustomMessagingManager; object obj4 = <>O.<3>__OnAssignmentRequestServer; if (obj4 == null) { HandleNamedMessageDelegate val4 = OnAssignmentRequestServer; <>O.<3>__OnAssignmentRequestServer = val4; obj4 = (object)val4; } customMessagingManager4.RegisterNamedMessageHandler("Y4NGZ.Lucky8.AssignmentRequest.Server", (HandleNamedMessageDelegate)obj4); } CustomMessagingManager customMessagingManager5 = singleton.CustomMessagingManager; object obj5 = <>O.<4>__OnSpinResultClient; if (obj5 == null) { HandleNamedMessageDelegate val5 = OnSpinResultClient; <>O.<4>__OnSpinResultClient = val5; obj5 = (object)val5; } customMessagingManager5.RegisterNamedMessageHandler("Y4NGZ.Lucky8.SpinResult.Client", (HandleNamedMessageDelegate)obj5); CustomMessagingManager customMessagingManager6 = singleton.CustomMessagingManager; object obj6 = <>O.<5>__OnStateClient; if (obj6 == null) { HandleNamedMessageDelegate val6 = OnStateClient; <>O.<5>__OnStateClient = val6; obj6 = (object)val6; } customMessagingManager6.RegisterNamedMessageHandler("Y4NGZ.Lucky8.State.Client", (HandleNamedMessageDelegate)obj6); CustomMessagingManager customMessagingManager7 = singleton.CustomMessagingManager; object obj7 = <>O.<6>__OnCapsulePayloadClient; if (obj7 == null) { HandleNamedMessageDelegate val7 = OnCapsulePayloadClient; <>O.<6>__OnCapsulePayloadClient = val7; obj7 = (object)val7; } customMessagingManager7.RegisterNamedMessageHandler("Y4NGZ.Lucky8.CapsulePayload.Client", (HandleNamedMessageDelegate)obj7); CustomMessagingManager customMessagingManager8 = singleton.CustomMessagingManager; object obj8 = <>O.<7>__OnAssignmentClient; if (obj8 == null) { HandleNamedMessageDelegate val8 = OnAssignmentClient; <>O.<7>__OnAssignmentClient = val8; obj8 = (object)val8; } customMessagingManager8.RegisterNamedMessageHandler("Y4NGZ.Lucky8.Assignment.Client", (HandleNamedMessageDelegate)obj8); registeredNetwork = singleton; if (!singleton.IsClient || singleton.IsServer) { return; } FastBufferWriter val9 = default(FastBufferWriter); ((FastBufferWriter)(ref val9))..ctor(0, (Allocator)2, -1); try { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.SnapshotRequest.Server", 0uL, val9, (NetworkDelivery)4); FastBufferWriter val10 = new FastBufferWriter(0, (Allocator)2, -1); try { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.AssignmentRequest.Server", 0uL, val10, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val10))/*cast due to .constrained prefix*/).Dispose(); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val9))/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception ex) { registeredNetwork = null; ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Network handler registration failed: " + ex.Message)); } } } private static void UnregisterNetworkHandlers() { NetworkManager obj = registeredNetwork; if (((obj != null) ? obj.CustomMessagingManager : null) == null) { registeredNetwork = null; return; } try { if (registeredNetwork.IsServer) { registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.SpinRequest.Server"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.SnapshotRequest.Server"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.CapsuleConsume.Server"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.AssignmentRequest.Server"); } registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.SpinResult.Client"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.State.Client"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.CapsulePayload.Client"); registeredNetwork.CustomMessagingManager.UnregisterNamedMessageHandler("Y4NGZ.Lucky8.Assignment.Client"); } catch { } registeredNetwork = null; hasHostAssignments = false; hostFeatureEnabled = false; } private unsafe static void BroadcastAssignments(ulong? onlyClient = null) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0072: 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_009b: 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_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_012f: 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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: 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) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || !singleton.IsServer) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(17 + AssignedRoutes.Count * 8, (Allocator)2, -1); try { bool flag = Config?.FeatureEnabled ?? false; ((FastBufferWriter)(ref val)).WriteValueSafe(ref flag, default(ForPrimitives)); int num = Config?.SpinCost ?? 3; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); float num2 = Config?.HoldDuration ?? 0.75f; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num2, default(ForPrimitives)); num2 = Config?.PressDuration ?? 1f; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num2, default(ForPrimitives)); num = AssignedRoutes.Count; ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); foreach (int item in AssignedRoutes.OrderBy((int result) => result)) { int current = item; ((FastBufferWriter)(ref val)).WriteValueSafe(ref current, default(ForPrimitives)); num = (AssignedLevelIds.TryGetValue(current, out var value) ? value : (-1)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref num, default(ForPrimitives)); } if (onlyClient.HasValue) { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.Assignment.Client", onlyClient.Value, val, (NetworkDelivery)4); } else { singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ.Lucky8.Assignment.Client", val, (NetworkDelivery)4); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void OnAssignmentRequestServer(ulong sender, FastBufferReader reader) { RefreshAssignments(); BroadcastAssignments(sender); } private static void OnAssignmentClient(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_003f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) try { bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref flag, default(ForPrimitives)); int num = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num, default(ForPrimitives)); float num2 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num2, default(ForPrimitives)); float num3 = default(float); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num3, default(ForPrimitives)); int num4 = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref num4, default(ForPrimitives)); num4 = Mathf.Clamp(num4, 0, 128); AssignedRoutes.Clear(); AssignedLevelIds.Clear(); int num5 = default(int); int value = default(int); for (int i = 0; i < num4; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref num5, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref value, default(ForPrimitives)); AssignedRoutes.Add(num5); AssignedLevelIds[num5] = value; } hostFeatureEnabled = flag; hostSpinCost = Mathf.Clamp(num, 1, 99); hostHoldDuration = Mathf.Clamp(num2, 0.1f, 3f); hostPressDuration = Mathf.Clamp(num3, 0.2f, 3f); hasHostAssignments = true; LogDebug("host assignments=" + string.Join(",", AssignedRoutes.OrderBy((int result) => result))); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Malformed assignment snapshot: " + ex.Message)); } } } private unsafe static void OnSpinRequestServer(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0018: 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_002b: 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) try { ulong machineId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref machineId, default(ForPrimitives)); FixedString128Bytes val = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); int cost = default(int); ((FastBufferReader)(ref reader)).ReadValueSafe(ref cost, default(ForPrimitives)); HandleSpinRequest(sender, machineId, ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString(), cost); } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Malformed spin request: " + ex.Message)); } } } private unsafe static void OnSpinResultClient(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_00a3: 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) try { FixedString128Bytes val = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); bool flag = default(bool); ((FastBufferReader)(ref reader)).ReadValueSafe(ref flag, default(ForPrimitives)); FixedString128Bytes val2 = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val2, default(ForFixedStrings)); string text = ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString(); if (!PendingTransactions.Remove(text)) { return; } if (flag) { if (!ProgressionApi.CommitTokenSpend(text)) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LUCKY-8", "The accepted token transaction could not be committed.", true, false, "LC_Tip1"); } } } else { ProgressionApi.CancelTokenSpend(text); HUDManager instance2 = HUDManager.Instance; if (instance2 != null) { FixedString128Bytes val3 = val2; instance2.DisplayTip("LUCKY-8", "Spin rejected: " + ((object)(*(FixedString128Bytes*)(&val3))/*cast due to .constrained prefix*/).ToString(), true, false, "LC_Tip1"); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Malformed spin result: " + ex.Message)); } } } private unsafe static void SendSpinResult(ulong clientId, string transaction, bool accepted, string reason) { //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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0097: 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) NetworkManager singleton = NetworkManager.Singleton; if ((Object)(object)singleton == (Object)null) { return; } if (singleton.IsHost && clientId == singleton.LocalClientId) { if (PendingTransactions.Remove(transaction)) { if (accepted) { ProgressionApi.CommitTokenSpend(transaction); } else { ProgressionApi.CancelTokenSpend(transaction); } } return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1); try { FixedString128Bytes val2 = new FixedString128Bytes(transaction); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); ((FastBufferWriter)(ref val)).WriteValueSafe(ref accepted, default(ForPrimitives)); val2 = new FixedString128Bytes(reason ?? string.Empty); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.SpinResult.Client", clientId, val, (NetworkDelivery)4); } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void RejectLocalTransaction(string transaction, string reason) { PendingTransactions.Remove(transaction); ProgressionApi.CancelTokenSpend(transaction); HUDManager instance = HUDManager.Instance; if (instance != null) { instance.DisplayTip("LUCKY-8", "Spin rejected: " + reason, true, false, "LC_Tip1"); } } private unsafe static void BroadcastState(Lucky8MachineState state, ulong? onlyClient = null) { //IL_0026: 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_0048: Unknown result type (might be due to invalid IL or missing references) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || state == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(4096, (Allocator)2, -1); try { WriteState(val, state); if (onlyClient.HasValue) { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.State.Client", onlyClient.Value, val, (NetworkDelivery)4); } else { singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ.Lucky8.State.Client", val, (NetworkDelivery)4); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private static void WriteState(FastBufferWriter writer, Lucky8MachineState state) { //IL_000a: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0036: 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_004c: 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_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00df: 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_00fb: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_012a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.NetworkObjectId, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.SoldMask, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.SpinsRemaining, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.IsSpinning, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.WinnerIndex, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.SpinStartedAt, default(ForPrimitives)); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref state.SpinDuration, default(ForPrimitives)); for (int i = 0; i < 8; i++) { Lucky8RewardDefinition lucky8RewardDefinition = state.Rewards[i] ?? new Lucky8RewardDefinition(); byte category = (byte)lucky8RewardDefinition.Category; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref category, default(ForPrimitives)); category = (byte)lucky8RewardDefinition.Rarity; ((FastBufferWriter)(ref writer)).WriteValueSafe(ref category, default(ForPrimitives)); FixedString128Bytes val = new FixedString128Bytes(lucky8RewardDefinition.StableId ?? string.Empty); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref val, default(ForFixedStrings)); val = new FixedString128Bytes(lucky8RewardDefinition.DisplayName ?? string.Empty); ((FastBufferWriter)(ref writer)).WriteValueSafe(ref val, default(ForFixedStrings)); } } private unsafe static Lucky8MachineState ReadState(FastBufferReader reader) { //IL_0010: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: 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_0094: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: 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_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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) Lucky8MachineState lucky8MachineState = new Lucky8MachineState(); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.NetworkObjectId, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.SoldMask, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.SpinsRemaining, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.IsSpinning, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.WinnerIndex, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.SpinStartedAt, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref lucky8MachineState.SpinDuration, default(ForPrimitives)); byte category = default(byte); byte rarity = default(byte); FixedString128Bytes val = default(FixedString128Bytes); FixedString128Bytes val2 = default(FixedString128Bytes); for (int i = 0; i < 8; i++) { ((FastBufferReader)(ref reader)).ReadValueSafe(ref category, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref rarity, default(ForPrimitives)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val2, default(ForFixedStrings)); lucky8MachineState.Rewards[i] = Lucky8RewardCatalog.Resolve((Lucky8RewardCategory)category, ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString(), ((object)(*(FixedString128Bytes*)(&val2))/*cast due to .constrained prefix*/).ToString(), (Lucky8Rarity)rarity); } return lucky8MachineState; } private static void OnStateClient(ulong sender, FastBufferReader reader) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) try { Lucky8MachineState lucky8MachineState = ReadState(reader); States[lucky8MachineState.NetworkObjectId] = lucky8MachineState; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Malformed machine state: " + ex.Message)); } } } private static void OnSnapshotRequestServer(ulong sender, FastBufferReader reader) { foreach (Lucky8MachineState value in States.Values) { BroadcastState(value, sender); } foreach (KeyValuePair capsulePayload in CapsulePayloads) { BroadcastCapsulePayload(capsulePayload.Key, capsulePayload.Value, sender); } } private unsafe static void BroadcastCapsulePayload(ulong capsuleId, Lucky8RewardDefinition reward, ulong? onlyClient = null) { //IL_002c: 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_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: 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_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_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) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: 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) NetworkManager singleton = NetworkManager.Singleton; if (((singleton != null) ? singleton.CustomMessagingManager : null) == null || reward == null) { return; } FastBufferWriter val = default(FastBufferWriter); ((FastBufferWriter)(ref val))..ctor(512, (Allocator)2, -1); try { ((FastBufferWriter)(ref val)).WriteValueSafe(ref capsuleId, default(ForPrimitives)); byte category = (byte)reward.Category; ((FastBufferWriter)(ref val)).WriteValueSafe(ref category, default(ForPrimitives)); category = (byte)reward.Rarity; ((FastBufferWriter)(ref val)).WriteValueSafe(ref category, default(ForPrimitives)); FixedString128Bytes val2 = new FixedString128Bytes(reward.StableId ?? string.Empty); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); val2 = new FixedString128Bytes(reward.DisplayName ?? string.Empty); ((FastBufferWriter)(ref val)).WriteValueSafe(ref val2, default(ForFixedStrings)); if (onlyClient.HasValue) { singleton.CustomMessagingManager.SendNamedMessage("Y4NGZ.Lucky8.CapsulePayload.Client", onlyClient.Value, val, (NetworkDelivery)4); } else { singleton.CustomMessagingManager.SendNamedMessageToAll("Y4NGZ.Lucky8.CapsulePayload.Client", val, (NetworkDelivery)4); } } finally { ((IDisposable)(*(FastBufferWriter*)(&val))/*cast due to .constrained prefix*/).Dispose(); } } private unsafe static void OnCapsulePayloadClient(ulong sender, FastBufferReader reader) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0019: 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_002c: 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_003f: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) try { ulong key = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref key, default(ForPrimitives)); byte category = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref category, default(ForPrimitives)); byte rarity = default(byte); ((FastBufferReader)(ref reader)).ReadValueSafe(ref rarity, default(ForPrimitives)); FixedString128Bytes val = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val, default(ForFixedStrings)); FixedString128Bytes val2 = default(FixedString128Bytes); ((FastBufferReader)(ref reader)).ReadValueSafe(ref val2, default(ForFixedStrings)); Lucky8RewardDefinition lucky8RewardDefinition = Lucky8RewardCatalog.Resolve((Lucky8RewardCategory)category, ((object)(*(FixedString128Bytes*)(&val))/*cast due to .constrained prefix*/).ToString(), ((object)(*(FixedString128Bytes*)(&val2))/*cast due to .constrained prefix*/).ToString(), (Lucky8Rarity)rarity); NetworkManager singleton = NetworkManager.Singleton; if (singleton != null && singleton.IsServer) { CapsulePayloads[key] = lucky8RewardDefinition; } PendingCapsulePayloads[key] = lucky8RewardDefinition; if (Capsules.TryGetValue(key, out var value)) { value.SetReward(lucky8RewardDefinition); PendingCapsulePayloads.Remove(key); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Malformed capsule payload: " + ex.Message)); } } } private static void OnCapsuleConsumeServer(ulong sender, FastBufferReader reader) { //IL_0006: 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) try { ulong capsuleId = default(ulong); ((FastBufferReader)(ref reader)).ReadValueSafe(ref capsuleId, default(ForPrimitives)); ConsumeCapsule(capsuleId, sender); } catch { } } private static void ConsumeCapsule(ulong capsuleId, ulong requesterClientId) { NetworkManager singleton = NetworkManager.Singleton; if (singleton == null || !singleton.IsServer || !CapsulePayloads.ContainsKey(capsuleId)) { return; } if (singleton.SpawnManager.SpawnedObjects.TryGetValue(capsuleId, out var value)) { if ((Object)(object)((Component)value).GetComponent() == (Object)null) { return; } GrabbableObject component = ((Component)value).GetComponent(); if ((Object)(object)component?.playerHeldBy == (Object)null || component.playerHeldBy.actualClientId != requesterClientId) { return; } value.Despawn(true); } CapsulePayloads.Remove(capsuleId); PendingCapsulePayloads.Remove(capsuleId); } private static void LogDebug(string message) { Lucky8Config config = Config; if (config != null && config.DebugLogging?.Value == true) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[LUCKY-8] " + message)); } } } } internal enum Lucky8RewardCategory : byte { Weapon, Suit, Cosmetic, Ammo, Emote } internal enum Lucky8Rarity : byte { Common, Uncommon, Rare, Legendary } internal sealed class Lucky8RewardDefinition { internal string StableId; internal string DisplayName; internal Lucky8RewardCategory Category; internal Lucky8Rarity Rarity; internal int WinWeight; internal Texture IconTexture; internal object IconSource; internal uint PresentationColorRgba; internal bool HasPresentationColor; } internal sealed class Lucky8RouteInfo { internal int RouteIndex; internal int LevelId; internal string MoonName; internal string ConstellationKey; internal bool IsCompanyMoon; internal bool HasFacility; } internal sealed class Lucky8MachineState { internal ulong NetworkObjectId; internal readonly Lucky8RewardDefinition[] Rewards = new Lucky8RewardDefinition[8]; internal byte SoldMask; internal int SpinsRemaining; internal bool IsSpinning; internal int WinnerIndex = -1; internal double SpinStartedAt; internal float SpinDuration; internal bool IsSold(int index) { if (index >= 0 && index < 8) { return (SoldMask & (1 << index)) != 0; } return false; } } internal static class Lucky8LineupGenerator { internal static bool TryCreate(IReadOnlyList weapons, IReadOnlyList suits, IReadOnlyList cosmetics, int seed, out Lucky8RewardDefinition[] lineup, out string reason) { return TryCreate(weapons, suits, cosmetics, null, seed, out lineup, out reason); } internal static bool TryCreate(IReadOnlyList weapons, IReadOnlyList suits, IReadOnlyList cosmetics, IReadOnlyList ammo, int seed, out Lucky8RewardDefinition[] lineup, out string reason) { return TryCreate(weapons, suits, cosmetics, ammo, null, seed, out lineup, out reason); } internal static bool TryCreate(IReadOnlyList weapons, IReadOnlyList suits, IReadOnlyList cosmetics, IReadOnlyList ammo, IReadOnlyList emotes, int seed, out Lucky8RewardDefinition[] lineup, out string reason) { lineup = null; reason = string.Empty; if (weapons == null || weapons.Count < 3 || suits == null || suits.Count < 3 || cosmetics == null || cosmetics.Count < 3) { reason = $"minimum-pool-not-met weapons={weapons?.Count ?? 0} suits={suits?.Count ?? 0} cosmetics={cosmetics?.Count ?? 0}"; return false; } StableRandom stableRandom = new StableRandom(seed); List list = new List(8); bool num = ammo != null && ammo.Count > 0; bool flag = emotes != null && emotes.Count > 0; int num2 = (num ? 1 : 0) + (flag ? 1 : 0); int num3 = (num ? ((num2 != 1) ? 1 : Math.Min(2, ammo.Count)) : 0); int num4 = (flag ? ((num2 != 1) ? 1 : Math.Min(2, emotes.Count)) : 0); int num5 = 8 - num3 - num4; int num6 = num5 / 3; int num7 = num5 % 3; int[] array = new int[3] { num6, num6, num6 }; List list2 = new List { 0, 1, 2 }; Shuffle(list2, stableRandom); for (int i = 0; i < num7; i++) { array[list2[i]]++; } AddUniqueRandom(list, weapons, array[0], stableRandom); AddUniqueRandom(list, suits, array[1], stableRandom); AddUniqueRandom(list, cosmetics, array[2], stableRandom); if (num3 > 0) { AddUniqueRandom(list, ammo, num3, stableRandom); } if (num4 > 0) { AddUniqueRandom(list, emotes, num4, stableRandom); } for (int num8 = list.Count - 1; num8 > 0; num8--) { int num9 = stableRandom.Next(num8 + 1); List list3 = list; int index = num8; int index2 = num9; Lucky8RewardDefinition value = list[num9]; Lucky8RewardDefinition value2 = list[num8]; list3[index] = value; list[index2] = value2; } lineup = list.ToArray(); return lineup.Length == 8; } internal static int PickWinner(Lucky8MachineState state, int seed) { if (state == null) { return -1; } int num = 0; for (int i = 0; i < state.Rewards.Length; i++) { if (!state.IsSold(i) && state.Rewards[i] != null) { num += Math.Max(1, state.Rewards[i].WinWeight); } } if (num <= 0) { return -1; } int num2 = new StableRandom(seed).Next(num); for (int j = 0; j < state.Rewards.Length; j++) { if (!state.IsSold(j) && state.Rewards[j] != null) { num2 -= Math.Max(1, state.Rewards[j].WinWeight); if (num2 < 0) { return j; } } } return -1; } private static void AddUniqueRandom(List destination, IReadOnlyList source, int count, StableRandom random) { List list = new List(source.Count); for (int i = 0; i < source.Count; i++) { list.Add(i); } for (int j = 0; j < count; j++) { int index = random.Next(list.Count); destination.Add(source[list[index]]); list.RemoveAt(index); } } private static void Shuffle(List values, StableRandom random) { for (int num = values.Count - 1; num > 0; num--) { int num2 = random.Next(num + 1); int index = num; int index2 = num2; int value = values[num2]; int value2 = values[num]; values[index] = value; values[index2] = value2; } } } internal static class Lucky8RewardResolver { internal static Lucky8RewardDefinition Resolve(IReadOnlyList pool, Lucky8RewardCategory category, string stableId, string displayName, Lucky8Rarity rarity, int winWeight) { if (pool != null) { for (int i = 0; i < pool.Count; i++) { Lucky8RewardDefinition lucky8RewardDefinition = pool[i]; if (lucky8RewardDefinition != null && string.Equals(lucky8RewardDefinition.StableId, stableId, StringComparison.OrdinalIgnoreCase)) { lucky8RewardDefinition.Rarity = rarity; lucky8RewardDefinition.WinWeight = Math.Max(1, winWeight); return lucky8RewardDefinition; } } } return new Lucky8RewardDefinition { StableId = (stableId ?? string.Empty), DisplayName = (string.IsNullOrWhiteSpace(displayName) ? (stableId ?? "Unknown reward") : displayName), Category = category, Rarity = rarity, WinWeight = Math.Max(1, winWeight) }; } } internal sealed class StableRandom { private uint state; internal StableRandom(int seed) { state = (uint)seed; if (state == 0) { state = 1831565813u; } } internal int Next(int maximum) { if (maximum <= 1) { return 0; } state ^= state << 13; state ^= state >> 17; state ^= state << 5; return (int)(state % (uint)maximum); } internal double NextDouble() { return (double)Next(int.MaxValue) / 2147483647.0; } } [HarmonyPatch] internal static class Lucky8Patches { [HarmonyPatch(typeof(StartOfRound), "Awake")] [HarmonyPostfix] private static void StartOfRoundAwakePostfix() { if (Lucky8Manager.IsInitialized) { Lucky8RuntimeAssets.TryRegisterCapsulePrefab(); } } [HarmonyPatch(typeof(RoundManager), "Update")] [HarmonyPostfix] private static void RoundManagerUpdatePostfix() { if (Lucky8Manager.IsInitialized) { Lucky8Manager.UpdateRuntime(); } } [HarmonyPatch(typeof(StartOfRound), "ShipLeave")] [HarmonyPostfix] private static void ShipLeavePostfix() { if (Lucky8Manager.IsInitialized) { Lucky8Manager.ResetVisit(); } } [HarmonyPatch(typeof(GrabbableObject), "ItemActivate")] [HarmonyPostfix] private static void ItemActivatePostfix(GrabbableObject __instance, bool buttonDown) { if (Lucky8Manager.IsInitialized && buttonDown && !((Object)(object)__instance == (Object)null)) { ((Component)__instance).GetComponent()?.TryClaimLocal(__instance); } } } internal static class Lucky8RewardCatalog { internal static IReadOnlyList BuildWeapons() { List list = new List(); string[] weaponPrizeIds = ArmoryBridge.GetWeaponPrizeIds(); foreach (string text in weaponPrizeIds) { list.Add(new Lucky8RewardDefinition { StableId = text, DisplayName = ArmoryBridge.GetWeaponDisplayName(text), Category = Lucky8RewardCategory.Weapon }); } return ApplyPool(list, Lucky8Manager.Config.WeaponPool.Value); } internal static IReadOnlyList BuildAmmo() { List list = new List(); string[] ammoPrizeIds = ArmoryBridge.GetAmmoPrizeIds(); foreach (string text in ammoPrizeIds) { list.Add(new Lucky8RewardDefinition { StableId = text, DisplayName = ArmoryBridge.GetAmmoDisplayName(text), Category = Lucky8RewardCategory.Ammo }); } return ApplyPool(list, Lucky8Manager.Config.AmmoPool.Value); } internal static IReadOnlyList BuildSuits() { List list = new List(); List list2 = StartOfRound.Instance?.unlockablesList?.unlockables; if (list2 != null) { for (int i = 0; i < list2.Count; i++) { UnlockableItem val = list2[i]; if (val != null && val.unlockableType == 0 && !((Object)(object)val.suitMaterial == (Object)null) && !val.alreadyUnlocked) { string text = (string.IsNullOrWhiteSpace(val.unlockableName) ? ("Suit " + i) : val.unlockableName.Trim()); list.Add(new Lucky8RewardDefinition { StableId = Slug(text), DisplayName = text, Category = Lucky8RewardCategory.Suit }); } } } return ApplyPool(list, Lucky8Manager.Config.SuitPool.Value); } internal static IReadOnlyList BuildCosmetics() { return ApplyPool((from entry in Lucky8IconResolver.DiscoverMoreCompanyCosmetics() select new Lucky8RewardDefinition { StableId = entry.id, DisplayName = entry.label, Category = Lucky8RewardCategory.Cosmetic }).ToList(), Lucky8Manager.Config.CosmeticPool.Value); } internal static IReadOnlyList BuildEmotes() { return BuildEmotes(excludeOwned: true); } private static IReadOnlyList BuildEmotes(bool excludeOwned) { List allPurchasableEmotes = TooManyEmotesBridge.GetAllPurchasableEmotes(); if (allPurchasableEmotes == null) { return Array.Empty(); } List list = new List(); for (int i = 0; i < allPurchasableEmotes.Count; i++) { TooManyEmotesEntry tooManyEmotesEntry = allPurchasableEmotes[i]; if (excludeOwned) { bool flag = TooManyEmotesBridge.IsEmoteUnlocked(tooManyEmotesEntry.obj); if (!TooManyEmotesBridge.IsAvailable) { return Array.Empty(); } if (flag) { continue; } } list.Add(CreateEmoteReward(tooManyEmotesEntry)); } return ApplyPool(list, Lucky8Manager.Config.EmotePool.Value); } internal static Lucky8RewardDefinition Resolve(Lucky8RewardCategory category, string stableId, string displayName, Lucky8Rarity rarity) { if (category == Lucky8RewardCategory.Emote) { TooManyEmotesEntry tooManyEmotesEntry = TooManyEmotesBridge.FindPurchasableEmote(stableId); if (tooManyEmotesEntry != null) { Lucky8RewardDefinition lucky8RewardDefinition = CreateEmoteReward(tooManyEmotesEntry); lucky8RewardDefinition.Rarity = rarity; lucky8RewardDefinition.WinWeight = Lucky8Manager.Config.WeightFor(rarity); return lucky8RewardDefinition; } } return Lucky8RewardResolver.Resolve(category switch { Lucky8RewardCategory.Weapon => BuildWeapons(), Lucky8RewardCategory.Suit => BuildSuits(), Lucky8RewardCategory.Ammo => BuildAmmo(), Lucky8RewardCategory.Emote => Array.Empty(), _ => BuildCosmetics(), }, category, stableId, displayName, rarity, Lucky8Manager.Config.WeightFor(rarity)); } internal static bool HasMinimumPools(out string reason) { int count = BuildSuits().Count; int count2 = BuildCosmetics().Count; bool flag = count >= 3 && count2 >= 3; if (!ArmoryBridge.IsArmoryPresent) { reason = (flag ? string.Empty : $"suits={count}, cosmetics={count2}; each category requires at least 3"); return flag; } int count3 = BuildWeapons().Count; flag = flag && count3 >= 3; reason = (flag ? string.Empty : $"weapons={count3}, suits={count}, cosmetics={count2}; each category requires at least 3"); return flag; } internal static int MinimumPoolSourceFingerprint() { uint hash = 2166136261u; string[] weaponFingerprintTokens = ArmoryBridge.GetWeaponFingerprintTokens(); foreach (string value in weaponFingerprintTokens) { AddFingerprint(ref hash, value); } List list = StartOfRound.Instance?.unlockablesList?.unlockables; if (list == null) { AddFingerprint(ref hash, "suits-unavailable"); } else { for (int j = 0; j < list.Count; j++) { UnlockableItem val = list[j]; if (val != null && val.unlockableType == 0 && !((Object)(object)val.suitMaterial == (Object)null)) { AddFingerprint(ref hash, j.ToString()); AddFingerprint(ref hash, val.unlockableName); AddFingerprint(ref hash, val.alreadyUnlocked ? "owned" : "eligible"); } } } foreach (var item2 in Lucky8IconResolver.DiscoverMoreCompanyCosmetics()) { string item = item2.id; AddFingerprint(ref hash, item); } return (int)hash; } private static void AddFingerprint(ref uint hash, string value) { string text = value ?? string.Empty; foreach (char c in text) { hash ^= c; hash *= 16777619u; } hash ^= 124u; hash *= 16777619u; } private static IReadOnlyList ApplyPool(List discovered, string configuration) { Dictionary dictionary = new Dictionary(StringComparer.OrdinalIgnoreCase); Lucky8Rarity? lucky8Rarity = null; bool flag = false; string[] array = (configuration ?? string.Empty).Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split('|'); string text = array2[0].Trim(); if (text.Length != 0) { Lucky8Rarity? lucky8Rarity2 = ((array2.Length > 1 && !string.IsNullOrWhiteSpace(array2[1])) ? new Lucky8Rarity?(ParseRarity(array2[1])) : ((Lucky8Rarity?)null)); if (text == "*") { flag = true; lucky8Rarity = lucky8Rarity2; } else { dictionary[text] = lucky8Rarity2; } } } List list = new List(); foreach (Lucky8RewardDefinition item in discovered) { if (!dictionary.TryGetValue(item.StableId, out var value)) { if (!flag) { continue; } value = lucky8Rarity; } if (value.HasValue) { item.Rarity = value.Value; } item.WinWeight = Lucky8Manager.Config.WeightFor(item.Rarity); list.Add(item); } return (from @group in list.GroupBy((Lucky8RewardDefinition reward) => reward.StableId, StringComparer.OrdinalIgnoreCase) select @group.First()).OrderBy((Lucky8RewardDefinition reward) => reward.DisplayName, StringComparer.OrdinalIgnoreCase).ToArray(); } private static Lucky8Rarity ParseRarity(string value) { if (!Enum.TryParse((value ?? string.Empty).Trim(), ignoreCase: true, out var result)) { return Lucky8Rarity.Common; } return result; } internal static Lucky8Rarity MapEmoteRarity(int tier, string tierName) { string text = (tierName ?? string.Empty).Trim(); if (text.IndexOf("legend", StringComparison.OrdinalIgnoreCase) >= 0) { return Lucky8Rarity.Legendary; } if (text.IndexOf("epic", StringComparison.OrdinalIgnoreCase) >= 0) { return Lucky8Rarity.Rare; } if (text.IndexOf("uncommon", StringComparison.OrdinalIgnoreCase) >= 0) { return Lucky8Rarity.Uncommon; } if (tier > 0) { return tier switch { 2 => Lucky8Rarity.Rare, 1 => Lucky8Rarity.Uncommon, _ => Lucky8Rarity.Legendary, }; } return Lucky8Rarity.Common; } private static Lucky8RewardDefinition CreateEmoteReward(TooManyEmotesEntry emote) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) return new Lucky8RewardDefinition { StableId = emote.emoteName, DisplayName = emote.displayName, Category = Lucky8RewardCategory.Emote, Rarity = MapEmoteRarity(emote.rarity, emote.rarityName), IconSource = emote.icon, PresentationColorRgba = Lucky8RewardPresentation.PackColor(emote.rarityColor), HasPresentationColor = true }; } private static string Slug(string value) { return new string((from character in (value ?? string.Empty).ToLowerInvariant() select (!char.IsLetterOrDigit(character)) ? '_' : character).ToArray()).Trim('_'); } } internal static class Lucky8RewardPresentation { internal static uint PackColor(Color color) { //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_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) Color32 val = Color32.op_Implicit(color); return (uint)((val.r << 24) | (val.g << 16) | (val.b << 8) | val.a); } internal static bool TryGetColor(Lucky8RewardDefinition reward, out Color color) { //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_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_0040: Unknown result type (might be due to invalid IL or missing references) color = Color.white; if (reward == null || !reward.HasPresentationColor) { return false; } uint presentationColorRgba = reward.PresentationColorRgba; color = Color32.op_Implicit(new Color32((byte)(presentationColorRgba >> 24), (byte)(presentationColorRgba >> 16), (byte)(presentationColorRgba >> 8), (byte)presentationColorRgba)); return true; } } internal static class Lucky8RewardUnlockApi { internal static bool IsOwned(Lucky8RewardDefinition reward) { if (reward == null) { return true; } PlayerLevelData playerLevelData = PlayerLevelStore.Get(); return reward.Category switch { Lucky8RewardCategory.Suit => playerLevelData.suits.Exists((string value) => string.Equals(value, reward.DisplayName, StringComparison.OrdinalIgnoreCase)), Lucky8RewardCategory.Cosmetic => playerLevelData.cosmetics.Exists((string value) => string.Equals(value, reward.StableId, StringComparison.OrdinalIgnoreCase)), Lucky8RewardCategory.Emote => TooManyEmotesBridge.IsEmoteUnlocked(reward.StableId), _ => false, }; } internal static bool TryClaim(Lucky8RewardDefinition reward, out string reason) { reason = string.Empty; if (reward == null || reward.Category == Lucky8RewardCategory.Weapon || reward.Category == Lucky8RewardCategory.Ammo) { reason = "invalid-claim-reward"; return false; } if (IsOwned(reward)) { reason = "already-owned"; return false; } if (reward.Category == Lucky8RewardCategory.Emote) { if (!TooManyEmotesBridge.IsAvailable) { reason = "emote-unavailable"; return false; } if (!TooManyEmotesBridge.TryUnlockEmoteLocal(reward.StableId)) { reason = "unlock-failed"; return false; } reason = "claimed"; return true; } PlayerLevelData playerLevelData = PlayerLevelStore.Get(); if (reward.Category == Lucky8RewardCategory.Suit) { playerLevelData.suits.Add(reward.DisplayName); } else { playerLevelData.cosmetics.Add(reward.StableId); } PlayerLevelStore.Save(); reason = "claimed"; return true; } } internal static class Lucky8RuntimeAssets { private sealed class MaterialIntent { internal readonly Color BaseColor; internal readonly float Metallic; internal readonly float Smoothness; internal readonly Color EmissiveColor; internal readonly bool UsesBaseMap; internal readonly bool UsesNormalMap; internal readonly bool UsesMaskMap; internal readonly bool UsesEmissiveMap; internal MaterialIntent(Color baseColor, float metallic, float smoothness, Color emissiveColor = default(Color), bool usesBaseMap = false, bool usesNormalMap = false, bool usesMaskMap = false, bool usesEmissiveMap = false) { //IL_0007: 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_001c: 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) BaseColor = baseColor; Metallic = metallic; Smoothness = smoothness; EmissiveColor = emissiveColor; UsesBaseMap = usesBaseMap; UsesNormalMap = usesNormalMap; UsesMaskMap = usesMaskMap; UsesEmissiveMap = usesEmissiveMap; } } private const string BundleFileName = "y4ngz-lucky8.bundle"; private static readonly MaterialIntent DefaultMaterialIntent = new MaterialIntent(new Color(0.05f, 0.055f, 0.06f), 0.78f, 0.58f); private static readonly Dictionary MaterialIntents = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["M_Lucky8_CreamPaint"] = new MaterialIntent(new Color(0.72f, 0.67f, 0.56f), 0.25f, 0.45f, default(Color), usesBaseMap: true, usesNormalMap: true, usesMaskMap: true), ["M_Lucky8_BluePaint"] = new MaterialIntent(new Color(0.05f, 0.21f, 0.33f), 0.3f, 0.48f, default(Color), usesBaseMap: true, usesNormalMap: true, usesMaskMap: true), ["M_Lucky8_DarkSteel"] = new MaterialIntent(new Color(0.05f, 0.055f, 0.06f), 0.78f, 0.58f, default(Color), usesBaseMap: true, usesNormalMap: false, usesMaskMap: true), ["M_Lucky8_SteelEdge"] = new MaterialIntent(new Color(0.4f, 0.41f, 0.43f), 0.86f, 0.62f, default(Color), usesBaseMap: true, usesNormalMap: false, usesMaskMap: true), ["M_Lucky8_Rubber"] = new MaterialIntent(new Color(0.03f, 0.032f, 0.032f), 0.02f, 0.18f, default(Color), usesBaseMap: true, usesNormalMap: true), ["M_Lucky8_IconFrame"] = new MaterialIntent(new Color(0.095f, 0.1f, 0.105f), 0.68f, 0.52f), ["M_Lucky8_IconScreen"] = new MaterialIntent(new Color(0.01f, 0.012f, 0.01f), 0.05f, 0.85f, new Color(1f, 0.74f, 0.45f) * 1.1f), ["M_Lucky8_ButtonPlastic"] = new MaterialIntent(new Color(0.2f, 0.022f, 0.015f), 0.05f, 0.68f, new Color(0.42f, 0.02f, 0.008f) * 0.18f), ["M_Lucky8_Indicator"] = new MaterialIntent(new Color(0.08f, 0.34f, 0.13f), 0.05f, 0.76f, new Color(0.05f, 0.65f, 0.12f) * 1.8f), ["M_Lucky8_BrandingTexture"] = new MaterialIntent(Color.white, 0.05f, 0.55f, Color.white * 2.2f, usesBaseMap: true, usesNormalMap: false, usesMaskMap: false, usesEmissiveMap: true), ["M_Lucky8_InstructionDecal"] = new MaterialIntent(Color.white, 0.1f, 0.4f, default(Color), usesBaseMap: true), ["M_Lucky8_CapsuleGlass"] = new MaterialIntent(new Color(0.08f, 0.26f, 0.24f), 0.15f, 0.85f, new Color(0.02f, 0.45f, 0.32f) * 0.5f), ["M_Lucky8_CapsuleLabelDecal"] = new MaterialIntent(Color.white, 0.05f, 0.5f, default(Color), usesBaseMap: true) }; private static AssetBundle bundle; private static GameObject holder; private static readonly Dictionary runtimeMaterials = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool machineRegistered; private static bool capsuleRegistered; internal static GameObject MachinePrefab { get; private set; } internal static GameObject CapsulePrefab { get; private set; } internal static Item CapsuleItem { get; private set; } internal static void Initialize() { LoadBundle(); TryRegisterMachinePrefab(); } internal static void Shutdown() { if ((Object)(object)holder != (Object)null) { Object.Destroy((Object)(object)holder); } AssetBundle obj = bundle; if (obj != null) { obj.Unload(false); } bundle = null; holder = null; foreach (Material value in runtimeMaterials.Values) { if ((Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } } runtimeMaterials.Clear(); MachinePrefab = null; CapsulePrefab = null; CapsuleItem = null; machineRegistered = false; capsuleRegistered = false; } internal static bool TryRegisterMachinePrefab() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0066: 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_00cd: 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 (machineRegistered) { return (Object)(object)MachinePrefab != (Object)null; } EnsureHolder(); GameObject val = new GameObject("Y4NGZ_Lucky8_Machine_NetworkPrefab"); val.transform.SetParent(holder.transform, false); val.SetActive(true); AssignStableNetworkHash(val.AddComponent(), "lucky8_machine"); BoxCollider obj = val.AddComponent(); obj.center = new Vector3(0f, 1.21f, 0f); obj.size = new Vector3(1.35f, 2.42f, 0.7f); val.AddComponent(); AssetBundle obj2 = bundle; GameObject val2 = ((obj2 != null) ? obj2.LoadAsset("Lucky8MachineVisual") : null); if ((Object)(object)val2 != (Object)null) { GameObject obj3 = Object.Instantiate(val2, val.transform); ((Object)obj3).name = "Lucky8MachineVisual"; obj3.transform.localPosition = Vector3.zero; obj3.transform.localRotation = Quaternion.identity; RemapAuthoredMaterials(obj3); } else { BuildFallbackMachine(val.transform); } DawnLibCompat.RegisterNetworkPrefab(val); MachinePrefab = val; machineRegistered = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[LUCKY-8] Registered machine network prefab" + (((Object)(object)val2 != (Object)null) ? " from authored bundle." : " with procedural fallback visuals."))); } return true; } internal static bool TryRegisterCapsulePrefab() { //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) if (capsuleRegistered) { return (Object)(object)CapsulePrefab != (Object)null; } Item val = FindBasePhysicsProp(); if ((Object)(object)val?.spawnPrefab == (Object)null) { return false; } EnsureHolder(); GameObject val2 = Object.Instantiate(val.spawnPrefab, holder.transform); ((Object)val2).name = "Y4NGZ_Lucky8_ClaimCapsule_NetworkPrefab"; val2.SetActive(true); AssignStableNetworkHash(val2.GetComponent(), "lucky8_claim_capsule"); Renderer[] componentsInChildren = val2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = false; } AssetBundle obj = bundle; GameObject val3 = ((obj != null) ? obj.LoadAsset("Lucky8ClaimCapsuleVisual") : null); if ((Object)(object)val3 != (Object)null) { GameObject obj2 = Object.Instantiate(val3, val2.transform); ((Object)obj2).name = "Lucky8ClaimCapsuleVisual"; obj2.transform.localPosition = Vector3.zero; obj2.transform.localRotation = Quaternion.identity; RemapAuthoredMaterials(obj2); componentsInChildren = obj2.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].enabled = true; } } else { BuildFallbackCapsule(val2.transform); } Item val4 = Object.Instantiate(val); ((Object)val4).name = "Y4NGZ_Lucky8_ClaimCapsule_Item"; val4.itemName = "LUCKY-8 Claim Capsule"; val4.isScrap = false; val4.creditsWorth = 0; val4.minValue = 0; val4.maxValue = 0; val4.saveItemVariable = false; val4.holdButtonUse = false; val4.syncUseFunction = false; val4.syncInteractLRFunction = false; val4.twoHanded = false; val4.twoHandedAnimation = false; val4.spawnPrefab = val2; string text = UpgradeInput.VanillaDisplayLabel("ActivateItem", "LMB"); string text2 = UpgradeInput.VanillaDisplayLabel("DiscardHeldObject", "G"); val4.toolTips = new string[2] { "Claim reward : [" + text + "]", "Drop : [" + text2 + "]" }; ((Object)val4).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val4); GrabbableObject[] components = val2.GetComponents(); for (int i = 0; i < components.Length; i++) { components[i].itemProperties = val4; } val2.AddComponent(); DawnLibCompat.FixMixerGroups(val2); DawnLibCompat.RegisterNetworkPrefab(val2); DawnLibCompat.RegisterItem("lucky8_claim_capsule", val4); CapsulePrefab = val2; CapsuleItem = val4; capsuleRegistered = true; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[LUCKY-8] Registered transferable claim capsule."); } return true; } private static void LoadBundle() { try { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? string.Empty, "y4ngz-lucky8.bundle"); if (File.Exists(text)) { bundle = AssetBundle.LoadFromFile(text); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[LUCKY-8] Authored bundle load failed; using fallback: " + ex.Message)); } } } private static void EnsureHolder() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown if (!((Object)(object)holder != (Object)null)) { holder = new GameObject("Y4NGZ_Lucky8_InactivePrefabHolder"); ((Object)holder).hideFlags = (HideFlags)61; holder.SetActive(false); Object.DontDestroyOnLoad((Object)(object)holder); } } private static Item FindBasePhysicsProp() { List list = StartOfRound.Instance?.allItemsList?.itemsList; if (list == null) { return null; } foreach (Item item in list) { object obj; if (item == null) { obj = null; } else { GameObject spawnPrefab = item.spawnPrefab; obj = ((spawnPrefab != null) ? spawnPrefab.GetComponent() : null); } GrabbableObject val = (GrabbableObject)obj; if ((Object)(object)val != (Object)null && ((object)val).GetType() == typeof(PhysicsProp)) { return item; } } return null; } private static void AssignStableNetworkHash(NetworkObject networkObject, string id) { if ((Object)(object)networkObject == (Object)null) { return; } using MD5 mD = MD5.Create(); uint num = BitConverter.ToUInt32(mD.ComputeHash(Encoding.UTF8.GetBytes("com.y4ngz.upgrades.Lucky8." + id)), 0); (typeof(NetworkObject).GetField("GlobalObjectIdHash", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) ?? typeof(NetworkObject).GetField("k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic))?.SetValue(networkObject, num); } private static void BuildFallbackMachine(Transform root) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_008b: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0100: 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_0116: 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_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_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_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0173: Unknown result type (might be due to invalid IL or missing references) //IL_01b0: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: 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_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0253: Unknown result type (might be due to invalid IL or missing references) //IL_0299: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_02c1: Unknown result type (might be due to invalid IL or missing references) //IL_02fa: 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_0322: Unknown result type (might be due to invalid IL or missing references) //IL_0374: Unknown result type (might be due to invalid IL or missing references) //IL_0388: Unknown result type (might be due to invalid IL or missing references) //IL_039c: Unknown result type (might be due to invalid IL or missing references) //IL_03dd: Unknown result type (might be due to invalid IL or missing references) //IL_03f1: Unknown result type (might be due to invalid IL or missing references) //IL_03f6: Unknown result type (might be due to invalid IL or missing references) //IL_042f: Unknown result type (might be due to invalid IL or missing references) //IL_0443: Unknown result type (might be due to invalid IL or missing references) //IL_0448: Unknown result type (might be due to invalid IL or missing references) //IL_0481: Unknown result type (might be due to invalid IL or missing references) //IL_0495: Unknown result type (might be due to invalid IL or missing references) //IL_04a9: Unknown result type (might be due to invalid IL or missing references) //IL_04e1: Unknown result type (might be due to invalid IL or missing references) //IL_0500: Unknown result type (might be due to invalid IL or missing references) CreatePrimitive(root, "CabinetLowerBlue", (PrimitiveType)3, new Vector3(0f, 0.65f, 0f), new Vector3(1.32f, 1.3f, 0.68f), new Color(0.05f, 0.21f, 0.33f), 0.3f, 0.48f, null, "M_Lucky8_BluePaint"); CreatePrimitive(root, "CabinetUpperCream", (PrimitiveType)3, new Vector3(0f, 1.82f, 0f), new Vector3(1.32f, 1.1f, 0.68f), new Color(0.72f, 0.67f, 0.56f), 0.25f, 0.45f, null, "M_Lucky8_CreamPaint"); Vector2[] array = (Vector2[])(object)new Vector2[8] { new Vector2(-0.39f, 1.92f), new Vector2(0f, 1.92f), new Vector2(0.39f, 1.92f), new Vector2(0.39f, 1.58f), new Vector2(0.39f, 1.24f), new Vector2(0f, 1.24f), new Vector2(-0.39f, 1.24f), new Vector2(-0.39f, 1.58f) }; for (int i = 0; i < array.Length; i++) { CreatePrimitive(root, "RewardFrame_" + i, (PrimitiveType)3, new Vector3(array[i].x, array[i].y, 0.35f), new Vector3(0.318f, 0.238f, 0.014f), new Color(0.095f, 0.1f, 0.105f), 0.68f, 0.52f, null, "M_Lucky8_IconFrame"); CreatePrimitive(root, "RewardSlot_" + i, (PrimitiveType)3, new Vector3(array[i].x, array[i].y, 0.363f), new Vector3(0.286f, 0.206f, 0.012f), new Color(0.01f, 0.012f, 0.01f), 0.05f, 0.85f, null, "M_Lucky8_IconScreen"); } CreatePrimitive(root, "CenterButton", (PrimitiveType)3, new Vector3(0f, 1.58f, 0.37f), new Vector3(0.185f, 0.185f, 0.016f), new Color(0.2f, 0.022f, 0.015f), 0.05f, 0.68f, null, "M_Lucky8_ButtonPlastic"); CreatePrimitive(root, "PrizeChute", (PrimitiveType)3, new Vector3(0f, 0.48f, 0.36f), new Vector3(0.69f, 0.18f, 0.02f), new Color(0.03f, 0.032f, 0.032f), 0.02f, 0.18f, null, "M_Lucky8_Rubber"); for (int j = 0; j < 3; j++) { CreatePrimitive(root, "TokenLed_" + j, (PrimitiveType)3, new Vector3(-0.09f + (float)j * 0.09f, 1.005f, 0.36f), new Vector3(0.042f, 0.026f, 0.012f), new Color(0.08f, 0.34f, 0.13f), 0.05f, 0.76f, null, "M_Lucky8_Indicator"); } CreatePrimitive(root, "Lucky8_BrandingDecal", (PrimitiveType)3, new Vector3(0f, 2.18f, 0.355f), new Vector3(0.92f, 0.2f, 0.012f), Color.white, 0.05f, 0.55f, null, "M_Lucky8_BrandingTexture"); CreatePrimitive(root, "TokenPanelDecal", (PrimitiveType)3, new Vector3(-0.1f, 0.92f, 0.363f), new Vector3(0.36f, 0.14f, 0.008f), Color.white, 0.1f, 0.4f, null, "M_Lucky8_InstructionDecal"); CreatePrimitive(root, "StatusAccent", (PrimitiveType)3, new Vector3(0f, 2.005f, 0.356f), new Vector3(0.88f, 0.016f, 0.01f), new Color(0.08f, 0.34f, 0.13f), 0.05f, 0.76f, null, "M_Lucky8_Indicator"); CreateAnchor(root, "MarqueeLightAnchor", new Vector3(0f, 2.175f, 0.4f)); CreateAnchor(root, "RewardBayLightAnchor", new Vector3(0f, 1.565f, 0.43f)); } private static void RemapAuthoredMaterials(GameObject root) { Renderer[] componentsInChildren = root.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { Material[] sharedMaterials = val.sharedMaterials; for (int j = 0; j < sharedMaterials.Length; j++) { Material val2 = sharedMaterials[j]; string sourceName = (((Object)(object)val2 != (Object)null) ? ((Object)val2).name.Replace(" (Instance)", string.Empty) : ((Object)val).name); sharedMaterials[j] = GetRuntimeMaterial(sourceName, val2); } val.sharedMaterials = sharedMaterials; } } private static Material GetRuntimeMaterial(string sourceName, Material sourceMaterial) { //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Expected O, but got Unknown //IL_00d7: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: 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_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_029c: Unknown result type (might be due to invalid IL or missing references) //IL_02a1: Unknown result type (might be due to invalid IL or missing references) if (runtimeMaterials.TryGetValue(sourceName, out var value) && (Object)(object)value != (Object)null) { return value; } Shader obj = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard"); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("LUCKY-8 could not locate a runtime lit shader."); } if (!MaterialIntents.TryGetValue(sourceName, out var value2)) { value2 = DefaultMaterialIntent; } Material val = new Material(obj) { name = "Lucky8_Runtime_" + sourceName, hideFlags = (HideFlags)61 }; bool flag = false; if (value2.UsesBaseMap) { flag = CopyTexture(sourceMaterial, val, "_BaseColorMap", "_BaseColorMap", "_MainTex"); flag = CopyTexture(sourceMaterial, val, "_MainTex", "_BaseColorMap", "_MainTex") || flag; } Color value3 = (flag ? Color.white : value2.BaseColor); SetColor(val, "_BaseColor", value3); SetColor(val, "_Color", value3); SetFloat(val, "_Metallic", value2.Metallic); SetFloat(val, "_Smoothness", value2.Smoothness); SetColor(val, "_EmissiveColor", value2.EmissiveColor); SetColor(val, "_EmissionColor", value2.EmissiveColor); if (value2.UsesNormalMap) { bool flag2 = CopyTexture(sourceMaterial, val, "_NormalMap", "_NormalMap", "_BumpMap"); if (CopyTexture(sourceMaterial, val, "_BumpMap", "_NormalMap", "_BumpMap") || flag2) { SetFloat(val, "_NormalScale", 0.8f); SetFloat(val, "_BumpScale", 0.8f); val.EnableKeyword("_NORMALMAP"); val.EnableKeyword("_NORMALMAP_TANGENT_SPACE"); } } if (value2.UsesMaskMap) { bool flag3 = CopyTexture(sourceMaterial, val, "_MaskMap", "_MaskMap", "_MetallicGlossMap"); if (CopyTexture(sourceMaterial, val, "_MetallicGlossMap", "_MaskMap", "_MetallicGlossMap") || flag3) { val.EnableKeyword("_MASKMAP"); val.EnableKeyword("_METALLICGLOSSMAP"); } } if (value2.UsesEmissiveMap) { bool flag4 = CopyTexture(sourceMaterial, val, "_EmissiveColorMap", "_EmissiveColorMap", "_EmissionMap"); if (CopyTexture(sourceMaterial, val, "_EmissionMap", "_EmissiveColorMap", "_EmissionMap") || flag4) { val.EnableKeyword("_EMISSIVE_COLOR_MAP"); } } Color emissiveColor = value2.EmissiveColor; if (((Color)(ref emissiveColor)).maxColorComponent > 0f || value2.UsesEmissiveMap) { val.EnableKeyword("_EMISSION"); val.globalIlluminationFlags = (MaterialGlobalIlluminationFlags)1; } runtimeMaterials[sourceName] = val; return val; } private static void SetColor(Material material, string property, Color value) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(property)) { material.SetColor(property, value); } } private static void SetFloat(Material material, string property, float value) { if (material.HasProperty(property)) { material.SetFloat(property, value); } } private static bool CopyTexture(Material source, Material target, string targetProperty, params string[] sourceProperties) { //IL_0044: 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) if ((Object)(object)source == (Object)null || !target.HasProperty(targetProperty)) { return false; } foreach (string text in sourceProperties) { if (source.HasProperty(text)) { Texture texture = source.GetTexture(text); if (!((Object)(object)texture == (Object)null)) { target.SetTexture(targetProperty, texture); target.SetTextureScale(targetProperty, source.GetTextureScale(text)); target.SetTextureOffset(targetProperty, source.GetTextureOffset(text)); return true; } } } return false; } private static void BuildFallbackCapsule(Transform root) { //IL_0007: 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_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_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_009f: Unknown result type (might be due to invalid IL or missing references) CreatePrimitive(root, "CapsuleVisual", (PrimitiveType)1, Vector3.zero, new Vector3(0.32f, 0.42f, 0.32f), new Color(0.08f, 0.26f, 0.24f), 0.15f, 0.85f, null, "M_Lucky8_CapsuleGlass"); CreatePrimitive(root, "Capsule8Decal", (PrimitiveType)2, new Vector3(0f, 0.04f, 0.165f), new Vector3(0.052f, 0.006f, 0.052f), Color.white, 0.05f, 0.5f, (Vector3?)new Vector3(90f, 0f, 0f), "M_Lucky8_CapsuleLabelDecal"); } private static void CreateAnchor(Transform parent, string name, Vector3 position) { //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_0018: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); val.transform.localPosition = position; } private static GameObject CreatePrimitive(Transform parent, string name, PrimitiveType type, Vector3 position, Vector3 scale, Color color, float metallic, float smoothness, Vector3? euler = null, string materialName = null) { //IL_0000: 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_0041: 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_0051: 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_00ce: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive(type); ((Object)obj).name = name; obj.transform.SetParent(parent, false); obj.transform.localPosition = position; obj.transform.localEulerAngles = (Vector3)(((??)euler) ?? Vector3.zero); obj.transform.localScale = scale; Collider component = obj.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent(); Shader val = Shader.Find("HDRP/Lit") ?? Shader.Find("Standard"); if ((Object)(object)component2 != (Object)null && (Object)(object)val != (Object)null) { Material val2; if (!string.IsNullOrEmpty(materialName)) { val2 = GetRuntimeMaterial(materialName, null); } else { val2 = new Material(val) { name = "Lucky8_" + name }; SetColor(val2, "_BaseColor", color); SetColor(val2, "_Color", color); SetFloat(val2, "_Metallic", metallic); SetFloat(val2, "_Smoothness", smoothness); } component2.sharedMaterial = val2; } return obj; } } } namespace Y4NGZUpgrades.Interactive { public static class Plugin { public const string ModuleName = "Y4NGZUpgrades Interactive Systems"; public static ConfigEntry CombatFeedbackEnabled; public static ConfigEntry CombatFeedbackHitMarkerEnabled; public static ConfigEntry CombatFeedbackHitSoundEnabled; public static ConfigEntry CombatFeedbackEnemyFlashEnabled; public static ConfigEntry CombatFeedbackEnemyImpactLightEnabled; public static ConfigEntry CombatFeedbackEnemyImpactSoundEnabled; public static ConfigEntry DangerFeedbackEnabled; public static ConfigEntry DangerFeedbackDirectionalDamageEnabled; public static ConfigEntry DangerFeedbackLowHealthEnabled; public static ConfigEntry DangerFeedbackHeartbeatEnabled; public static ConfigEntry DangerFeedbackLowHealthThreshold; public static ConfigEntry WorldFeedbackEnabled; public static ConfigEntry WorldFeedbackScrapPickupEnabled; public static ConfigEntry WorldFeedbackHighValueGlintEnabled; public static ConfigEntry WorldFeedbackNearMissWhooshEnabled; public static ConfigEntry WorldFeedbackScanEnhancementsEnabled; private static bool _initialized; public static ManualLogSource Log { get; private set; } internal static void Initialize(ManualLogSource log, MonoBehaviour coroutineHost) { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) if (!_initialized) { _initialized = true; Log = log; UiTheme.Initialize(); GameplayUiVisibility.Initialize(); GameplayHudMotion.Initialize(); UiTheme.ProtectedSlotResolver = (int slot) => DeathboundUpgrade.IsUnlocked() && slot == 0; UiTheme.ThemeChanged += OnThemeChanged; GameplayUiVisibility.VisibilityChanged += OnGameplayUiVisibilityChanged; GameplayHudMotion.MotionSampled += OnHudMotionSampled; OnThemeChanged(UiTheme.CurrentPreset); OnGameplayUiVisibilityChanged(GameplayUiVisibility.IsVisible); OnHudMotionSampled(GameplayHudMotion.CurrentOffset); ManualLogSource log2 = Log; if (log2 != null) { log2.LogInfo((object)"Y4NGZUpgrades Interactive Systems initialized."); } } } internal static void Shutdown() { DirectionalDamageHud.DestroyInstance(); PlayerDangerHud.DestroyInstance(); CommandNetPatch.ShutdownPresentation(); UiTheme.ThemeChanged -= OnThemeChanged; GameplayUiVisibility.VisibilityChanged -= OnGameplayUiVisibilityChanged; GameplayHudMotion.MotionSampled -= OnHudMotionSampled; UiTheme.ProtectedSlotResolver = null; GameplayHudMotion.Shutdown(); GameplayUiVisibility.Shutdown(); UiTheme.Shutdown(); _initialized = false; } private static void OnThemeChanged(HudColorPreset preset) { Y4ngzPromptOverlay.RefreshTheme(); UpgradeHUDManager.RefreshTheme(); CommandNetPatch.RefreshPresentationTheme(); } private static void OnGameplayUiVisibilityChanged(bool visible) { Y4ngzPromptOverlay.SetPresentationVisible(visible); DirectionalDamageHud.SetPresentationVisible(visible); PlayerDangerHud.SetPresentationVisible(visible); CommandNetPatch.SetPresentationVisible(visible); } private static void OnHudMotionSampled(Vector2 offset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) CommandNetPatch.SetHudMotionOffset(offset); } } internal readonly struct HeldItemStowHandle : IDisposable { private readonly PlayerControllerB _player; private readonly long _token; internal bool IsActive => HeldItemStowService.IsTokenLive(_player, _token); internal long Token => _token; internal HeldItemStowHandle(PlayerControllerB player, long token) { _player = player; _token = token; } public void Dispose() { if (_token != 0L) { HeldItemStowService.Release(_player, _token); } } } internal static class HeldItemStowService { private sealed class StowEntry { internal GrabbableObject Item; internal int Slot; internal bool EquippedUsableItemQE; internal float ExpiresAt; internal string Reason; internal List DisabledActions; internal readonly Dictionary Tokens = new Dictionary(); } private const int ItemOnlySlotIndex = 50; private const float SpecialInteractGraceSeconds = 3f; private static readonly Dictionary Entries = new Dictionary(); private static readonly List ScratchPlayers = new List(); private static readonly InteractionAnimationPresentationKind[] BodyPresentationKinds = (InteractionAnimationPresentationKind[])(object)new InteractionAnimationPresentationKind[2] { (InteractionAnimationPresentationKind)1, default(InteractionAnimationPresentationKind) }; private static readonly string[] SuppressedActionNames = new string[6] { "ActivateItem", "ItemSecondaryUse", "ItemTertiaryUse", "SwitchItem", "UseUtilitySlot", "DiscardHeldObject" }; private static long _nextToken = 1L; internal static HeldItemStowHandle Begin(PlayerControllerB player, string reason, float safetyTimeoutSeconds = 15f, bool disableItemActions = false, bool force = false) { if ((Object)(object)player == (Object)null) { return default(HeldItemStowHandle); } Y4NGZPersistentRunner.Ensure(); string text = (string.IsNullOrWhiteSpace(reason) ? "unspecified" : reason); float num = Time.time + Mathf.Max(0.25f, safetyTimeoutSeconds); if (Entries.TryGetValue(player, out var value)) { long num2 = NextToken(); value.Tokens[num2] = text; value.ExpiresAt = Mathf.Max(value.ExpiresAt, num); if (disableItemActions) { ApplyInputSuppression(player, value); } return new HeldItemStowHandle(player, num2); } GrabbableObject currentlyHeldObjectServer = player.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null) { return default(HeldItemStowHandle); } if (!force && !ShouldStow(currentlyHeldObjectServer)) { return default(HeldItemStowHandle); } value = new StowEntry { Item = currentlyHeldObjectServer, Slot = player.currentItemSlot, EquippedUsableItemQE = player.equippedUsableItemQE, ExpiresAt = num, Reason = text }; if (!TryStow(player, value)) { return default(HeldItemStowHandle); } long num3 = NextToken(); value.Tokens[num3] = text; Entries[player] = value; if (disableItemActions) { ApplyInputSuppression(player, value); } return new HeldItemStowHandle(player, num3); } internal static void End(PlayerControllerB player, string reason) { if ((Object)(object)player == (Object)null || !Entries.TryGetValue(player, out var value)) { return; } string b = (string.IsNullOrWhiteSpace(reason) ? "unspecified" : reason); List list = new List(value.Tokens.Count); foreach (KeyValuePair token in value.Tokens) { if (string.Equals(token.Value, b, StringComparison.Ordinal)) { list.Add(token.Key); } } for (int i = 0; i < list.Count; i++) { value.Tokens.Remove(list[i]); } if (value.Tokens.Count == 0) { Finish(player, value, restore: true); } } internal static bool IsStowed(PlayerControllerB player) { if ((Object)(object)player != (Object)null) { return Entries.ContainsKey(player); } return false; } internal static void AbortAll(string reason) { if (Entries.Count == 0) { return; } CollectPlayers(); for (int i = 0; i < ScratchPlayers.Count; i++) { PlayerControllerB val = ScratchPlayers[i]; if (Entries.TryGetValue(val, out var value)) { Finish(val, value, restore: true); } } Entries.Clear(); ScratchPlayers.Clear(); if (!string.IsNullOrWhiteSpace(reason)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[HeldItemStow] aborted all stows: " + reason)); } } } internal static void Clear(PlayerControllerB player) { if (!((Object)(object)player == (Object)null) && Entries.TryGetValue(player, out var value)) { Finish(player, value, restore: false); } } internal static void Tick() { if (Entries.Count == 0) { return; } CollectPlayers(); for (int i = 0; i < ScratchPlayers.Count; i++) { PlayerControllerB val = ScratchPlayers[i]; if (!Entries.TryGetValue(val, out var value)) { continue; } if ((Object)(object)val == (Object)null || val.isPlayerDead || !val.isPlayerControlled || (Object)(object)((Component)val).gameObject == (Object)null) { Finish(val, value, restore: false); } else if ((Object)(object)value.Item == (Object)null || (Object)(object)val.currentlyHeldObjectServer != (Object)null || val.currentItemSlot != value.Slot || !ItemStillOccupiesSlot(val, value)) { Finish(val, value, restore: false); } else if (val.isClimbingLadder || val.inSpecialInteractAnimation) { value.ExpiresAt = Mathf.Max(value.ExpiresAt, Time.time + 3f); } else if (Time.time >= value.ExpiresAt) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HeldItemStow] safety timeout expired for reason '" + value.Reason + "'; restoring held item. Live tokens: " + DescribeTokens(value) + ".")); } Finish(val, value, restore: true); } } ScratchPlayers.Clear(); } internal static bool ShouldStow(GrabbableObject item) { if ((Object)(object)item == (Object)null) { return false; } if (ArmoryItemProbe.IsArmoryWeapon(item)) { return true; } if ((Object)(object)item.itemProperties != (Object)null) { return item.itemProperties.twoHandedAnimation; } return false; } internal static bool IsTokenLive(PlayerControllerB player, long token) { if ((Object)(object)player != (Object)null && token != 0L && Entries.TryGetValue(player, out var value)) { return value.Tokens.ContainsKey(token); } return false; } internal static void Release(PlayerControllerB player, long token) { if (!((Object)(object)player == (Object)null) && token != 0L && Entries.TryGetValue(player, out var value) && value.Tokens.Remove(token) && value.Tokens.Count == 0) { Finish(player, value, restore: true); } } private static string DescribeTokens(StowEntry entry) { if (entry.Tokens.Count == 0) { return "none"; } List list = new List(entry.Tokens.Count); foreach (KeyValuePair token in entry.Tokens) { list.Add($"{token.Value}#{token.Key}"); } return string.Join(", ", list.ToArray()); } private static long NextToken() { long result = _nextToken++; if (_nextToken == 0L) { _nextToken = 1L; } return result; } private static void CollectPlayers() { ScratchPlayers.Clear(); foreach (KeyValuePair entry in Entries) { ScratchPlayers.Add(entry.Key); } } private static void Finish(PlayerControllerB player, StowEntry entry, bool restore) { Entries.Remove(player); EnableActions(entry.DisabledActions); entry.DisabledActions = null; if (restore) { TryRestore(player, entry); } } private static bool TryStow(PlayerControllerB player, StowEntry entry) { GrabbableObject item = entry.Item; try { item.playerHeldBy = player; item.PocketItem(); player.currentlyHeldObjectServer = null; player.currentlyHeldObject = null; player.isHoldingObject = false; player.twoHanded = false; player.twoHandedAnimation = false; player.equippedUsableItemQE = false; ReleaseInteractionBody(player); Animator playerBodyAnimator = player.playerBodyAnimator; if ((Object)(object)playerBodyAnimator != (Object)null) { playerBodyAnimator.SetBool("Grab", false); if ((Object)(object)item.itemProperties != (Object)null && !string.IsNullOrEmpty(item.itemProperties.grabAnim)) { playerBodyAnimator.SetBool(item.itemProperties.grabAnim, false); } if ((Object)(object)item.itemProperties != (Object)null && !string.IsNullOrEmpty(item.itemProperties.pocketAnim)) { playerBodyAnimator.SetTrigger(item.itemProperties.pocketAnim); } playerBodyAnimator.SetBool("GrabValidated", false); playerBodyAnimator.SetBool("cancelHolding", true); } if ((Object)(object)player.heldObjectServerCopy != (Object)null) { player.heldObjectServerCopy.SetActive(false); } if (((NetworkBehaviour)player).IsOwner) { HUDManager instance = HUDManager.Instance; if (instance != null) { instance.ClearControlTips(); } } return true; } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HeldItemStow] stow failed for '" + entry.Reason + "': " + ex.Message)); } return false; } } private static void ReleaseInteractionBody(PlayerControllerB player) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) try { ArmoryBridge.StopPresentationForHeldItemStow(player); InteractionAnimationHandle val = default(InteractionAnimationHandle); for (int i = 0; i < BodyPresentationKinds.Length; i++) { if (LCInteractionAnimationAPI.TryGetActiveInteraction(player, BodyPresentationKinds[i], ref val)) { LCInteractionAnimationAPI.TryStopInteraction(val, (InteractionAnimationStopReason)2); } } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HeldItemStow] interaction body release failed safely: " + ex.Message)); } } } private static void TryRestore(PlayerControllerB player, StowEntry entry) { if ((Object)(object)player == (Object)null || (Object)(object)entry.Item == (Object)null || player.isPlayerDead || (Object)(object)player.currentlyHeldObjectServer != (Object)null || !ItemStillOccupiesSlot(player, entry)) { return; } try { GrabbableObject item = entry.Item; item.playerHeldBy = player; item.EquipItem(); player.currentlyHeldObjectServer = item; player.currentlyHeldObject = item; player.isHoldingObject = true; player.twoHanded = (Object)(object)item.itemProperties != (Object)null && item.itemProperties.twoHanded; player.twoHandedAnimation = (Object)(object)item.itemProperties != (Object)null && item.itemProperties.twoHandedAnimation; player.equippedUsableItemQE = entry.EquippedUsableItemQE; player.timeSinceSwitchingSlots = 0f; if ((Object)(object)player.heldObjectServerCopy != (Object)null) { player.heldObjectServerCopy.SetActive(true); } Animator playerBodyAnimator = player.playerBodyAnimator; if ((Object)(object)playerBodyAnimator != (Object)null) { playerBodyAnimator.SetBool("GrabValidated", true); playerBodyAnimator.SetBool("cancelHolding", false); if ((Object)(object)item.itemProperties != (Object)null && !string.IsNullOrEmpty(item.itemProperties.grabAnim)) { playerBodyAnimator.SetBool(item.itemProperties.grabAnim, true); } string text = (player.twoHandedAnimation ? "SwitchHoldAnimationTwoHanded" : "SwitchHoldAnimation"); playerBodyAnimator.ResetTrigger(text); playerBodyAnimator.SetTrigger(text); } } catch (Exception ex) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[HeldItemStow] restore failed safely for '" + entry.Reason + "': " + ex.Message)); } } } private static bool ItemStillOccupiesSlot(PlayerControllerB player, StowEntry entry) { if (entry.Slot == 50) { return (Object)(object)player.ItemOnlySlot == (Object)(object)entry.Item; } if (player.ItemSlots != null && entry.Slot >= 0 && entry.Slot < player.ItemSlots.Length) { return (Object)(object)player.ItemSlots[entry.Slot] == (Object)(object)entry.Item; } return false; } private static void ApplyInputSuppression(PlayerControllerB player, StowEntry entry) { if (entry.DisabledActions != null || (Object)(object)player != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return; } List list = new List(SuppressedActionNames.Length); IngamePlayerSettings instance = IngamePlayerSettings.Instance; object obj; if (instance == null) { obj = null; } else { PlayerInput playerInput = instance.playerInput; obj = ((playerInput != null) ? playerInput.actions : null); } InputActionAsset val = (InputActionAsset)obj; if ((Object)(object)val != (Object)null) { for (int i = 0; i < SuppressedActionNames.Length; i++) { InputAction val2 = val.FindAction(SuppressedActionNames[i], false); if (val2 != null && val2.enabled) { val2.Disable(); list.Add(val2); } } } entry.DisabledActions = list; } private static void EnableActions(List actions) { if (actions == null) { return; } for (int i = 0; i < actions.Count; i++) { InputAction obj = actions[i]; if (obj != null) { obj.Enable(); } } } } } namespace Y4NGZUpgrades.Interactive.Patches { [HarmonyPatch] internal static class CombatFeedbackPatch { private const int BurnHitId = -9401; private const float DamageSourceValidityWindow = 1.25f; private const float DamageSourceValidityRange = 26f; private const float NearestEnemyDamageRange = 18f; private const float FeedbackSampleInterval = 0.05f; private static EnemyAI _lastPotentialDamageSource; private static float _lastPotentialDamageSourceTime = -999f; private static float _nextFeedbackSampleTime; [HarmonyPatch(typeof(EnemyAI), "HitEnemy")] [HarmonyPostfix] private static void PostHitEnemy(EnemyAI __instance, int force, int hitID) { if (!((Object)(object)__instance == (Object)null) && force != 0 && hitID != -9401) { EnemyHitFlash.Pulse(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && !(Time.unscaledTime < _nextFeedbackSampleTime)) { _nextFeedbackSampleTime = Time.unscaledTime + 0.05f; PlayerDangerHud.UpdatePlayerState(__instance); } } [HarmonyPatch(typeof(EnemyAI), "OnCollideWithPlayer")] [HarmonyPrefix] private static void PreEnemyAIOnCollideWithPlayer(EnemyAI __instance, Collider other) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)other == (Object)null)) { PlayerControllerB component = ((Component)other).GetComponent(); if (!((Object)(object)component == (Object)null) && !((Object)(object)component != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { _lastPotentialDamageSource = __instance; _lastPotentialDamageSourceTime = Time.time; } } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber, bool fallDamage, CauseOfDeath causeOfDeath) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && damageNumber > 0) { PlayerDangerHud.PulseDamage(damageNumber); if (TryResolveDamageSource(__instance, fallDamage, causeOfDeath, out var sourcePosition)) { DirectionalDamageHud.ShowFromWorldPosition(__instance, sourcePosition, damageNumber); } } } internal static void OnRoundStarted() { _lastPotentialDamageSource = null; _lastPotentialDamageSourceTime = -999f; _nextFeedbackSampleTime = 0f; DirectionalDamageHud.DestroyInstance(); PlayerDangerHud.DestroyInstance(); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { _lastPotentialDamageSource = null; _lastPotentialDamageSourceTime = -999f; _nextFeedbackSampleTime = 0f; DirectionalDamageHud.DestroyInstance(); PlayerDangerHud.DestroyInstance(); } private static bool TryResolveDamageSource(PlayerControllerB player, bool fallDamage, CauseOfDeath causeOfDeath, out Vector3 sourcePosition) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) sourcePosition = Vector3.zero; if ((Object)(object)player == (Object)null || fallDamage) { return false; } EnemyAI recentPotentialDamageSource = GetRecentPotentialDamageSource(player); if ((Object)(object)recentPotentialDamageSource != (Object)null) { sourcePosition = ((Component)recentPotentialDamageSource).transform.position; return true; } if (!LooksLikeEnemyDamage(causeOfDeath)) { return false; } EnemyAI val = FindClosestEnemy(player); if ((Object)(object)val == (Object)null) { return false; } sourcePosition = ((Component)val).transform.position; return true; } private static EnemyAI GetRecentPotentialDamageSource(PlayerControllerB player) { //IL_0037: 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) if ((Object)(object)_lastPotentialDamageSource == (Object)null) { return null; } if (_lastPotentialDamageSource.isEnemyDead) { return null; } if (Time.time - _lastPotentialDamageSourceTime > 1.25f) { return null; } if (Vector3.Distance(((Component)player).transform.position, ((Component)_lastPotentialDamageSource).transform.position) > 26f) { return null; } return _lastPotentialDamageSource; } private static EnemyAI FindClosestEnemy(PlayerControllerB player) { //IL_0030: 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) EnemyAI result = null; float num = 18f; EnemyAI[] array = Object.FindObjectsOfType(); foreach (EnemyAI val in array) { if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { float num2 = Vector3.Distance(((Component)player).transform.position, ((Component)val).transform.position); if (!(num2 >= num)) { result = val; num = num2; } } } return result; } private static bool LooksLikeEnemyDamage(CauseOfDeath cause) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected I4, but got Unknown switch ((int)cause) { case 0: case 1: case 4: case 5: case 6: case 8: case 12: case 14: return true; default: return false; } } } [HarmonyPatch] internal static class HeldItemStowPatches { private const string SpecialInteractReason = "special-interact"; private static readonly Dictionary SpecialInteractState = new Dictionary(); [HarmonyPatch(typeof(PlayerControllerB), "Update")] [HarmonyPostfix] private static void PostPlayerUpdate(PlayerControllerB __instance) { if ((Object)(object)__instance == (Object)null) { return; } bool flag = __instance.inSpecialInteractAnimation || __instance.isClimbingLadder; SpecialInteractState.TryGetValue(__instance, out var value); if (flag != value) { SpecialInteractState[__instance] = flag; if (flag) { HeldItemStowService.Begin(__instance, "special-interact"); } else { HeldItemStowService.End(__instance, "special-interact"); } } } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static void PreKillPlayer(PlayerControllerB __instance) { HeldItemStowService.Clear(__instance); if ((Object)(object)__instance != (Object)null) { SpecialInteractState.Remove(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "DropAllHeldItems")] [HarmonyPrefix] private static void PreDropAllHeldItems(PlayerControllerB __instance) { HeldItemStowService.Clear(__instance); } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { HeldItemStowService.AbortAll("round-end"); SpecialInteractState.Clear(); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void PostDisconnect() { HeldItemStowService.AbortAll("disconnect"); SpecialInteractState.Clear(); } } [HarmonyPatch] internal static class LadderStowSequencePatches { internal sealed class TwoHandedRelaxScope : IDisposable { private readonly PlayerControllerB _player; private bool _disposed; internal TwoHandedRelaxScope(PlayerControllerB player) { _player = player; _relaxedPlayer = player; _relaxedOriginalTwoHanded = player.twoHanded; _player.twoHanded = false; _relaxingTwoHandedGate = true; } public void Dispose() { if (!_disposed) { _disposed = true; _relaxingTwoHandedGate = false; _relaxedPlayer = null; _relaxedOriginalTwoHanded = false; if (!((Object)(object)_player == (Object)null)) { GrabbableObject currentlyHeldObjectServer = _player.currentlyHeldObjectServer; _player.twoHanded = (Object)(object)currentlyHeldObjectServer != (Object)null && (Object)(object)currentlyHeldObjectServer.itemProperties != (Object)null && currentlyHeldObjectServer.itemProperties.twoHanded; } } } } private const string SpecialInteractReason = "special-interact"; private const float StowSeconds = 0.28f; private const float StowTimeoutSeconds = 6f; private const float MaxLadderHorizontalDistance = 8f; private const string HandsFullTip = "[Hands full]"; private const float PendingStaleSlackSeconds = 2f; private static bool _relaxingTwoHandedGate; private static PlayerControllerB _relaxedPlayer; private static bool _relaxedOriginalTwoHanded; private static bool _replayingLadderInteract; private static Coroutine _pendingRoutine; private static PlayerControllerB _pendingPlayer; private static InteractTrigger _pendingTrigger; private static long _pendingToken; private static float _pendingStartedAtRealtime; [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")] [HarmonyPrefix] private static void RelaxLadderGateForTapPrefix(PlayerControllerB __instance, out TwoHandedRelaxScope __state) { __state = BeginRelaxScope(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "Interact_performed")] [HarmonyFinalizer] private static Exception RelaxLadderGateForTapFinalizer(Exception __exception, TwoHandedRelaxScope __state) { __state?.Dispose(); return __exception; } [HarmonyPatch(typeof(PlayerControllerB), "ClickHoldInteraction")] [HarmonyPrefix] private static void RelaxLadderGateForHoldPrefix(PlayerControllerB __instance, out TwoHandedRelaxScope __state) { __state = BeginRelaxScope(__instance); } [HarmonyPatch(typeof(PlayerControllerB), "ClickHoldInteraction")] [HarmonyFinalizer] private static Exception RelaxLadderGateForHoldFinalizer(Exception __exception, TwoHandedRelaxScope __state) { __state?.Dispose(); return __exception; } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyPrefix] [HarmonyPriority(800)] private static void RestoreTwoHandedForGrabPrefix(PlayerControllerB __instance, out bool __state) { __state = false; if (_relaxingTwoHandedGate && !((Object)(object)__instance == (Object)null) && !__instance.twoHanded) { GrabbableObject currentlyHeldObjectServer = __instance.currentlyHeldObjectServer; if (!((Object)(object)currentlyHeldObjectServer == (Object)null) && !((Object)(object)currentlyHeldObjectServer.itemProperties == (Object)null) && currentlyHeldObjectServer.itemProperties.twoHanded) { __instance.twoHanded = true; __state = true; } } } [HarmonyPatch(typeof(PlayerControllerB), "BeginGrabObject")] [HarmonyFinalizer] [HarmonyPriority(0)] private static Exception RestoreTwoHandedForGrabFinalizer(Exception __exception, PlayerControllerB __instance, bool __state) { if (__state && (Object)(object)__instance != (Object)null) { __instance.twoHanded = false; } return __exception; } [HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")] [HarmonyPostfix] private static void RepairLadderHoverTipPostfix(PlayerControllerB __instance) { if (CanRelaxLadderGate(__instance) && !((Object)(object)__instance.cursorTip == (Object)null) && string.Equals(((TMP_Text)__instance.cursorTip).text, "[Hands full]", StringComparison.Ordinal)) { InteractTrigger hoveringOverTrigger = __instance.hoveringOverTrigger; ((TMP_Text)__instance.cursorTip).text = (string.IsNullOrEmpty(hoveringOverTrigger.holdTip) ? hoveringOverTrigger.hoverTip : hoveringOverTrigger.holdTip); } } [HarmonyPatch(typeof(InteractTrigger), "Interact")] [HarmonyPrefix] private static bool StowBeforeLadderPrefix(InteractTrigger __instance, Transform playerTransform) { if (_replayingLadderInteract) { return true; } if ((Object)(object)__instance == (Object)null || !__instance.isLadder || !__instance.interactable) { return true; } if (__instance.usingLadder || __instance.isPlayingSpecialAnimation) { return true; } if ((Object)(object)playerTransform == (Object)null) { return true; } PlayerControllerB component = ((Component)playerTransform).GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return true; } if (component.isPlayerDead || component.inSpecialInteractAnimation || component.isClimbingLadder) { return true; } if (_pendingRoutine != null && !TryReapStrandedPending()) { return false; } if (HeldItemStowService.IsStowed(component)) { return true; } GrabbableObject currentlyHeldObjectServer = component.currentlyHeldObjectServer; if ((Object)(object)currentlyHeldObjectServer == (Object)null) { return true; } if (!HeldItemStowService.ShouldStow(currentlyHeldObjectServer) && !WasTwoHandedBeforeRelax(component)) { return true; } HeldItemStowHandle heldItemStowHandle = HeldItemStowService.Begin(component, "special-interact", 6f, disableItemActions: true, force: true); if (!heldItemStowHandle.IsActive) { return true; } _pendingPlayer = component; _pendingTrigger = __instance; _pendingToken = heldItemStowHandle.Token; _pendingStartedAtRealtime = Time.realtimeSinceStartup; _pendingRoutine = Y4NGZPersistentRunner.Run(StartLadderAfterStow(component, __instance, heldItemStowHandle.Token)); if (_pendingRoutine == null) { ClearPending(); HeldItemStowService.Release(component, heldItemStowHandle.Token); return true; } ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Ladder] stow-first sequence armed on '" + ((Object)((Component)__instance).gameObject).name + "'; climb starts in " + 0.28f.ToString("0.00") + "s.")); } return false; } private static IEnumerator StartLadderAfterStow(PlayerControllerB player, InteractTrigger trigger, long stowToken) { yield return (object)new WaitForSeconds(0.28f); ClearPending(); if (!IsLadderStartStillValid(player, trigger)) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)"[Ladder] stow-first sequence aborted before the climb; restoring item."); } HeldItemStowService.Release(player, stowToken); yield break; } _replayingLadderInteract = true; try { trigger.Interact(player.thisPlayerBody); } catch (Exception ex) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Ladder] deferred climb start threw safely: " + ex.Message)); } } finally { _replayingLadderInteract = false; } if (!player.inSpecialInteractAnimation && !player.isClimbingLadder) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogInfo((object)"[Ladder] deferred climb declined by vanilla; restoring item."); } HeldItemStowService.Release(player, stowToken); } } private static bool TryReapStrandedPending() { if (Time.realtimeSinceStartup - _pendingStartedAtRealtime <= 2.28f) { return false; } PlayerControllerB pendingPlayer = _pendingPlayer; long pendingToken = _pendingToken; string text = (((Object)(object)_pendingTrigger != (Object)null) ? ((Object)((Component)_pendingTrigger).gameObject).name : "unknown"); ClearPending(); if (pendingToken != 0L && HeldItemStowService.IsTokenLive(pendingPlayer, pendingToken)) { HeldItemStowService.Release(pendingPlayer, pendingToken); } ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Ladder] pending stow-first sequence on '" + text + "' was stranded (its host went away mid lead-in); reaped it and letting this interact through.")); } return true; } private static bool IsLadderStartStillValid(PlayerControllerB player, InteractTrigger trigger) { //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: 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_00f9: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || (Object)(object)trigger == (Object)null) { return false; } if (player.isPlayerDead || !player.isPlayerControlled || (Object)(object)player.thisPlayerBody == (Object)null) { return false; } if (player.inSpecialInteractAnimation || player.isClimbingLadder || player.isInHangarShipRoom) { return false; } if ((Object)(object)player.inAnimationWithEnemy != (Object)null) { return false; } if ((Object)(object)((Component)trigger).gameObject == (Object)null || !((Component)trigger).gameObject.activeInHierarchy) { return false; } if (!trigger.interactable || trigger.usingLadder || trigger.isPlayingSpecialAnimation) { return false; } if ((Object)(object)trigger.ladderPlayerPositionNode == (Object)null || (Object)(object)trigger.ladderHorizontalPosition == (Object)null || (Object)(object)trigger.bottomOfLadderPosition == (Object)null || (Object)(object)trigger.topOfLadderPosition == (Object)null) { return false; } Vector3 position = player.thisPlayerBody.position; Vector3 position2 = trigger.ladderHorizontalPosition.position; float num = position.x - position2.x; float num2 = position.z - position2.z; return num * num + num2 * num2 <= 64f; } [HarmonyPatch(typeof(PlayerControllerB), "KillPlayer")] [HarmonyPrefix] private static void CancelPendingOnDeath(PlayerControllerB __instance) { if ((Object)(object)__instance != (Object)null && (Object)(object)__instance == (Object)(object)_pendingPlayer) { CancelPendingSequence("death"); } } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void CancelPendingOnRoundEnd() { CancelPendingSequence("round-end"); } [HarmonyPatch(typeof(GameNetworkManager), "Disconnect")] [HarmonyPostfix] private static void CancelPendingOnDisconnect() { CancelPendingSequence("disconnect"); } private static void CancelPendingSequence(string reason) { if (_pendingRoutine != null) { Y4NGZPersistentRunner.Stop(_pendingRoutine); _relaxingTwoHandedGate = false; _replayingLadderInteract = false; string text = (((Object)(object)_pendingTrigger != (Object)null) ? ((Object)((Component)_pendingTrigger).gameObject).name : "unknown"); ClearPending(); ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Ladder] pending stow-first sequence on '" + text + "' cancelled: " + reason)); } } } private static void ClearPending() { _pendingRoutine = null; _pendingPlayer = null; _pendingTrigger = null; _pendingToken = 0L; _pendingStartedAtRealtime = 0f; } private static bool WasTwoHandedBeforeRelax(PlayerControllerB player) { if ((Object)(object)player == (Object)null) { return false; } if (player.twoHanded) { return true; } if (_relaxingTwoHandedGate && (Object)(object)_relaxedPlayer == (Object)(object)player) { return _relaxedOriginalTwoHanded; } return false; } private static TwoHandedRelaxScope BeginRelaxScope(PlayerControllerB player) { if (!CanRelaxLadderGate(player)) { return null; } return new TwoHandedRelaxScope(player); } private static bool CanRelaxLadderGate(PlayerControllerB player) { if ((Object)(object)player == (Object)null || !player.twoHanded) { return false; } if ((Object)(object)player != (Object)(object)GameNetworkManager.Instance?.localPlayerController) { return false; } if (player.isPlayerDead || player.isClimbingLadder) { return false; } InteractTrigger hoveringOverTrigger = player.hoveringOverTrigger; if ((Object)(object)hoveringOverTrigger != (Object)null && hoveringOverTrigger.isLadder && hoveringOverTrigger.interactable) { return !hoveringOverTrigger.twoHandedItemAllowed; } return false; } } [HarmonyPatch] internal static class WorldFeedbackPatch { private const int HighValueScrapThreshold = 80; private const float NearMissSampleInterval = 0.1f; private static float _nextNearMissSampleTime; [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] [HarmonyPostfix] private static void PostPlayerLateUpdate(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && !(Time.unscaledTime < _nextNearMissSampleTime)) { _nextNearMissSampleTime = Time.unscaledTime + 0.1f; NearMissFeedback.Update(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "DamagePlayer")] [HarmonyPostfix] private static void PostDamagePlayer(PlayerControllerB __instance, int damageNumber) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController) && damageNumber > 0) { NearMissFeedback.NoteDamage(); } } [HarmonyPatch(typeof(GrabbableObject), "Start")] [HarmonyPostfix] private static void PostGrabbableStart(GrabbableObject __instance) { HighValueScrapGlint.Ensure(__instance, 80); } [HarmonyPatch(typeof(GrabbableObject), "SetScrapValue")] [HarmonyPostfix] private static void PostSetScrapValue(GrabbableObject __instance) { HighValueScrapGlint.Ensure(__instance, 80); } [HarmonyPatch(typeof(HUDManager), "UpdateWeightCounter")] [HarmonyPostfix] private static void PostUpdateWeightCounter(HUDManager __instance) { ScrapPickupFeedback.PulseWeightCounter(__instance); } [HarmonyPatch(typeof(HUDManager), "DisplayNewScrapFound")] [HarmonyPrefix] private static void PreDisplayNewScrapFound(HUDManager __instance, ref GrabbableObject __state) { __state = (((Object)(object)__instance != (Object)null && __instance.itemsToBeDisplayed != null && __instance.itemsToBeDisplayed.Count > 0) ? __instance.itemsToBeDisplayed[0] : null); } [HarmonyPatch(typeof(HUDManager), "DisplayNewScrapFound")] [HarmonyPostfix] private static void PostDisplayNewScrapFound(HUDManager __instance, GrabbableObject __state, int ___bottomBoxIndex) { ScrapPickupFeedback.PulseScrapDisplay(__instance, __state, ___bottomBoxIndex); } [HarmonyPatch(typeof(HUDManager), "UpdateScanNodes")] [HarmonyPostfix] private static void PostUpdateScanNodes(HUDManager __instance) { ScanFeedback.EnsureFadeDrivers(__instance); } [HarmonyPatch(typeof(HUDManager), "PingScan_performed")] [HarmonyPostfix] private static void PostPingScan(HUDManager __instance, float ___playerPingingScan) { if (!(___playerPingingScan < 0.2f)) { ScanFeedback.PlayScanAccent(__instance); } } internal static void OnRoundStarted() { HighValueScrapGlint.Reset(); ScanFeedback.Reset(); NearMissFeedback.Reset(); _nextNearMissSampleTime = 0f; } [HarmonyPatch(typeof(StartOfRound), "EndOfGame")] [HarmonyPostfix] private static void PostEndOfGame() { HighValueScrapGlint.Reset(); ScanFeedback.Reset(); NearMissFeedback.Reset(); _nextNearMissSampleTime = 0f; } } internal static class HighValueScrapGlint { private static readonly List Candidates = new List(); private static HighValueScrapGlintDriver _driver; internal static void Ensure(GrabbableObject item, int valueThreshold) { ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled != null && !worldFeedbackEnabled.Value) { return; } ConfigEntry worldFeedbackHighValueGlintEnabled = Plugin.WorldFeedbackHighValueGlintEnabled; if ((worldFeedbackHighValueGlintEnabled == null || worldFeedbackHighValueGlintEnabled.Value) && !((Object)(object)item == (Object)null) && !((Object)(object)item.itemProperties == (Object)null) && item.itemProperties.isScrap && item.scrapValue >= valueThreshold) { if (!Candidates.Contains(item)) { Candidates.Add(item); } EnsureDriver(); } } internal static void Reset() { Candidates.Clear(); if ((Object)(object)_driver != (Object)null) { _driver.ClearTarget(); } } internal static GrabbableObject FindNearestCandidate(PlayerControllerB player, float maxDistance) { //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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_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) if ((Object)(object)player == (Object)null) { return null; } Vector3 position = ((Component)player).transform.position; float num = maxDistance * maxDistance; GrabbableObject result = null; for (int num2 = Candidates.Count - 1; num2 >= 0; num2--) { GrabbableObject val = Candidates[num2]; if (!IsValidCandidate(val)) { Candidates.RemoveAt(num2); } else { Vector3 val2 = ((Component)val).transform.position - position; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (!(sqrMagnitude > num)) { result = val; num = sqrMagnitude; } } } return result; } private static void EnsureDriver() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if (!((Object)(object)_driver != (Object)null)) { GameObject val = new GameObject("Y4NGZ_HighValueScrapGlintDriver"); Object.DontDestroyOnLoad((Object)val); _driver = val.AddComponent(); } } private static bool IsValidCandidate(GrabbableObject item) { if ((Object)(object)item != (Object)null && (Object)(object)item.itemProperties != (Object)null && item.itemProperties.isScrap && item.scrapValue >= 80 && !item.isHeld && !item.isPocketed) { return !item.isHeldByEnemy; } return false; } } internal sealed class HighValueScrapGlintDriver : MonoBehaviour { private const float CheckInterval = 0.35f; private const float MaxDistance = 18f; private Light _light; private GrabbableObject _target; private Renderer _targetRenderer; private float _nextCheckTime; private float _nextPulseTime; private float _pulseStartTime = -999f; private float _pulseDuration = 0.38f; private void Awake() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Expected O, but got Unknown //IL_004a: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Y4NGZ_HighValueScrapGlintLight"); val.transform.SetParent(((Component)this).transform, false); _light = val.AddComponent(); _light.type = (LightType)2; _light.color = new Color(1f, 0.78f, 0.48f); _light.range = 0.85f; _light.intensity = 0f; ((Behaviour)_light).enabled = false; _light.shadows = (LightShadows)0; ScheduleNextPulse(); } private void Update() { ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled == null || worldFeedbackEnabled.Value) { ConfigEntry worldFeedbackHighValueGlintEnabled = Plugin.WorldFeedbackHighValueGlintEnabled; if (worldFeedbackHighValueGlintEnabled == null || worldFeedbackHighValueGlintEnabled.Value) { if (Time.time >= _nextCheckTime) { _nextCheckTime = Time.time + 0.35f; PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || val.isPlayerDead) { ClearTarget(); return; } GrabbableObject val2 = HighValueScrapGlint.FindNearestCandidate(val, 18f); if ((Object)(object)val2 != (Object)(object)_target) { _target = val2; _targetRenderer = (((Object)(object)_target != (Object)null) ? ((Component)_target).GetComponentInChildren(false) : null); } } UpdateLightPulse(); return; } } ClearTarget(); } internal void ClearTarget() { _target = null; _targetRenderer = null; if ((Object)(object)_light != (Object)null) { _light.intensity = 0f; ((Behaviour)_light).enabled = false; } } private void UpdateLightPulse() { //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_006f: 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_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_target == (Object)null || (Object)(object)_light == (Object)null) { if ((Object)(object)_light != (Object)null) { ((Behaviour)_light).enabled = false; } return; } if ((Object)(object)_targetRenderer != (Object)null) { Bounds bounds = _targetRenderer.bounds; ((Component)_light).transform.position = ((Bounds)(ref bounds)).center + Vector3.up * Mathf.Min(0.18f, ((Bounds)(ref bounds)).extents.y * 0.35f); } else { ((Component)_light).transform.position = ((Component)_target).transform.position + Vector3.up * 0.15f; } if (Time.time >= _nextPulseTime) { _pulseStartTime = Time.time; _pulseDuration = Random.Range(0.28f, 0.42f); ScheduleNextPulse(); } float num = Mathf.Clamp01((Time.time - _pulseStartTime) / _pulseDuration); float num2 = ((num < 1f) ? Mathf.Sin(num * MathF.PI) : 0f); float num3 = Mathf.Clamp((float)_target.scrapValue / 145f, 0.45f, 1f); float num4 = num2 * Mathf.Lerp(0.12f, 0.3f, num3); _light.intensity = num4; ((Behaviour)_light).enabled = num4 > 0.01f; } private void ScheduleNextPulse() { _nextPulseTime = Time.time + Random.Range(3.8f, 7.8f); } } internal static class ScrapPickupFeedback { private static float _lastWeightPulseTime = -999f; internal static void PulseWeightCounter(HUDManager hud) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled == null || worldFeedbackEnabled.Value) { ConfigEntry worldFeedbackScrapPickupEnabled = Plugin.WorldFeedbackScrapPickupEnabled; if ((worldFeedbackScrapPickupEnabled == null || worldFeedbackScrapPickupEnabled.Value) && !((Object)(object)hud == (Object)null) && !((Object)(object)hud.weightCounter == (Object)null) && !(Time.unscaledTime - _lastWeightPulseTime < 0.18f)) { _lastWeightPulseTime = Time.unscaledTime; HudPulseDriver.Play(((Component)hud.weightCounter).gameObject, 0.08f, 0.22f, new Color(1f, 0.78f, 0.35f, 1f)); } } } internal static void PulseScrapDisplay(HUDManager hud, GrabbableObject item, int displayedBoxIndex) { //IL_00b5: 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_00ba: 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_0105: Unknown result type (might be due to invalid IL or missing references) ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled != null && !worldFeedbackEnabled.Value) { return; } ConfigEntry worldFeedbackScrapPickupEnabled = Plugin.WorldFeedbackScrapPickupEnabled; if ((worldFeedbackScrapPickupEnabled != null && !worldFeedbackScrapPickupEnabled.Value) || (Object)(object)hud == (Object)null || (Object)(object)item == (Object)null || hud.ScrapItemBoxes == null || displayedBoxIndex < 0 || displayedBoxIndex >= hud.ScrapItemBoxes.Length) { return; } ScrapItemHUDDisplay val = hud.ScrapItemBoxes[displayedBoxIndex]; if (val != null) { float num = ((item.scrapValue >= 80) ? 0.1f : 0.06f); Color flashColor = ((item.scrapValue >= 80) ? new Color(1f, 0.78f, 0.35f, 1f) : new Color(0.78f, 0.96f, 1f, 1f)); if ((Object)(object)val.valueText != (Object)null) { HudPulseDriver.Play(((Component)val.valueText).gameObject, num, 0.26f, flashColor); } if ((Object)(object)val.UIContainer != (Object)null) { HudPulseDriver.Play(((Component)val.UIContainer).gameObject, num * 0.45f, 0.24f, flashColor); } } } } internal sealed class HudPulseDriver : MonoBehaviour { private RectTransform _rect; private Graphic _graphic; private Vector3 _baseScale; private Color _baseColor; private Color _flashColor; private float _scaleBump; private float _duration; private float _startTime; internal static void Play(GameObject target, float scaleBump, float duration, Color flashColor) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null)) { HudPulseDriver hudPulseDriver = target.GetComponent(); if ((Object)(object)hudPulseDriver == (Object)null) { hudPulseDriver = target.AddComponent(); } hudPulseDriver.Restart(scaleBump, duration, flashColor); } } private void Awake() { //IL_003a: 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_003f: 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_0053: 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) _rect = ((Component)this).GetComponent(); _graphic = ((Component)this).GetComponent(); _baseScale = (((Object)(object)_rect != (Object)null) ? ((Transform)_rect).localScale : ((Component)this).transform.localScale); _baseColor = (((Object)(object)_graphic != (Object)null) ? _graphic.color : Color.white); } private void Restart(float scaleBump, float duration, Color flashColor) { //IL_0056: 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_005b: 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_006f: 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_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rect == (Object)null) { _rect = ((Component)this).GetComponent(); } if ((Object)(object)_graphic == (Object)null) { _graphic = ((Component)this).GetComponent(); } _baseScale = (((Object)(object)_rect != (Object)null) ? ((Transform)_rect).localScale : ((Component)this).transform.localScale); _baseColor = (((Object)(object)_graphic != (Object)null) ? _graphic.color : Color.white); _scaleBump = scaleBump; _duration = Mathf.Max(0.05f, duration); _flashColor = flashColor; _startTime = Time.unscaledTime; ((Behaviour)this).enabled = true; } private void Update() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: 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_00b5: 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) float num = Mathf.Clamp01((Time.unscaledTime - _startTime) / _duration); float num2 = Mathf.Sin(num * MathF.PI); Vector3 localScale = _baseScale * (1f + num2 * _scaleBump); if ((Object)(object)_rect != (Object)null) { ((Transform)_rect).localScale = localScale; } else { ((Component)this).transform.localScale = localScale; } if ((Object)(object)_graphic != (Object)null) { _graphic.color = Color.Lerp(_baseColor, _flashColor, num2 * 0.35f); } if (!(num < 1f)) { if ((Object)(object)_rect != (Object)null) { ((Transform)_rect).localScale = _baseScale; } else { ((Component)this).transform.localScale = _baseScale; } if ((Object)(object)_graphic != (Object)null) { _graphic.color = _baseColor; } ((Behaviour)this).enabled = false; } } } internal sealed class ScanNodeFade : MonoBehaviour { private CanvasGroup _group; private float _startTime; private void Awake() { _group = ((Component)this).GetComponent(); if ((Object)(object)_group == (Object)null) { _group = ((Component)this).gameObject.AddComponent(); } } private void OnEnable() { if ((Object)(object)_group == (Object)null) { _group = ((Component)this).GetComponent(); } _startTime = Time.unscaledTime; if ((Object)(object)_group != (Object)null) { _group.alpha = 0f; } } private void Update() { ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled == null || worldFeedbackEnabled.Value) { ConfigEntry worldFeedbackScanEnhancementsEnabled = Plugin.WorldFeedbackScanEnhancementsEnabled; if (worldFeedbackScanEnhancementsEnabled == null || worldFeedbackScanEnhancementsEnabled.Value) { if (!((Object)(object)_group == (Object)null)) { float num = Mathf.Clamp01((Time.unscaledTime - _startTime) / 0.18f); _group.alpha = Mathf.SmoothStep(0f, 1f, num); } return; } } if ((Object)(object)_group != (Object)null) { _group.alpha = 1f; } } } internal static class ScanFeedback { private enum ScanCategory { Generic, Scrap, Creature } private static readonly RaycastHit[] ScanHits = (RaycastHit[])(object)new RaycastHit[32]; private static AudioClip _scrapScanClip; private static AudioClip _creatureScanClip; private static AudioClip _genericScanClip; private static int _fadeDriversHudId = -1; internal static void Reset() { _fadeDriversHudId = -1; } internal static void EnsureFadeDrivers(HUDManager hud) { ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled != null && !worldFeedbackEnabled.Value) { return; } ConfigEntry worldFeedbackScanEnhancementsEnabled = Plugin.WorldFeedbackScanEnhancementsEnabled; if ((worldFeedbackScanEnhancementsEnabled != null && !worldFeedbackScanEnhancementsEnabled.Value) || (Object)(object)hud == (Object)null || hud.scanElements == null) { return; } int instanceID = ((Object)hud).GetInstanceID(); if (_fadeDriversHudId == instanceID) { return; } for (int i = 0; i < hud.scanElements.Length; i++) { RectTransform val = hud.scanElements[i]; if (!((Object)(object)val == (Object)null) && (Object)(object)((Component)val).GetComponent() == (Object)null) { ((Component)val).gameObject.AddComponent(); } } _fadeDriversHudId = instanceID; } internal static void PlayScanAccent(HUDManager hud) { ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled != null && !worldFeedbackEnabled.Value) { return; } ConfigEntry worldFeedbackScanEnhancementsEnabled = Plugin.WorldFeedbackScanEnhancementsEnabled; if ((worldFeedbackScanEnhancementsEnabled == null || worldFeedbackScanEnhancementsEnabled.Value) && !((Object)(object)hud == (Object)null) && !((Object)(object)hud.UIAudio == (Object)null)) { switch (ResolveDominantCategory()) { case ScanCategory.Creature: hud.UIAudio.PlayOneShot(GetCreatureScanClip(), 0.11f); break; case ScanCategory.Scrap: hud.UIAudio.PlayOneShot(GetScrapScanClip(), 0.12f); break; default: hud.UIAudio.PlayOneShot(GetGenericScanClip(), 0.08f); break; } } } private static ScanCategory ResolveDominantCategory() { //IL_0038: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || (Object)(object)val.gameplayCamera == (Object)null) { return ScanCategory.Generic; } Transform transform = ((Component)val.gameplayCamera).transform; int num = Physics.SphereCastNonAlloc(new Ray(transform.position + transform.forward * 20f, transform.forward), 20f, ScanHits, 80f, 4194304); bool flag = false; for (int i = 0; i < num && i < ScanHits.Length; i++) { ScanNodeProperties val2 = (((Object)(object)((RaycastHit)(ref ScanHits[i])).transform != (Object)null) ? ((Component)((RaycastHit)(ref ScanHits[i])).transform).GetComponent() : null); if (!((Object)(object)val2 == (Object)null)) { if (val2.creatureScanID != -1 || val2.nodeType == 1) { return ScanCategory.Creature; } if (val2.nodeType == 2) { flag = true; } } } if (!flag) { return ScanCategory.Generic; } return ScanCategory.Scrap; } private static AudioClip GetScrapScanClip() { if ((Object)(object)_scrapScanClip != (Object)null) { return _scrapScanClip; } _scrapScanClip = MakeToneClip("Y4NGZ_ScanScrapAccent", 1320f, 1760f, 0.055f, 0.32f); return _scrapScanClip; } private static AudioClip GetCreatureScanClip() { if ((Object)(object)_creatureScanClip != (Object)null) { return _creatureScanClip; } _creatureScanClip = MakeToneClip("Y4NGZ_ScanCreatureAccent", 520f, 390f, 0.075f, 0.4f); return _creatureScanClip; } private static AudioClip GetGenericScanClip() { if ((Object)(object)_genericScanClip != (Object)null) { return _genericScanClip; } _genericScanClip = MakeToneClip("Y4NGZ_ScanGenericAccent", 900f, 980f, 0.045f, 0.24f); return _genericScanClip; } private static AudioClip MakeToneClip(string name, float startHz, float endHz, float duration, float gain) { int num = Mathf.CeilToInt(44100f * duration); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 44100f; float num3 = Mathf.Clamp01(num2 / duration); float num4 = Mathf.Lerp(startHz, endHz, num3); float num5 = Mathf.Sin(num3 * MathF.PI); array[i] = Mathf.Sin(MathF.PI * 2f * num4 * num2) * num5 * gain; } AudioClip obj = AudioClip.Create(name, num, 1, 44100, false); obj.SetData(array, 0); ((Object)obj).hideFlags = (HideFlags)61; return obj; } } internal static class NearMissFeedback { private const float MinDistance = 0.85f; private const float MaxDistance = 2.55f; private const float MinApproachSpeed = 1.15f; private const float GlobalCooldown = 1.4f; private const float EvaluationInterval = 0.12f; private const float EnemyCacheRefreshInterval = 0.85f; private const float MinDistanceSqr = 0.7225f; private const float MaxDistanceSqr = 6.5024996f; private static readonly List CachedEnemies = new List(); private static readonly Dictionary LastPositions = new Dictionary(); private static float _lastWhooshTime = -999f; private static float _lastDamageTime = -999f; private static float _nextEvaluationTime; private static float _nextEnemyCacheRefreshTime; private static AudioClip _whooshClip; internal static void Update(PlayerControllerB player) { //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_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: 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_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_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_0147: 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_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015e: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0192: Unknown result type (might be due to invalid IL or missing references) //IL_0197: Unknown result type (might be due to invalid IL or missing references) //IL_01af: Unknown result type (might be due to invalid IL or missing references) ConfigEntry worldFeedbackEnabled = Plugin.WorldFeedbackEnabled; if (worldFeedbackEnabled != null && !worldFeedbackEnabled.Value) { return; } ConfigEntry worldFeedbackNearMissWhooshEnabled = Plugin.WorldFeedbackNearMissWhooshEnabled; if (worldFeedbackNearMissWhooshEnabled == null || !worldFeedbackNearMissWhooshEnabled.Value || (Object)(object)player == (Object)null || player.isPlayerDead || (Object)(object)player.gameplayCamera == (Object)null || Time.time - _lastWhooshTime < 1.4f || Time.time - _lastDamageTime < 0.55f || Time.time < _nextEvaluationTime) { return; } _nextEvaluationTime = Time.time + 0.12f; RefreshEnemyCache(); if (CachedEnemies.Count == 0) { return; } Vector3 position = ((Component)player).transform.position; for (int num = CachedEnemies.Count - 1; num >= 0; num--) { EnemyAI val = CachedEnemies[num]; if ((Object)(object)val == (Object)null || val.isEnemyDead) { CachedEnemies.RemoveAt(num); } else if (LooksThreatening(val, player)) { Vector3 position2 = ((Component)val).transform.position; Vector3 val2 = position - position2; float sqrMagnitude = ((Vector3)(ref val2)).sqrMagnitude; if (sqrMagnitude < 0.7225f || sqrMagnitude > 6.5024996f) { LastPositions[val] = position2; } else { Vector3 val3 = ResolveVelocity(val, position2); LastPositions[val] = position2; val2 = ((Component)player).transform.position - position2; Vector3 normalized = ((Vector3)(ref val2)).normalized; if (!(Vector3.Dot(val3, normalized) < 1.15f) && !Physics.Linecast(((Component)player.gameplayCamera).transform.position, position2 + Vector3.up * 0.6f, StartOfRound.Instance.collidersAndRoomMaskAndDefault, (QueryTriggerInteraction)1)) { PlayWhoosh(player, position2, Mathf.Sqrt(sqrMagnitude)); _lastWhooshTime = Time.time; break; } } } } } internal static void NoteDamage() { _lastDamageTime = Time.time; } internal static void Reset() { CachedEnemies.Clear(); LastPositions.Clear(); _lastWhooshTime = -999f; _lastDamageTime = -999f; _nextEvaluationTime = 0f; _nextEnemyCacheRefreshTime = 0f; } private static void RefreshEnemyCache() { if (Time.time < _nextEnemyCacheRefreshTime) { return; } _nextEnemyCacheRefreshTime = Time.time + 0.85f; CachedEnemies.Clear(); if ((Object)(object)RoundManager.Instance != (Object)null && RoundManager.Instance.SpawnedEnemies != null) { List spawnedEnemies = RoundManager.Instance.SpawnedEnemies; for (int i = 0; i < spawnedEnemies.Count; i++) { EnemyAI val = spawnedEnemies[i]; if (!((Object)(object)val == (Object)null) && !val.isEnemyDead) { CachedEnemies.Add(val); } } return; } EnemyAI[] array = Object.FindObjectsOfType(); foreach (EnemyAI val2 in array) { if (!((Object)(object)val2 == (Object)null) && !val2.isEnemyDead) { CachedEnemies.Add(val2); } } } private static bool LooksThreatening(EnemyAI enemy, PlayerControllerB player) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy.targetPlayer == (Object)(object)player) { return true; } if (enemy.movingTowardsTargetPlayer && (Object)(object)enemy.targetPlayer == (Object)null) { return true; } if (enemy.currentBehaviourStateIndex > 0) { Vector3 val = ((Component)enemy).transform.position - ((Component)player).transform.position; return ((Vector3)(ref val)).sqrMagnitude < 6.5024996f; } return false; } private static Vector3 ResolveVelocity(EnemyAI enemy, Vector3 currentPosition) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0062: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy.agent != (Object)null && ((Behaviour)enemy.agent).enabled) { Vector3 velocity = enemy.agent.velocity; if (((Vector3)(ref velocity)).sqrMagnitude > 0.01f) { return velocity; } } if (!LastPositions.TryGetValue(enemy, out var value)) { return Vector3.zero; } return (currentPosition - value) / Mathf.Max(0.001f, Time.deltaTime); } private static void PlayWhoosh(PlayerControllerB player, Vector3 enemyPosition, float distance) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) AudioSource component = ((Component)player.gameplayCamera).GetComponent(); float num = Mathf.Lerp(0.18f, 0.08f, Mathf.InverseLerp(0.85f, 2.55f, distance)); if ((Object)(object)component != (Object)null) { component.PlayOneShot(GetWhooshClip(), num); } else { AudioSource.PlayClipAtPoint(GetWhooshClip(), enemyPosition, num); } } private static AudioClip GetWhooshClip() { if ((Object)(object)_whooshClip != (Object)null) { return _whooshClip; } int num = Mathf.CeilToInt(7938.0005f); float[] array = new float[num]; Random random = new Random(9142); float num2 = 0f; for (int i = 0; i < num; i++) { float num3 = (float)i / 44100f; float num4 = Mathf.Clamp01(num3 / 0.18f); float num5 = (float)(random.NextDouble() * 2.0 - 1.0); num2 = Mathf.Lerp(num2, num5, 0.18f); float num6 = Mathf.Sin(MathF.PI * 2f * Mathf.Lerp(260f, 90f, num4) * num3) * 0.18f; float num7 = Mathf.Sin(num4 * MathF.PI); array[i] = (num2 * 0.45f + num6) * num7; } _whooshClip = AudioClip.Create("Y4NGZ_NearMissWhoosh", num, 1, 44100, false); _whooshClip.SetData(array, 0); ((Object)_whooshClip).hideFlags = (HideFlags)61; return _whooshClip; } } } namespace Y4NGZUpgrades.Interactive.Hud { internal static class Y4ngzPromptOverlay { private static readonly Vector2 PromptAnchor = new Vector2(1f, 1f); private static readonly Vector2 PromptPivot = new Vector2(1f, 1f); private const int MaxPromptLines = 12; private const float PromptRight = 24f; private const float PromptBaseTop = 224f; private const float PromptWidth = 460f; private const float PromptHeight = 26f; private const float PromptSpacing = 27f; private const float TickInterval = 0.1f; private const float InitialFadeDelay = 0.35f; private const float InitialFadeDuration = 1.65f; private const float InactivityDelay = 3f; private const float InactivityFadeDuration = 0.55f; private const float StackLayoutSmoothTime = 0.16f; private const float ExternalSourceInitialScanInterval = 0.75f; private const float ExternalSourceStableScanInterval = 5f; private const float FontFallbackScanInterval = 5f; private const string PoltergeistControllerTypeName = "Poltergeist.SpectatorCamController"; private static GameObject _promptCanvasObject; private static RectTransform _promptRoot; private static CanvasGroup _promptCanvasGroup; private static TextMeshProUGUI[] _promptLines; private static readonly List _externalPromptSources = new List(); private static readonly Dictionary _persistentPromptLines = new Dictionary(); private static readonly List _postPlayerMenuPromptKeys = new List(); private static readonly Dictionary _postPlayerMenuPromptBlocks = new Dictionary(); private static readonly string[] _cachedPromptLines = new string[12]; private static string _cursorTipOverride; private static TMP_FontAsset _fontCache; private static float _nextTickAt; private static float _nextExternalSourceScanAt; private static float _nextFontFallbackScanAt; private static int _lastPromptSignature = int.MinValue; private static int _lastSourceSignature = int.MinValue; private static int _lastActivitySignature = int.MinValue; private static bool _promptDirty = true; private static bool _activitySignatureInitialized; private static bool _wasDeadOrSpectating; private static int _externalSourceStableScans; private static bool _poltergeistControllerContractLookupAttempted; private static Type _poltergeistControllerType; private static FieldInfo _poltergeistControllerInstanceField; private static FieldInfo _poltergeistControlsTextField; private static TextMeshProUGUI _activePoltergeistPromptSource; private static HUDManager _lastStyledHud; private static TextMeshProUGUI[] _lastStyledControlTipLines; private static TextMeshProUGUI _lastStyledCursorTip; private static Color _lastStyledHudAccent; private static Color _lastStyledCursorAccent; private static int _fadeSceneHandle = -1; private static float _fadeStartedAt = -1f; private static float _lastActivityAt = -1f; private static int _heldItemInstanceId; private static GrabbableObject _heldWeapon; private static float _weaponPromptShownAt = -1f; private static bool _weaponPromptsSuppressed; private static bool _motionSubscribed; private static Vector2 _motionOffset; private static float _currentStackTop = 224f; private static float _stackTopVelocity; private static bool _stackLayoutInitialized; private static bool PoltergeistControllerContractResolved { get { if (_poltergeistControllerType != null && _poltergeistControllerInstanceField != null) { return _poltergeistControlsTextField != null; } return false; } } internal static void Apply(HUDManager hud) { if (!((Object)(object)hud == (Object)null) && hud.controlTipLines != null) { ApplyHudSourceStyleIfNeeded(hud, force: true); bool isVisible = GameplayUiVisibility.IsVisible; SetPresentationVisible(isVisible); if (isVisible) { UpdateHeldItemState(ResolveLocalPlayer()); _promptDirty = true; } } } internal static void Apply(PlayerControllerB player) { if ((Object)(object)player == (Object)null || (Object)(object)player.cursorTip == (Object)null) { return; } TextMeshProUGUI cursorTip = player.cursorTip; ApplyCursorSourceStyleIfNeeded(cursorTip, HUDManager.Instance, force: true); ((Behaviour)cursorTip).enabled = false; bool isVisible = GameplayUiVisibility.IsVisible; SetPresentationVisible(isVisible); if (isVisible) { bool flag = UpdateHeldItemState(player); string cursorText = ResolveCursorText(((TMP_Text)cursorTip).text); if (ObservePromptActivity(HUDManager.Instance, cursorText) || flag) { _promptDirty = true; RefreshPromptOverlay(cursorText); } } } internal static void RefreshTheme() { //IL_0017: 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) _lastStyledHud = null; _lastStyledControlTipLines = null; _lastStyledCursorTip = null; _lastStyledHudAccent = default(Color); _lastStyledCursorAccent = default(Color); HUDManager instance = HUDManager.Instance; ApplyHudSourceStyleIfNeeded(instance, force: true); PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val != (Object)null && (Object)(object)val.cursorTip != (Object)null) { ApplyCursorSourceStyleIfNeeded(val.cursorTip, instance, force: true); } if (_promptLines != null) { for (int i = 0; i < _promptLines.Length; i++) { if ((Object)(object)_promptLines[i] != (Object)null) { ApplyPromptLineStyleIfNeeded(_promptLines[i]); } } } _promptDirty = true; } internal static void Tick() { bool isVisible = GameplayUiVisibility.IsVisible; SetPresentationVisible(isVisible); if (!isVisible) { return; } if (Time.unscaledTime >= _nextTickAt) { _nextTickAt = Time.unscaledTime + 0.1f; string cursorText = null; PlayerControllerB val = ResolveLocalPlayer(); if ((Object)(object)val != (Object)null && (Object)(object)val.cursorTip != (Object)null) { cursorText = ResolveCursorText(((TMP_Text)val.cursorTip).text); ApplyCursorSourceStyleIfNeeded(val.cursorTip, HUDManager.Instance); if (((Behaviour)val.cursorTip).enabled) { ((Behaviour)val.cursorTip).enabled = false; } } HUDManager instance = HUDManager.Instance; ApplyHudSourceStyleIfNeeded(instance); RefreshExternalPromptSources(); UpdateHeldItemState(val); ObservePromptActivity(instance, cursorText); int num = BuildSourceSignature(instance, cursorText); if (_promptDirty || num != _lastSourceSignature) { _lastSourceSignature = num; _promptDirty = false; RefreshPromptOverlay(cursorText); } } UpdatePresentationFrame(); } internal static void SetPresentationVisible(bool visible) { bool flag = (Object)(object)_promptCanvasObject != (Object)null && _promptCanvasObject.activeSelf != visible; if (flag) { _promptCanvasObject.SetActive(visible); } if (visible && flag) { _promptDirty = true; _nextTickAt = 0f; } } private static void UpdatePresentationFrame() { bool isVisible = GameplayUiVisibility.IsVisible; SetPresentationVisible(isVisible); if (!isVisible || (Object)(object)_promptCanvasObject == (Object)null) { return; } bool flag = BeginInitialFadeForCurrentSceneIfNeeded(); UpdateStackLayoutFrame(); if (!((Object)(object)_promptCanvasGroup == (Object)null) && flag) { float num = Mathf.Clamp01(Mathf.Max(0f, Time.unscaledTime - _fadeStartedAt - 0.35f) / 1.65f); float num2 = Mathf.SmoothStep(0f, 1f, num); float num3 = ((_lastActivityAt < 0f) ? 0f : Mathf.Max(0f, Time.unscaledTime - _lastActivityAt)); if ((Object)(object)_heldWeapon != (Object)null && !_weaponPromptsSuppressed && _weaponPromptShownAt >= 0f && Time.unscaledTime - _weaponPromptShownAt >= 3f) { _weaponPromptsSuppressed = true; } float num4 = Mathf.Clamp01((num3 - 3f) / 0.55f); float num5 = 1f - Mathf.SmoothStep(0f, 1f, num4); _promptCanvasGroup.alpha = num2 * num5; } } private static bool BeginInitialFadeForCurrentSceneIfNeeded() { //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) Scene activeScene = SceneManager.GetActiveScene(); if (!((Scene)(ref activeScene)).IsValid() || !((Scene)(ref activeScene)).isLoaded || ((Scene)(ref activeScene)).name != "SampleSceneRelay") { return false; } if (_fadeSceneHandle == ((Scene)(ref activeScene)).handle) { return _fadeStartedAt >= 0f; } PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val == (Object)null || !val.isPlayerControlled || (Object)(object)HUDManager.Instance == (Object)null) { if ((Object)(object)_promptCanvasGroup != (Object)null) { _promptCanvasGroup.alpha = 0f; } return false; } _fadeSceneHandle = ((Scene)(ref activeScene)).handle; _fadeStartedAt = Time.unscaledTime; _lastActivitySignature = int.MinValue; _activitySignatureInitialized = false; WakePromptPresentation(); if ((Object)(object)_promptCanvasGroup != (Object)null) { _promptCanvasGroup.alpha = 0f; } return true; } private static PlayerControllerB ResolveLocalPlayer() { object obj = GameNetworkManager.Instance?.localPlayerController; if (obj == null) { StartOfRound instance = StartOfRound.Instance; if (instance == null) { return null; } obj = instance.localPlayerController; } return (PlayerControllerB)obj; } private static bool UpdateHeldItemState(PlayerControllerB player) { GrabbableObject val = (((Object)(object)player != (Object)null) ? player.currentlyHeldObjectServer : null); if ((Object)(object)val != (Object)null && val.isPocketed) { val = null; } int num = (((Object)(object)val != (Object)null) ? ((Object)val).GetInstanceID() : 0); if (num == _heldItemInstanceId) { return false; } _heldItemInstanceId = num; _heldWeapon = (IsWeapon(val) ? val : null); _weaponPromptShownAt = (((Object)(object)_heldWeapon != (Object)null) ? Time.unscaledTime : (-1f)); _weaponPromptsSuppressed = false; _lastSourceSignature = int.MinValue; _promptDirty = true; WakePromptPresentation(); return true; } private static bool IsWeapon(GrabbableObject item) { return ArmoryItemProbe.IsArmoryWeapon(item); } private static bool IsHeldWeaponPrompt(string normalized) { if ((Object)(object)_heldWeapon == (Object)null || string.IsNullOrWhiteSpace(normalized)) { return false; } if (normalized.StartsWith("Drop ", StringComparison.OrdinalIgnoreCase) || normalized.StartsWith("Turn safety ", StringComparison.OrdinalIgnoreCase)) { return true; } string[] array = (((Object)(object)_heldWeapon.itemProperties != (Object)null) ? _heldWeapon.itemProperties.toolTips : null); if (array == null) { return false; } for (int i = 0; i < array.Length; i++) { string b = NormalizePromptText(array[i]); if (string.Equals(normalized, b, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static bool ObservePromptActivity(HUDManager hud, string cursorText) { int num = BuildActivitySignature(hud, cursorText); if (_activitySignatureInitialized && num == _lastActivitySignature) { return false; } _activitySignatureInitialized = true; _lastActivitySignature = num; WakePromptPresentation(); return true; } private static void WakePromptPresentation() { _lastActivityAt = Time.unscaledTime; _nextTickAt = 0f; } internal static void SetPersistentPrompt(string key, string text) { if (!string.IsNullOrWhiteSpace(key)) { string text2 = NormalizePromptText(text); string value; if (string.IsNullOrWhiteSpace(text2)) { ClearPersistentPrompt(key); } else if (!_persistentPromptLines.TryGetValue(key, out value) || !(value == text2)) { _persistentPromptLines[key] = text2; _promptDirty = true; WakePromptPresentation(); } } } internal static void ClearPersistentPrompt(string key) { if (!string.IsNullOrWhiteSpace(key) && _persistentPromptLines.Remove(key)) { _promptDirty = true; WakePromptPresentation(); } } internal static void SetPostPlayerMenuPrompt(string key, string text) { SetPostPlayerMenuPromptLines(key, (text == null) ? null : new string[1] { text }); } internal static void SetPostPlayerMenuPromptLines(string key, IReadOnlyList lines) { if (string.IsNullOrWhiteSpace(key)) { return; } string[] array = NormalizePromptBlock(lines); string[] value; if (array.Length == 0) { ClearPostPlayerMenuPrompt(key); } else if (!_postPlayerMenuPromptBlocks.TryGetValue(key, out value) || !BlocksEqual(value, array)) { if (!_postPlayerMenuPromptBlocks.ContainsKey(key)) { _postPlayerMenuPromptKeys.Add(key); } _postPlayerMenuPromptBlocks[key] = array; _promptDirty = true; WakePromptPresentation(); } } internal static void ClearPostPlayerMenuPrompt(string key) { if (!string.IsNullOrWhiteSpace(key) && _postPlayerMenuPromptBlocks.Remove(key)) { _postPlayerMenuPromptKeys.Remove(key); _promptDirty = true; WakePromptPresentation(); } } private static string[] NormalizePromptBlock(IReadOnlyList lines) { if (lines == null || lines.Count == 0) { return Array.Empty(); } List list = new List(lines.Count); for (int i = 0; i < lines.Count; i++) { string text = NormalizePromptText(lines[i]); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } } if (list.Count != 0) { return list.ToArray(); } return Array.Empty(); } private static bool BlocksEqual(string[] left, string[] right) { if (left == right) { return true; } if (left == null || right == null || left.Length != right.Length) { return false; } for (int i = 0; i < left.Length; i++) { if (!string.Equals(left[i], right[i], StringComparison.Ordinal)) { return false; } } return true; } internal static void SetCursorTipOverride(string text) { string text2 = (string.IsNullOrWhiteSpace(text) ? null : NormalizePromptText(text)); if (!string.Equals(_cursorTipOverride, text2, StringComparison.Ordinal)) { _cursorTipOverride = text2; _promptDirty = true; WakePromptPresentation(); } } private static string ResolveCursorText(string rawCursorText) { if (_cursorTipOverride == null || string.IsNullOrWhiteSpace(rawCursorText)) { return rawCursorText; } return _cursorTipOverride; } private static void ApplyTextStyle(TextMeshProUGUI tmp, HUDManager hud, TextAlignmentOptions alignment, bool flatten = true) { //IL_004d: 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_0065: 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_00e2: 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_00f4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)tmp == (Object)null) { return; } TMP_FontAsset val = ResolveVanillaFont(hud); if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)tmp).font != (Object)(object)val) { ((TMP_Text)tmp).font = val; } if (!Mathf.Approximately(((TMP_Text)tmp).fontSize, 24f)) { ((TMP_Text)tmp).fontSize = 24f; } if ((int)((TMP_Text)tmp).fontStyle != 0) { ((TMP_Text)tmp).fontStyle = (FontStyles)0; } if (((TMP_Text)tmp).alignment != alignment) { ((TMP_Text)tmp).alignment = alignment; } if (!Mathf.Approximately(((TMP_Text)tmp).characterSpacing, 0f)) { ((TMP_Text)tmp).characterSpacing = 0f; } if (!Mathf.Approximately(((TMP_Text)tmp).lineSpacing, 0f)) { ((TMP_Text)tmp).lineSpacing = 0f; } if (((TMP_Text)tmp).enableAutoSizing) { ((TMP_Text)tmp).enableAutoSizing = false; } if (((TMP_Text)tmp).enableWordWrapping) { ((TMP_Text)tmp).enableWordWrapping = false; } if ((int)((TMP_Text)tmp).overflowMode != 0) { ((TMP_Text)tmp).overflowMode = (TextOverflowModes)0; } if (!((TMP_Text)tmp).richText) { ((TMP_Text)tmp).richText = true; } if (((Graphic)tmp).color != Y4ngzUiStyle.CurrentAccentColor) { ((Graphic)tmp).color = Y4ngzUiStyle.CurrentAccentColor; } if (flatten) { string text = FlattenToSingleLine(((TMP_Text)tmp).text); if (text != ((TMP_Text)tmp).text) { ((TMP_Text)tmp).text = text; } } } private static void RefreshPromptOverlay(string cursorText) { EnsurePromptOverlay(); if (_promptLines == null) { return; } int num = BuildPromptLines(cursorText, _cachedPromptLines); int num2 = BuildPromptSignature(_cachedPromptLines, num); bool flag = num2 != _lastPromptSignature; if (flag) { _lastPromptSignature = num2; } for (int i = 0; i < _promptLines.Length; i++) { TextMeshProUGUI val = _promptLines[i]; if ((Object)(object)val == (Object)null) { continue; } bool flag2 = i < num && !string.IsNullOrWhiteSpace(_cachedPromptLines[i]); if (((Behaviour)val).enabled != flag2) { ((Behaviour)val).enabled = flag2; } if (flag) { string text = (flag2 ? _cachedPromptLines[i] : string.Empty); if (((TMP_Text)val).text != text) { ((TMP_Text)val).text = text; } } ApplyPromptLineStyleIfNeeded(val); } } private static int BuildPromptLines(string cursorText, string[] output) { for (int i = 0; i < output.Length; i++) { output[i] = string.Empty; } int count = 0; string text = NormalizePromptText(cursorText); if (!string.IsNullOrWhiteSpace(text)) { AddPromptLine(output, ref count, text); } AppendExternalPromptLines(output, ref count); HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null && instance.controlTipLines != null) { for (int j = 0; j < instance.controlTipLines.Length; j++) { if (count >= 12) { break; } TextMeshProUGUI val = instance.controlTipLines[j]; if (!((Object)(object)val == (Object)null)) { string text2 = NormalizePromptText(((TMP_Text)val).text); if (!string.IsNullOrWhiteSpace(text2) && (!_weaponPromptsSuppressed || !IsHeldWeaponPrompt(text2)) && !string.IsNullOrWhiteSpace(text2)) { AddPromptLine(output, ref count, text2); } } } } AppendPersistentPromptLines(output, ref count); PlayerControllerB val2 = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val2 != (Object)null && (val2.isInHangarShipRoom || val2.isInElevator || ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.inShipPhase)) && !val2.inTerminalMenu && !val2.isTypingChat) { AddPromptLine(output, ref count, "Player Menu: [" + UpgradeInput.DisplayLabel(Y4NGZUpgrades.Gui.Plugin.Keybinds?.PurchaseMenu, "P") + "]"); } AppendPostPlayerMenuPromptLines(output, ref count); return count; } private static void AppendPersistentPromptLines(string[] lines, ref int count) { if (_persistentPromptLines.Count == 0 || count >= 12) { return; } foreach (KeyValuePair persistentPromptLine in _persistentPromptLines) { if (count >= 12) { break; } if (!string.IsNullOrWhiteSpace(persistentPromptLine.Value)) { AddPromptLine(lines, ref count, persistentPromptLine.Value); } } } private static void AppendPostPlayerMenuPromptLines(string[] lines, ref int count) { if (_postPlayerMenuPromptKeys.Count == 0 || count >= 12) { return; } for (int i = 0; i < _postPlayerMenuPromptKeys.Count; i++) { if (count >= 12) { break; } if (!_postPlayerMenuPromptBlocks.TryGetValue(_postPlayerMenuPromptKeys[i], out var value)) { continue; } for (int j = 0; j < value.Length; j++) { if (count >= 12) { return; } AddPromptLine(lines, ref count, value[j]); } } } private static void RefreshExternalPromptSources() { TextMeshProUGUI source; bool num = TryGetActivePoltergeistPromptSource(out source); _activePoltergeistPromptSource = (num ? source : null); if (num) { if (_externalPromptSources.Count != 1 || _externalPromptSources[0] != source) { _externalPromptSources.Clear(); _externalPromptSources.Add(source); _promptDirty = true; } ApplyTextStyle(source, HUDManager.Instance, (TextAlignmentOptions)260, flatten: false); if (((Behaviour)source).enabled) { ((Behaviour)source).enabled = false; } _wasDeadOrSpectating = true; _externalSourceStableScans = 0; return; } if (PoltergeistControllerContractResolved) { if (_externalPromptSources.Count > 0) { _externalPromptSources.Clear(); _promptDirty = true; } _wasDeadOrSpectating = false; _externalSourceStableScans = 0; return; } if (!LocalPlayerIsDeadOrSpectating()) { if (_externalPromptSources.Count > 0) { _externalPromptSources.Clear(); _promptDirty = true; } _wasDeadOrSpectating = false; _externalSourceStableScans = 0; return; } if (!_wasDeadOrSpectating) { _wasDeadOrSpectating = true; _externalSourceStableScans = 0; _nextExternalSourceScanAt = 0f; _promptDirty = true; } float unscaledTime = Time.unscaledTime; if (unscaledTime < _nextExternalSourceScanAt) { return; } int count = _externalPromptSources.Count; _externalPromptSources.Clear(); TextMeshProUGUI[] array = Resources.FindObjectsOfTypeAll(); foreach (TextMeshProUGUI val in array) { if (IsExternalPromptSource(val)) { ApplyTextStyle(val, HUDManager.Instance, (TextAlignmentOptions)260, flatten: false); ((Behaviour)val).enabled = false; _externalPromptSources.Add(val); } } if (_externalPromptSources.Count != count) { _promptDirty = true; _externalSourceStableScans = 0; } else { _externalSourceStableScans++; } _nextExternalSourceScanAt = unscaledTime + ((_externalSourceStableScans >= 3) ? 5f : 0.75f); } private static bool TryGetActivePoltergeistPromptSource(out TextMeshProUGUI source) { source = null; try { Type poltergeistControllerType = _poltergeistControllerType; if (poltergeistControllerType == null) { if (_poltergeistControllerContractLookupAttempted) { return false; } _poltergeistControllerContractLookupAttempted = true; poltergeistControllerType = AccessTools.TypeByName("Poltergeist.SpectatorCamController"); if (poltergeistControllerType == null) { return false; } _poltergeistControllerType = poltergeistControllerType; _poltergeistControllerInstanceField = AccessTools.Field(poltergeistControllerType, "instance"); _poltergeistControlsTextField = AccessTools.Field(poltergeistControllerType, "controlsText"); } if (!PoltergeistControllerContractResolved) { return false; } object value = _poltergeistControllerInstanceField.GetValue(null); Behaviour val = (Behaviour)((value is Behaviour) ? value : null); if ((Object)(object)val == (Object)null || !val.isActiveAndEnabled) { return false; } object? value2 = _poltergeistControlsTextField.GetValue(value); source = (TextMeshProUGUI)((value2 is TextMeshProUGUI) ? value2 : null); return (Object)(object)source != (Object)null && (Object)(object)((Component)source).gameObject != (Object)null && ((Component)source).gameObject.activeInHierarchy; } catch { source = null; return false; } } private static bool IsExternalPromptSource(TextMeshProUGUI text) { if ((Object)(object)text == (Object)null || (Object)(object)((Component)text).gameObject == (Object)null || !((Component)text).gameObject.activeInHierarchy) { return false; } if (text == _activePoltergeistPromptSource) { return true; } string text2 = ((Object)((Component)text).gameObject).name ?? string.Empty; if (text2.IndexOf("Y4NGZUpgrades_PromptOverlay", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (text2.IndexOf("PoltergeistControlsText", StringComparison.OrdinalIgnoreCase) >= 0) { return LocalPlayerIsDeadOrSpectating(); } if (GetHierarchyName(((TMP_Text)text).transform).IndexOf("PoltergeistControlsText", StringComparison.OrdinalIgnoreCase) >= 0) { return LocalPlayerIsDeadOrSpectating(); } return false; } private static bool LocalPlayerIsDeadOrSpectating() { PlayerControllerB val = GameNetworkManager.Instance?.localPlayerController ?? StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null) { return val.isPlayerDead; } return false; } private static void AppendExternalPromptLines(string[] lines, ref int count) { if (_externalPromptSources.Count == 0 || count >= 12) { return; } int num = _externalPromptSources.Count - 1; while (num >= 0 && count < 12) { TextMeshProUGUI val = _externalPromptSources[num]; if (!IsExternalPromptSource(val)) { _externalPromptSources.RemoveAt(num); _promptDirty = true; } else { if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; } string text = ((TMP_Text)val).text; if (!string.IsNullOrWhiteSpace(text)) { string[] array = text.Replace("\r\n", "\n").Replace('\r', '\n').Split('\n'); foreach (string text2 in array) { if (count >= 12) { break; } string text3 = NormalizePromptText(text2); if (!string.IsNullOrWhiteSpace(text3)) { AddPromptLine(lines, ref count, text3); } } } } num--; } } private static void EnsurePromptOverlay() { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Expected O, but got Unknown //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: 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_011c: 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_0144: 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_015d: 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_01c7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) if (!_motionSubscribed) { GameplayHudMotion.MotionSampled += OnHudMotionSampled; _motionSubscribed = true; } if (_promptLines == null) { if ((Object)(object)_promptCanvasObject == (Object)null) { _promptCanvasObject = new GameObject("Y4NGZUpgrades_PromptOverlayCanvas"); Object.DontDestroyOnLoad((Object)(object)_promptCanvasObject); Canvas obj = _promptCanvasObject.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 104; CanvasScaler obj2 = _promptCanvasObject.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 1f; _promptCanvasGroup = _promptCanvasObject.AddComponent(); _promptCanvasGroup.interactable = false; _promptCanvasGroup.blocksRaycasts = false; GameObject val = new GameObject("PromptMotionRoot", new Type[1] { typeof(RectTransform) }); val.transform.SetParent(_promptCanvasObject.transform, false); _promptRoot = val.GetComponent(); _promptRoot.anchorMin = Vector2.zero; _promptRoot.anchorMax = Vector2.one; _promptRoot.pivot = new Vector2(0.5f, 0.5f); _promptRoot.offsetMin = Vector2.zero; _promptRoot.offsetMax = Vector2.zero; _motionOffset = GameplayHudMotion.CurrentOffset; _currentStackTop = ResolvePromptStackTop(); _stackLayoutInitialized = true; ApplyPromptRootPosition(); BeginInitialFadeForCurrentSceneIfNeeded(); _promptCanvasObject.SetActive(GameplayUiVisibility.IsVisible); } _promptLines = (TextMeshProUGUI[])(object)new TextMeshProUGUI[12]; for (int i = 0; i < _promptLines.Length; i++) { GameObject val2 = new GameObject($"PromptLine_{i:00}", new Type[1] { typeof(RectTransform) }); val2.transform.SetParent((Transform)(((Object)(object)_promptRoot != (Object)null) ? ((object)_promptRoot) : ((object)_promptCanvasObject.transform)), false); TextMeshProUGUI val3 = val2.AddComponent(); ApplyTextStyle(val3, HUDManager.Instance, (TextAlignmentOptions)260); PositionPromptLine(((TMP_Text)val3).rectTransform, i); ((Behaviour)val3).enabled = false; _promptLines[i] = val3; } } } private static void OnHudMotionSampled(Vector2 offset) { //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) _motionOffset = offset; ApplyPromptRootPosition(); } private static void UpdateStackLayoutFrame() { if (!((Object)(object)_promptRoot == (Object)null)) { float num = ResolvePromptStackTop(); if (!_stackLayoutInitialized) { _currentStackTop = num; _stackTopVelocity = 0f; _stackLayoutInitialized = true; } else if (num > _currentStackTop) { _currentStackTop = num; _stackTopVelocity = 0f; } else { _currentStackTop = Mathf.SmoothDamp(_currentStackTop, num, ref _stackTopVelocity, 0.16f, float.PositiveInfinity, Mathf.Max(0.0001f, Time.unscaledDeltaTime)); } ApplyPromptRootPosition(); } } private static void ApplyPromptRootPosition() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_promptRoot == (Object)null)) { _promptRoot.anchoredPosition = _motionOffset + new Vector2(0f, 0f - (_currentStackTop - 224f)); } } private static void PositionPromptLine(RectTransform rect, int index) { //IL_000b: 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_0021: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: 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_006a: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)rect == (Object)null)) { rect.anchorMin = PromptAnchor; rect.anchorMax = PromptAnchor; rect.pivot = PromptPivot; rect.anchoredPosition = new Vector2(-24f, -224f - (float)index * 27f); rect.sizeDelta = new Vector2(460f, 26f); ((Transform)rect).localRotation = Quaternion.identity; ((Transform)rect).localScale = Vector3.one; } } private static float ResolvePromptStackTop() { return Mathf.Max(224f, ContractHudLayoutBridge.GetStackedPromptTop()); } private static string FlattenToSingleLine(string text) { if (!string.IsNullOrEmpty(text)) { return text.Replace("\r\n", " ").Replace('\n', ' ').Replace('\r', ' '); } return text; } private static string NormalizePromptText(string text) { string text2 = FlattenToSingleLine(text); if (string.IsNullOrWhiteSpace(text2)) { return text2; } text2 = text2.Trim(); if (text2.Contains("Open Emote") || text2.Contains("Emote Radial") || text2.Contains("Emote Menu")) { return "Emote Wheel : [`]"; } return text2; } private static void ApplyHudSourceStyleIfNeeded(HUDManager hud, bool force = false) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0035: 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_009c: 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) if ((Object)(object)hud == (Object)null || hud.controlTipLines == null) { return; } Color currentAccentColor = Y4ngzUiStyle.CurrentAccentColor; bool flag = force || (Object)(object)_lastStyledHud != (Object)(object)hud || _lastStyledControlTipLines != hud.controlTipLines || _lastStyledHudAccent != currentAccentColor; for (int i = 0; i < hud.controlTipLines.Length; i++) { TextMeshProUGUI val = hud.controlTipLines[i]; if (!((Object)(object)val == (Object)null)) { if (flag) { ApplyTextStyle(val, hud, (TextAlignmentOptions)513); } if (((Behaviour)val).enabled) { ((Behaviour)val).enabled = false; } } } if (flag) { _lastStyledHud = hud; _lastStyledControlTipLines = hud.controlTipLines; _lastStyledHudAccent = currentAccentColor; } } private static void ApplyCursorSourceStyleIfNeeded(TextMeshProUGUI source, HUDManager hud, bool force = false) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)source == (Object)null)) { Color currentAccentColor = Y4ngzUiStyle.CurrentAccentColor; if (force || !((Object)(object)_lastStyledCursorTip == (Object)(object)source) || !(_lastStyledCursorAccent == currentAccentColor)) { ApplyTextStyle(source, hud, (TextAlignmentOptions)514); _lastStyledCursorTip = source; _lastStyledCursorAccent = currentAccentColor; } } } private static void ApplyPromptLineStyleIfNeeded(TextMeshProUGUI line) { //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_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 //IL_0030: Unknown result type (might be due to invalid IL or missing references) if (!Mathf.Approximately(((TMP_Text)line).fontSize, 24f)) { ((TMP_Text)line).fontSize = 24f; } if (((Graphic)line).color != Y4ngzUiStyle.CurrentAccentColor) { ((Graphic)line).color = Y4ngzUiStyle.CurrentAccentColor; } if ((int)((TMP_Text)line).alignment != 260) { ((TMP_Text)line).alignment = (TextAlignmentOptions)260; } } private static TMP_FontAsset ResolveVanillaFont(HUDManager hud) { if ((Object)(object)_fontCache != (Object)null) { return _fontCache; } if ((Object)(object)hud != (Object)null && (Object)(object)hud.clockNumber != (Object)null && (Object)(object)((TMP_Text)hud.clockNumber).font != (Object)null) { _fontCache = ((TMP_Text)hud.clockNumber).font; return _fontCache; } if (Time.unscaledTime < _nextFontFallbackScanAt) { return null; } _nextFontFallbackScanAt = Time.unscaledTime + 5f; TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val in array) { if (((Object)val).name.Contains("3270") || ((Object)val).name.Contains("edunline") || ((Object)val).name.Contains("EdgeOf")) { _fontCache = val; return _fontCache; } } return null; } private static int BuildSourceSignature(HUDManager hud, string cursorText) { int signature = AddSignaturePart(17, NormalizePromptText(cursorText)); if ((Object)(object)hud != (Object)null && hud.controlTipLines != null) { for (int i = 0; i < hud.controlTipLines.Length; i++) { TextMeshProUGUI val = hud.controlTipLines[i]; signature = AddSignaturePart(signature, ((Object)(object)val == (Object)null) ? string.Empty : NormalizePromptText(((TMP_Text)val).text)); } } signature = AddSignaturePart(signature, IsPlayerMenuAvailable() ? "ship:1" : "ship:0"); signature = AddSignaturePart(signature, _externalPromptSources.Count); for (int j = 0; j < _externalPromptSources.Count; j++) { TextMeshProUGUI val2 = _externalPromptSources[j]; signature = AddSignaturePart(signature, ((Object)(object)val2 == (Object)null) ? string.Empty : NormalizePromptText(((TMP_Text)val2).text)); } foreach (KeyValuePair persistentPromptLine in _persistentPromptLines) { signature = AddSignaturePart(signature, persistentPromptLine.Key); signature = AddSignaturePart(signature, persistentPromptLine.Value); } return AddPostPlayerMenuSignatureParts(signature); } private static int AddPostPlayerMenuSignatureParts(int signature) { for (int i = 0; i < _postPlayerMenuPromptKeys.Count; i++) { string text = _postPlayerMenuPromptKeys[i]; signature = AddSignaturePart(signature, text); if (_postPlayerMenuPromptBlocks.TryGetValue(text, out var value)) { signature = AddSignaturePart(signature, value.Length); for (int j = 0; j < value.Length; j++) { signature = AddSignaturePart(signature, value[j]); } } } return signature; } private static int BuildActivitySignature(HUDManager hud, string cursorText) { int signature = AddSignaturePart(17, NormalizePromptText(cursorText)); if ((Object)(object)hud != (Object)null && hud.controlTipLines != null) { for (int i = 0; i < hud.controlTipLines.Length; i++) { TextMeshProUGUI val = hud.controlTipLines[i]; string text = (((Object)(object)val != (Object)null) ? NormalizePromptText(((TMP_Text)val).text) : string.Empty); if (!IsHeldWeaponPrompt(text)) { signature = AddSignaturePart(signature, text); } } } for (int j = 0; j < _externalPromptSources.Count; j++) { TextMeshProUGUI val2 = _externalPromptSources[j]; signature = AddSignaturePart(signature, ((Object)(object)val2 != (Object)null) ? ((TMP_Text)val2).text : string.Empty); } foreach (KeyValuePair persistentPromptLine in _persistentPromptLines) { signature = AddSignaturePart(signature, persistentPromptLine.Key); signature = AddSignaturePart(signature, persistentPromptLine.Value); } signature = AddPostPlayerMenuSignatureParts(signature); return AddSignaturePart(signature, IsPlayerMenuAvailable() ? 1 : 0); } private static int AddSignaturePart(int signature, string value) { return signature * 31 + (value?.GetHashCode() ?? 0); } private static int AddSignaturePart(int signature, int value) { return signature * 31 + value; } private static bool IsPlayerMenuAvailable() { PlayerControllerB val = (((Object)(object)GameNetworkManager.Instance != (Object)null) ? GameNetworkManager.Instance.localPlayerController : null); if ((Object)(object)val != (Object)null && (val.isInHangarShipRoom || val.isInElevator || ((Object)(object)StartOfRound.Instance != (Object)null && StartOfRound.Instance.inShipPhase)) && !val.inTerminalMenu) { return !val.isTypingChat; } return false; } private static void AddPromptLine(string[] lines, ref int count, string text) { if (count >= 12 || string.IsNullOrWhiteSpace(text)) { return; } for (int i = 0; i < count; i++) { if (lines[i] == text) { return; } } lines[count++] = text; } private static int BuildPromptSignature(string[] lines, int count) { int num = 17; for (int i = 0; i < count; i++) { num = AddSignaturePart(num, lines[i]); } return num; } private static string GetHierarchyName(Transform transform) { if ((Object)(object)transform == (Object)null) { return string.Empty; } string text = ((Object)transform).name ?? string.Empty; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = text + "/" + (((Object)parent).name ?? string.Empty); parent = parent.parent; } return text; } } [HarmonyPatch(typeof(HUDManager), "Start")] internal static class Y4ngzPromptStartPatch { [HarmonyPostfix] private static void Postfix(HUDManager __instance) { Y4ngzPromptOverlay.Apply(__instance); } } [HarmonyPatch(typeof(HUDManager), "ChangeControlTip")] internal static class Y4ngzPromptSinglePatch { [HarmonyPostfix] private static void Postfix(HUDManager __instance) { Y4ngzPromptOverlay.Apply(__instance); } } [HarmonyPatch(typeof(HUDManager), "ChangeControlTipMultiple")] internal static class Y4ngzPromptMultiplePatch { [HarmonyPostfix] private static void Postfix(HUDManager __instance) { Y4ngzPromptOverlay.Apply(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "SetHoverTipAndCurrentInteractTrigger")] internal static class Y4ngzPromptCursorPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { Y4ngzPromptOverlay.Apply(__instance); } } [HarmonyPatch(typeof(PlayerControllerB), "LateUpdate")] internal static class Y4ngzPromptTickPatch { [HarmonyPostfix] private static void Postfix(PlayerControllerB __instance) { if (!((Object)(object)__instance == (Object)null) && !((Object)(object)__instance != (Object)(object)GameNetworkManager.Instance?.localPlayerController)) { Y4ngzPromptOverlay.Tick(); } } } internal static class Y4ngzUiStyle { internal const float ControlTextSize = 24f; internal static Color CurrentAccentColor => UiTheme.Accent; } } namespace Y4NGZUpgrades.Interactive.Feedback { internal sealed class DirectionalDamageHud : MonoBehaviour { private const float Duration = 0.95f; private static DirectionalDamageHud _instance; private static Sprite _arcSprite; private RectTransform _root; private RectTransform _arcTransform; private Image _arcImage; private float _shownAt = -999f; private float _damageScale = 1f; public static void ShowFromWorldPosition(PlayerControllerB player, Vector3 sourcePosition, int damageNumber) { //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!GameplayUiVisibility.IsVisible) { return; } ConfigEntry dangerFeedbackEnabled = Plugin.DangerFeedbackEnabled; if (dangerFeedbackEnabled != null && !dangerFeedbackEnabled.Value) { return; } ConfigEntry dangerFeedbackDirectionalDamageEnabled = Plugin.DangerFeedbackDirectionalDamageEnabled; if ((dangerFeedbackDirectionalDamageEnabled == null || dangerFeedbackDirectionalDamageEnabled.Value) && !((Object)(object)player == (Object)null) && !((Object)(object)player.gameplayCamera == (Object)null)) { DirectionalDamageHud directionalDamageHud = Ensure(); if (!((Object)(object)directionalDamageHud == (Object)null)) { directionalDamageHud.PositionArrow(player, sourcePosition, damageNumber); directionalDamageHud._shownAt = Time.unscaledTime; ((Component)directionalDamageHud).gameObject.SetActive(true); directionalDamageHud.UpdateVisual(); } } } public static void DestroyInstance() { if (!((Object)(object)_instance == (Object)null)) { Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } } internal static void SetPresentationVisible(bool visible) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_instance == (Object)null || visible)) { _instance._shownAt = -999f; if ((Object)(object)_instance._arcImage != (Object)null) { ((Graphic)_instance._arcImage).color = new Color(1f, 0.08f, 0.02f, 0f); } ((Component)_instance).gameObject.SetActive(false); } } private static DirectionalDamageHud Ensure() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance != (Object)null) { return _instance; } if ((Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { return null; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if ((Object)(object)canvas == (Object)null) { return null; } GameObject val = new GameObject("Y4NGZ_DirectionalDamageHud"); val.transform.SetParent(((Component)canvas).transform, false); DirectionalDamageHud directionalDamageHud = val.AddComponent(); directionalDamageHud.Build(); _instance = directionalDamageHud; return directionalDamageHud; } private void Build() { //IL_0017: 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_0037: 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_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_008a: 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_00be: 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_0124: Unknown result type (might be due to invalid IL or missing references) _root = ((Component)this).gameObject.AddComponent(); _root.anchorMin = Vector2.zero; _root.anchorMax = Vector2.one; _root.offsetMin = Vector2.zero; _root.offsetMax = Vector2.zero; GameObject val = new GameObject("DamageDirectionArc"); val.transform.SetParent(((Component)this).transform, false); _arcTransform = val.AddComponent(); _arcTransform.anchorMin = new Vector2(0.5f, 0.5f); _arcTransform.anchorMax = new Vector2(0.5f, 0.5f); _arcTransform.pivot = new Vector2(0.5f, 0.5f); _arcTransform.sizeDelta = new Vector2(132f, 54f); _arcImage = val.AddComponent(); _arcImage.sprite = GetArcSprite(); ((Graphic)_arcImage).raycastTarget = false; ((Graphic)_arcImage).color = new Color(1f, 0.08f, 0.02f, 0f); ((Component)this).gameObject.SetActive(false); } private void PositionArrow(PlayerControllerB player, Vector3 sourcePosition, int damageNumber) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: 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) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0168: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_0178: Unknown result type (might be due to invalid IL or missing references) //IL_01a3: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0130: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_0144: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) Transform transform = ((Component)player.gameplayCamera).transform; Vector3 val = sourcePosition - ((Component)player).transform.position; val.y = 0f; Vector3 forward = transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.001f) { forward = ((Component)player).transform.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 right = transform.right; right.y = 0f; if (((Vector3)(ref right)).sqrMagnitude < 0.001f) { right = ((Component)player).transform.right; } ((Vector3)(ref right)).Normalize(); Vector2 down = default(Vector2); if (((Vector3)(ref val)).sqrMagnitude < 0.001f) { down = Vector2.down; } else { ((Vector3)(ref val)).Normalize(); ((Vector2)(ref down))..ctor(Vector3.Dot(right, val), Vector3.Dot(forward, val)); if (((Vector2)(ref down)).sqrMagnitude < 0.001f) { down = Vector2.down; } else { ((Vector2)(ref down)).Normalize(); } } float num = 270f; if ((Object)(object)_root != (Object)null) { Rect rect = _root.rect; if (((Rect)(ref rect)).width > 0f) { rect = _root.rect; if (((Rect)(ref rect)).height > 0f) { rect = _root.rect; float width = ((Rect)(ref rect)).width; rect = _root.rect; num = Mathf.Min(width, ((Rect)(ref rect)).height) * 0.36f; } } } _arcTransform.anchoredPosition = down * num; float num2 = Mathf.Atan2(down.y, down.x) * 57.29578f - 90f; ((Transform)_arcTransform).localRotation = Quaternion.Euler(0f, 0f, num2); _damageScale = Mathf.Lerp(0.9f, 1.25f, Mathf.Clamp01((float)damageNumber / 80f)); } private void Update() { UpdateVisual(); } private void UpdateVisual() { //IL_00a4: 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_0057: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_arcImage == (Object)null) { return; } if (!GameplayUiVisibility.IsVisible) { SetPresentationVisible(visible: false); return; } ((Component)this).transform.SetAsLastSibling(); float num = Time.unscaledTime - _shownAt; if (num >= 0.95f) { ((Graphic)_arcImage).color = new Color(1f, 0.08f, 0.02f, 0f); ((Component)this).gameObject.SetActive(false); return; } float num2 = Mathf.Clamp01(num / 0.95f); float num3 = Mathf.Lerp(0.58f, 0f, num2 * num2); ((Graphic)_arcImage).color = new Color(1f, 0.12f, 0.04f, num3); ((Transform)_arcTransform).localScale = Vector3.one * Mathf.Lerp(_damageScale * 1.12f, _damageScale, num2); } private static Sprite GetArcSprite() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_01d5: Unknown result type (might be due to invalid IL or missing references) //IL_01e4: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: 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_018d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_arcSprite != (Object)null) { return _arcSprite; } Texture2D val = new Texture2D(192, 96, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; Color val2 = default(Color); ((Color)(ref val2))..ctor(1f, 1f, 1f, 0f); for (int i = 0; i < 96; i++) { for (int j = 0; j < 192; j++) { val.SetPixel(j, i, val2); } } Vector2 val3 = default(Vector2); ((Vector2)(ref val3))..ctor(96f, -67.2f); float num = 136.31999f; float num2 = 12f; float num3 = 0.46f; for (int k = 0; k < 96; k++) { for (int l = 0; l < 192; l++) { Vector2 val4 = new Vector2((float)l + 0.5f, (float)k + 0.5f) - val3; float num4 = Mathf.Abs(((Vector2)(ref val4)).magnitude - num); if (!(num4 > num2)) { float num5 = Mathf.Abs(Mathf.DeltaAngle(Mathf.Atan2(val4.y, val4.x) * 57.29578f, 90f)) * (MathF.PI / 180f); if (!(num5 > num3)) { float num6 = 1f - Mathf.Clamp01(num4 / num2); float num7 = 1f - Mathf.Clamp01((num5 - num3 * 0.72f) / (num3 * 0.28f)); float num8 = Mathf.Clamp01(num6 * num7); num8 = num8 * num8 * (3f - 2f * num8); val.SetPixel(l, k, new Color(1f, 1f, 1f, num8)); } } } } val.Apply(false, true); _arcSprite = Sprite.Create(val, new Rect(0f, 0f, 192f, 96f), new Vector2(0.5f, 0.5f)); ((Object)_arcSprite).hideFlags = (HideFlags)61; return _arcSprite; } } internal sealed class EnemyHitFlash : MonoBehaviour { private static readonly int BaseColorId = Shader.PropertyToID("_BaseColor"); private static readonly int ColorId = Shader.PropertyToID("_Color"); private static readonly int EmissiveColorId = Shader.PropertyToID("_EmissiveColor"); private static AudioClip _impactClip; private Renderer[] _renderers; private MaterialPropertyBlock _block; private Coroutine _flashRoutine; public static void Pulse(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return; } ConfigEntry combatFeedbackEnabled = Plugin.CombatFeedbackEnabled; if (combatFeedbackEnabled != null && !combatFeedbackEnabled.Value) { return; } ConfigEntry combatFeedbackEnemyFlashEnabled = Plugin.CombatFeedbackEnemyFlashEnabled; if (combatFeedbackEnemyFlashEnabled != null && combatFeedbackEnemyFlashEnabled.Value) { EnemyHitFlash enemyHitFlash = ((Component)enemy).gameObject.GetComponent(); if ((Object)(object)enemyHitFlash == (Object)null) { enemyHitFlash = ((Component)enemy).gameObject.AddComponent(); } enemyHitFlash.StartPulse(enemy); } ConfigEntry combatFeedbackEnemyImpactLightEnabled = Plugin.CombatFeedbackEnemyImpactLightEnabled; if (combatFeedbackEnemyImpactLightEnabled != null && combatFeedbackEnemyImpactLightEnabled.Value) { SpawnImpactLight(enemy); } ConfigEntry combatFeedbackEnemyImpactSoundEnabled = Plugin.CombatFeedbackEnemyImpactSoundEnabled; if (combatFeedbackEnemyImpactSoundEnabled == null || combatFeedbackEnemyImpactSoundEnabled.Value) { PlayImpactSound(enemy); } } private void StartPulse(EnemyAI enemy) { //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Expected O, but got Unknown if (_renderers == null || _renderers.Length == 0) { _renderers = CollectRenderers(enemy); } if (_renderers != null && _renderers.Length != 0) { if (_block == null) { _block = new MaterialPropertyBlock(); } if (_flashRoutine != null) { ((MonoBehaviour)this).StopCoroutine(_flashRoutine); } _flashRoutine = ((MonoBehaviour)this).StartCoroutine(FlashRoutine()); } } private static Renderer[] CollectRenderers(EnemyAI enemy) { if ((Object)(object)enemy == (Object)null) { return Array.Empty(); } int num = ((enemy.skinnedMeshRenderers != null) ? enemy.skinnedMeshRenderers.Length : 0); int num2 = ((enemy.meshRenderers != null) ? enemy.meshRenderers.Length : 0); if (num + num2 <= 0) { return ((Component)enemy).GetComponentsInChildren(false); } Renderer[] array = (Renderer[])(object)new Renderer[num + num2]; int num3 = 0; for (int i = 0; i < num; i++) { array[num3++] = (Renderer)(object)enemy.skinnedMeshRenderers[i]; } for (int j = 0; j < num2; j++) { array[num3++] = (Renderer)(object)enemy.meshRenderers[j]; } return array; } private IEnumerator FlashRoutine() { Color flashColor = new Color(1f, 0.62f, 0.22f, 1f); float startedAt = Time.time; while (Time.time - startedAt < 0.18f) { float num = Mathf.Clamp01((Time.time - startedAt) / 0.18f); float strength = 1f - num * num; ApplyTint(flashColor, strength); yield return null; } ClearTint(); _flashRoutine = null; } private void ApplyTint(Color color, float strength) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0072: 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_0094: Unknown result type (might be due to invalid IL or missing references) if (_block == null) { _block = new MaterialPropertyBlock(); } Color val = Color.Lerp(Color.white, color, Mathf.Clamp01(strength * 0.65f)); Color val2 = color * Mathf.Clamp01(strength * 1.4f); for (int i = 0; i < _renderers.Length; i++) { Renderer val3 = _renderers[i]; if (!((Object)(object)val3 == (Object)null) && val3.enabled) { _block.Clear(); _block.SetColor(BaseColorId, val); _block.SetColor(ColorId, val); _block.SetColor(EmissiveColorId, val2); val3.SetPropertyBlock(_block); } } } private void ClearTint() { if (_renderers == null) { return; } for (int i = 0; i < _renderers.Length; i++) { Renderer val = _renderers[i]; if (!((Object)(object)val == (Object)null)) { val.SetPropertyBlock((MaterialPropertyBlock)null); } } } private static void SpawnImpactLight(EnemyAI enemy) { //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_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0018: 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) Vector3 position = ResolveCenter(enemy); GameObject val = new GameObject("Y4NGZ_EnemyHitFlash_Light"); val.transform.position = position; Light val2 = val.AddComponent(); val2.type = (LightType)2; val2.color = new Color(1f, 0.58f, 0.22f); val2.intensity = 8f; val2.range = 5f; val2.shadows = (LightShadows)0; val2.bounceIntensity = 0f; ((MonoBehaviour)(((Object)(object)HUDManager.Instance != (Object)null) ? ((object)HUDManager.Instance) : ((object)enemy))).StartCoroutine(FadeLight(val, val2)); } private static void PlayImpactSound(EnemyAI enemy) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) AudioClip impactClip = GetImpactClip(); if (!((Object)(object)impactClip == (Object)null)) { AudioSource.PlayClipAtPoint(impactClip, ResolveCenter(enemy), 0.16f); } } private static IEnumerator FadeLight(GameObject go, Light light) { float startIntensity = (((Object)(object)light != (Object)null) ? light.intensity : 0f); float elapsed = 0f; while (elapsed < 0.12f) { if ((Object)(object)light == (Object)null) { yield break; } float num = Mathf.Clamp01(elapsed / 0.12f); light.intensity = startIntensity * (1f - num); elapsed += Time.deltaTime; yield return null; } if ((Object)(object)go != (Object)null) { Object.Destroy((Object)(object)go); } } private static Vector3 ResolveCenter(EnemyAI enemy) { //IL_0009: 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_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: 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_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return Vector3.zero; } if ((Object)(object)enemy.eye != (Object)null) { return enemy.eye.position; } Renderer val = null; if (enemy.skinnedMeshRenderers != null) { for (int i = 0; i < enemy.skinnedMeshRenderers.Length; i++) { if ((Object)(object)enemy.skinnedMeshRenderers[i] != (Object)null) { val = (Renderer)(object)enemy.skinnedMeshRenderers[i]; break; } } } if ((Object)(object)val == (Object)null && enemy.meshRenderers != null) { for (int j = 0; j < enemy.meshRenderers.Length; j++) { if ((Object)(object)enemy.meshRenderers[j] != (Object)null) { val = (Renderer)(object)enemy.meshRenderers[j]; break; } } } if ((Object)(object)val != (Object)null) { Bounds bounds = val.bounds; return ((Bounds)(ref bounds)).center; } return ((Component)enemy).transform.position + Vector3.up; } private static AudioClip GetImpactClip() { if ((Object)(object)_impactClip != (Object)null) { return _impactClip; } int num = Mathf.CeilToInt(1984.5001f); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 44100f; float num3 = Mathf.Exp((0f - num2) * 70f); float num4 = Mathf.Sin(MathF.PI * 1240f * num2) * 0.55f; float num5 = Mathf.Sin(MathF.PI * 3020f * num2) * 0.25f; array[i] = (num4 + num5) * num3 * 0.38f; } _impactClip = AudioClip.Create("Y4NGZ_EnemyImpactTick", num, 1, 44100, false); _impactClip.SetData(array, 0); ((Object)_impactClip).hideFlags = (HideFlags)61; return _impactClip; } private void OnDestroy() { ClearTint(); } } internal sealed class PlayerDangerHud : MonoBehaviour { private const int VignetteSize = 256; private const float FlashDecay = 2.8f; private static PlayerDangerHud _instance; private static Texture2D _vignetteTexture; private static AudioClip _heartbeatClip; private RawImage _vignette; private float _damageFlashAlpha; private float _nextHeartbeatTime; public static void UpdatePlayerState(PlayerControllerB player) { if (GameplayUiVisibility.IsVisible) { ConfigEntry dangerFeedbackEnabled = Plugin.DangerFeedbackEnabled; if (dangerFeedbackEnabled == null || dangerFeedbackEnabled.Value) { PlayerDangerHud playerDangerHud = Ensure(); if (!((Object)(object)playerDangerHud == (Object)null)) { playerDangerHud.UpdateForPlayer(player); } return; } } HideInstance(); } public static void PulseDamage(int damageNumber) { if (!GameplayUiVisibility.IsVisible) { return; } ConfigEntry dangerFeedbackEnabled = Plugin.DangerFeedbackEnabled; if (dangerFeedbackEnabled == null || dangerFeedbackEnabled.Value) { PlayerDangerHud playerDangerHud = Ensure(); if (!((Object)(object)playerDangerHud == (Object)null)) { playerDangerHud._damageFlashAlpha = Mathf.Max(playerDangerHud._damageFlashAlpha, Mathf.Lerp(0.12f, 0.38f, Mathf.Clamp01((float)damageNumber / 80f))); ((Component)playerDangerHud).gameObject.SetActive(true); } } } public static void DestroyInstance() { if (!((Object)(object)_instance == (Object)null)) { Object.Destroy((Object)(object)((Component)_instance).gameObject); _instance = null; } } internal static void SetPresentationVisible(bool visible) { if (!visible) { HideInstance(); } } private static void HideInstance() { if (!((Object)(object)_instance == (Object)null)) { ((Component)_instance).gameObject.SetActive(false); } } private static PlayerDangerHud Ensure() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_instance != (Object)null) { return _instance; } if ((Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { return null; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if ((Object)(object)canvas == (Object)null) { return null; } GameObject val = new GameObject("Y4NGZ_PlayerDangerHud"); val.transform.SetParent(((Component)canvas).transform, false); PlayerDangerHud playerDangerHud = val.AddComponent(); playerDangerHud.Build(); _instance = playerDangerHud; return playerDangerHud; } private void Build() { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0022: 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_0071: Unknown result type (might be due to invalid IL or missing references) RectTransform obj = ((Component)this).gameObject.AddComponent(); obj.anchorMin = Vector2.zero; obj.anchorMax = Vector2.one; obj.offsetMin = Vector2.zero; obj.offsetMax = Vector2.zero; _vignette = ((Component)this).gameObject.AddComponent(); _vignette.texture = (Texture)(object)GetVignetteTexture(); ((Graphic)_vignette).color = new Color(0.9f, 0.02f, 0.01f, 0f); ((Graphic)_vignette).raycastTarget = false; ((Component)this).gameObject.SetActive(false); } private void UpdateForPlayer(PlayerControllerB player) { //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignette == (Object)null) { return; } if (!((Object)(object)player != (Object)null) || !((Object)(object)player == (Object)(object)GameNetworkManager.Instance?.localPlayerController) || !player.isPlayerControlled || player.isPlayerDead) { _damageFlashAlpha = 0f; ((Graphic)_vignette).color = new Color(0.9f, 0.02f, 0.01f, 0f); ((Component)this).gameObject.SetActive(false); return; } int num = Mathf.Clamp(Plugin.DangerFeedbackLowHealthThreshold?.Value ?? 35, 1, 99); float num2 = 0f; ConfigEntry dangerFeedbackLowHealthEnabled = Plugin.DangerFeedbackLowHealthEnabled; if ((dangerFeedbackLowHealthEnabled == null || dangerFeedbackLowHealthEnabled.Value) && player.health <= num) { num2 = Mathf.Clamp01((float)(num - Mathf.Max(player.health, 1)) / (float)num); } float num3 = ((num2 > 0f) ? (Mathf.Abs(Mathf.Sin(Time.unscaledTime * Mathf.Lerp(2.2f, 4.8f, num2))) * 0.06f) : 0f); _damageFlashAlpha = Mathf.MoveTowards(_damageFlashAlpha, 0f, Time.unscaledDeltaTime * 2.8f); float num4 = Mathf.Clamp01(_damageFlashAlpha + num2 * 0.18f + num3); ((Graphic)_vignette).color = new Color(0.88f, 0.03f, 0.015f, num4); ((Component)this).gameObject.SetActive(num4 > 0.01f); if (num2 > 0.45f) { ConfigEntry dangerFeedbackHeartbeatEnabled = Plugin.DangerFeedbackHeartbeatEnabled; if (dangerFeedbackHeartbeatEnabled == null || dangerFeedbackHeartbeatEnabled.Value) { TryPlayHeartbeat(num2); } } } private void TryPlayHeartbeat(float danger) { if (!(Time.unscaledTime < _nextHeartbeatTime)) { _nextHeartbeatTime = Time.unscaledTime + Mathf.Lerp(1.25f, 0.62f, danger); if (!((Object)(object)HUDManager.Instance == (Object)null) && !((Object)(object)HUDManager.Instance.UIAudio == (Object)null)) { HUDManager.Instance.UIAudio.PlayOneShot(GetHeartbeatClip(), Mathf.Lerp(0.16f, 0.34f, danger)); } } } private static Texture2D GetVignetteTexture() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_003b: Expected O, but got Unknown //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_vignetteTexture != (Object)null) { return _vignetteTexture; } Texture2D val = new Texture2D(256, 256, (TextureFormat)4, false) { wrapMode = (TextureWrapMode)1, filterMode = (FilterMode)1, hideFlags = (HideFlags)61 }; float num = 127.5f; float num2 = num * 0.46f; float num3 = num - num2; Color[] array = (Color[])(object)new Color[65536]; for (int i = 0; i < 256; i++) { for (int j = 0; j < 256; j++) { float num4 = (float)j - num; float num5 = (float)i - num; float num6 = Mathf.Clamp01((Mathf.Sqrt(num4 * num4 + num5 * num5) - num2) / num3); num6 *= num6; array[i * 256 + j] = new Color(1f, 1f, 1f, num6); } } val.SetPixels(array); val.Apply(false, true); _vignetteTexture = val; return _vignetteTexture; } private static AudioClip GetHeartbeatClip() { if ((Object)(object)_heartbeatClip != (Object)null) { return _heartbeatClip; } int num = Mathf.CeilToInt(7938.0005f); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 44100f; float num3 = Mathf.Sin(MathF.PI * 164f * num2) * Mathf.Exp((0f - num2) * 42f); float num4 = Mathf.Max(0f, num2 - 0.08f); float num5 = Mathf.Sin(MathF.PI * 132f * num4) * Mathf.Exp((0f - num4) * 55f) * 0.55f; array[i] = (num3 + num5) * 0.32f; } _heartbeatClip = AudioClip.Create("Y4NGZ_LowHealthHeartbeat", num, 1, 44100, false); _heartbeatClip.SetData(array, 0); ((Object)_heartbeatClip).hideFlags = (HideFlags)61; return _heartbeatClip; } } } namespace Y4NGZUpgrades.HUD { internal static class ForemanAuraStatusHud { private const float ResolveRetryInterval = 0.75f; private const float IconSize = 22f; private static GameObject _root; private static RectTransform _rootRect; private static RectTransform _healthBar; private static float _nextResolveAt; private static bool _active; private static Sprite _fallbackSprite; private static Texture2D _fallbackTexture; internal static void SetAuraActive(bool active) { _active = active; if (!_active) { Hide(); } else { UpdateActiveState(); } } internal static void Destroy() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } _root = null; _rootRect = null; _healthBar = null; _nextResolveAt = 0f; _active = false; if ((Object)(object)_fallbackSprite != (Object)null) { Object.Destroy((Object)(object)_fallbackSprite); } if ((Object)(object)_fallbackTexture != (Object)null) { Object.Destroy((Object)(object)_fallbackTexture); } _fallbackSprite = null; _fallbackTexture = null; } private static void UpdateActiveState() { //IL_0063: 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_0095: 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_00c7: Unknown result type (might be due to invalid IL or missing references) RectTransform val = ResolveHealthBar(); if ((Object)(object)val == (Object)null) { Hide(); return; } EnsureRoot(val); if (!((Object)(object)_root == (Object)null) && !((Object)(object)_rootRect == (Object)null)) { if ((Object)(object)((Transform)_rootRect).parent != (Object)(object)val) { ((Transform)_rootRect).SetParent((Transform)(object)val, false); } _rootRect.anchorMin = new Vector2(0.5f, 1f); _rootRect.anchorMax = new Vector2(0.5f, 1f); _rootRect.pivot = new Vector2(0.5f, 0f); _rootRect.sizeDelta = new Vector2(22f, 22f); _rootRect.anchoredPosition = new Vector2(0f, 4f); _root.SetActive(true); } } private static void Hide() { if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } private static RectTransform ResolveHealthBar() { if ((Object)(object)_healthBar != (Object)null) { return _healthBar; } if (Time.unscaledTime < _nextResolveAt) { return null; } _nextResolveAt = Time.unscaledTime + 0.75f; _healthBar = FindHealthBar(); return _healthBar; } private static RectTransform FindHealthBar() { Canvas[] array = Object.FindObjectsOfType(true); RectTransform val = null; int num = 0; RectTransform result = null; int num2 = 0; foreach (Canvas val2 in array) { if ((Object)(object)val2 == (Object)null || (Object)(object)((Component)val2).transform == (Object)null) { continue; } RectTransform[] componentsInChildren = ((Component)val2).GetComponentsInChildren(true); foreach (RectTransform val3 in componentsInChildren) { bool preferred; int num3 = ScoreHealthBarCandidate(val3, out preferred); if (num3 <= 0) { continue; } if (preferred) { if (num3 > num) { num = num3; val = val3; } } else if (num3 > num2) { num2 = num3; result = val3; } } } if (!((Object)(object)val != (Object)null)) { return result; } return val; } private static int ScoreHealthBarCandidate(RectTransform rect, out bool preferred) { preferred = false; if ((Object)(object)rect == (Object)null || string.IsNullOrWhiteSpace(((Object)rect).name)) { return 0; } string text = ((Object)rect).name.ToLowerInvariant(); string text2 = BuildTransformPath(((Component)rect).transform).ToLowerInvariant(); bool flag = text2.Contains("elad") || text2.Contains("customhud"); bool flag2 = text.Contains("health"); bool flag3 = text.Contains("healthbar") || text.Contains("health_bar"); bool flag4 = text2.Contains("health"); bool flag5 = text2.Contains("healthbar") || text2.Contains("health_bar"); preferred = flag && (flag2 || flag4); if (!preferred && !flag3) { return 0; } int num = (preferred ? 100 : 10); if (flag3) { num += 30; } else if (flag2) { num += 12; } if (flag5) { num += 8; } if ((Object)(object)((Component)rect).GetComponent() != (Object)null || (Object)(object)((Component)rect).GetComponent() != (Object)null) { num += 2; } if (((Component)rect).gameObject.activeInHierarchy) { num++; } return num; } private static string BuildTransformPath(Transform transform) { if ((Object)(object)transform == (Object)null) { return string.Empty; } string text = ((Object)transform).name; Transform parent = transform.parent; int num = 0; while ((Object)(object)parent != (Object)null && num++ < 48) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } private static void EnsureRoot(RectTransform healthBar) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown //IL_009b: 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) if (!((Object)(object)_root != (Object)null)) { Sprite val = UpgradeHUDManager.LoadUpgradeIconSprite("buddy_system"); _root = new GameObject("Y4NGZ_ForemanBuddyAuraStatus"); _root.transform.SetParent((Transform)(object)healthBar, false); _rootRect = _root.AddComponent(); Image obj = _root.AddComponent(); obj.sprite = (((Object)(object)val != (Object)null) ? val : GetFallbackSprite()); obj.preserveAspect = true; ((Graphic)obj).raycastTarget = false; ((Graphic)obj).color = (Color)(((Object)(object)val != (Object)null) ? Color.white : new Color(0.2f, 1f, 0.45f, 0.92f)); if ((Object)(object)val == (Object)null) { AddFallbackText(_root.transform); } } } private static void AddFallbackText(Transform parent) { //IL_0005: 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_0079: 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_008f: 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) TextMeshProUGUI obj = new GameObject("Fallback").AddComponent(); ((TMP_Text)obj).transform.SetParent(parent, false); ((TMP_Text)obj).text = "B"; ((TMP_Text)obj).fontSize = 14f; ((TMP_Text)obj).enableAutoSizing = true; ((TMP_Text)obj).fontSizeMin = 8f; ((TMP_Text)obj).fontSizeMax = 14f; ((TMP_Text)obj).enableWordWrapping = false; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).color = Color.black; ((Graphic)obj).raycastTarget = false; RectTransform component = ((Component)obj).GetComponent(); component.anchorMin = Vector2.zero; component.anchorMax = Vector2.one; component.offsetMin = Vector2.zero; component.offsetMax = Vector2.zero; } private static Sprite GetFallbackSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown //IL_0028: 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_0070: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_fallbackSprite != (Object)null) { return _fallbackSprite; } _fallbackTexture = new Texture2D(1, 1, (TextureFormat)4, false); _fallbackTexture.SetPixel(0, 0, Color.white); _fallbackTexture.Apply(); ((Object)_fallbackTexture).hideFlags = (HideFlags)61; _fallbackSprite = Sprite.Create(_fallbackTexture, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f), 100f); ((Object)_fallbackSprite).hideFlags = (HideFlags)61; return _fallbackSprite; } } internal static class UpgradeHUDManager { private static AssetBundle _bundle; private static bool _bundleLoadAttempted; private static bool _bundleLoadFailed; private static readonly Dictionary _spriteCache = new Dictionary(); private static readonly Dictionary _hudElements = new Dictionary(); private static readonly Dictionary _hudImages = new Dictionary(); private static readonly Dictionary _fillBars = new Dictionary(); private static readonly Dictionary _labelTexts = new Dictionary(); private static readonly Dictionary _stackPositions = new Dictionary(); private static readonly Dictionary _stackHeights = new Dictionary(); private static readonly List _stackOrder = new List(); private static Sprite _whiteFillSprite; private static TMP_FontAsset _hudFont; private const float ELEMENT_WIDTH = 105f; private const float ELEMENT_HEIGHT = 32f; private const float LARGE_ELEMENT_WIDTH = 190f; private const float LARGE_ELEMENT_HEIGHT = 58f; private const float RIGHT_MARGIN = 10f; private const float BOTTOM_MARGIN = 10f; private const float STACK_GAP = 3f; private const string BUNDLE_NAME = "Y4NGZUpgrades.lethalbundle"; private static readonly bool LOG_BUNDLE_CONTENTS = false; public static void LoadBundle() { if (_bundleLoadAttempted) { return; } _bundleLoadAttempted = true; foreach (AssetBundle allLoadedAssetBundle in AssetBundle.GetAllLoadedAssetBundles()) { if ((Object)(object)allLoadedAssetBundle == (Object)null || allLoadedAssetBundle.isStreamedSceneAssetBundle) { continue; } Sprite val; try { val = allLoadedAssetBundle.LoadAsset("shadow_hud"); } catch (Exception) { continue; } if ((Object)(object)val != (Object)null) { _bundle = allLoadedAssetBundle; ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)("[Y4NGZUpgrades] Found preloaded HUD bundle: " + ((Object)allLoadedAssetBundle).name)); } break; } } if ((Object)(object)_bundle == (Object)null) { string text = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Y4NGZUpgrades.lethalbundle"); if (!File.Exists(text)) { ManualLogSource log2 = Plugin.Log; if (log2 != null) { log2.LogWarning((object)("[Y4NGZUpgrades] HUD bundle not found at " + text)); } _bundleLoadFailed = true; return; } _bundle = AssetBundle.LoadFromFile(text); if ((Object)(object)_bundle == (Object)null) { ManualLogSource log3 = Plugin.Log; if (log3 != null) { log3.LogError((object)("[Y4NGZUpgrades] Failed to load HUD bundle at " + text)); } _bundleLoadFailed = true; return; } } if (LOG_BUNDLE_CONTENTS) { try { string[] allAssetNames = _bundle.GetAllAssetNames(); ManualLogSource log4 = Plugin.Log; if (log4 != null) { log4.LogInfo((object)$"[Y4NGZUpgrades] Bundle '{((Object)_bundle).name}' contains {allAssetNames.Length} assets:"); } for (int i = 0; i < allAssetNames.Length; i++) { ManualLogSource log5 = Plugin.Log; if (log5 != null) { log5.LogInfo((object)$"[Y4NGZUpgrades] asset[{i}] = {allAssetNames[i]}"); } } } catch { } } CacheSprite("shadow_hud"); CacheSprite("escape_hud"); CacheSprite("pipebomb_hud"); CacheSprite("pipe_hud"); CacheSprite("pipe_bomb_hud"); ManualLogSource log6 = Plugin.Log; if (log6 != null) { log6.LogInfo((object)"[Y4NGZUpgrades] HUD bundle loaded successfully."); } } public static Sprite GetCachedSprite(string spriteName) { _spriteCache.TryGetValue(spriteName, out var value); return value; } public static string ResolveSpriteName(params string[] candidates) { for (int i = 0; i < candidates.Length; i++) { if (_spriteCache.ContainsKey(candidates[i])) { return candidates[i]; } } return null; } private static Sprite GetWhiteFillSprite() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0043: 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_005c: Expected O, but got Unknown if ((Object)(object)_whiteFillSprite != (Object)null) { return _whiteFillSprite; } Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false); val.SetPixel(0, 0, Color.white); val.Apply(); _whiteFillSprite = Sprite.Create(val, new Rect(0f, 0f, 1f, 1f), new Vector2(0.5f, 0.5f)); return _whiteFillSprite; } private static TMP_FontAsset ResolveHudFont() { if ((Object)(object)_hudFont != (Object)null) { return _hudFont; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null) { if ((Object)(object)instance.clockNumber != (Object)null && (Object)(object)((TMP_Text)instance.clockNumber).font != (Object)null) { _hudFont = ((TMP_Text)instance.clockNumber).font; return _hudFont; } TMP_Text componentInChildren = ((Component)instance).GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null && (Object)(object)componentInChildren.font != (Object)null) { _hudFont = componentInChildren.font; return _hudFont; } } TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll(); foreach (TMP_FontAsset val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && (((Object)val).name.Contains("3270") || ((Object)val).name.Contains("edunline") || ((Object)val).name.Contains("EdgeOf"))) { _hudFont = val; return _hudFont; } } TMP_Text val2 = Object.FindObjectOfType(); if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null) { _hudFont = val2.font; } return _hudFont; } private static void ApplyHudTextStyle(TextMeshProUGUI label, float fontSize, float fontSizeMin, float fontSizeMax, TextAlignmentOptions alignment, Color color) { //IL_0059: 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) if (!((Object)(object)label == (Object)null)) { TMP_FontAsset val = ResolveHudFont(); if ((Object)(object)val != (Object)null && (Object)(object)((TMP_Text)label).font != (Object)(object)val) { ((TMP_Text)label).font = val; } ((TMP_Text)label).fontSize = fontSize; ((TMP_Text)label).enableAutoSizing = true; ((TMP_Text)label).fontSizeMin = fontSizeMin; ((TMP_Text)label).fontSizeMax = fontSizeMax; ((TMP_Text)label).enableWordWrapping = false; ((TMP_Text)label).overflowMode = (TextOverflowModes)1; ((TMP_Text)label).alignment = alignment; ((Graphic)label).color = color; ((TMP_Text)label).fontStyle = (FontStyles)0; ((TMP_Text)label).characterSpacing = 0f; ((TMP_Text)label).lineSpacing = 0f; ((TMP_Text)label).extraPadding = true; ((Graphic)label).raycastTarget = false; } } private static void CacheSprite(string name) { if ((Object)(object)_bundle == (Object)null) { return; } Sprite val = _bundle.LoadAsset(name); if ((Object)(object)val != (Object)null) { _spriteCache[name] = val; } else if (LOG_BUNDLE_CONTENTS) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)("[Y4NGZUpgrades] Sprite '" + name + "' not found in bundle.")); } } } private static Sprite LoadHudSprite(string spriteName) { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Expected O, but got Unknown //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(spriteName)) { return null; } string text = spriteName.Trim().ToLowerInvariant().Replace(' ', '_'); if (_spriteCache.TryGetValue(text, out var value) && (Object)(object)value != (Object)null) { return value; } LoadBundle(); if ((Object)(object)_bundle != (Object)null) { Sprite val = _bundle.LoadAsset(text); if ((Object)(object)val != (Object)null) { _spriteCache[text] = val; return val; } } string text2 = FindHudSpritePath(text); if (string.IsNullOrWhiteSpace(text2) || !File.Exists(text2)) { return null; } try { byte[] array = File.ReadAllBytes(text2); Texture2D val2 = new Texture2D(2, 2, (TextureFormat)4, false); if (!ImageConversion.LoadImage(val2, array)) { Object.Destroy((Object)(object)val2); return null; } ((Object)val2).name = Path.GetFileNameWithoutExtension(text2); ((Texture)val2).wrapMode = (TextureWrapMode)1; ((Texture)val2).filterMode = (FilterMode)1; Sprite val3 = Sprite.Create(val2, new Rect(0f, 0f, (float)((Texture)val2).width, (float)((Texture)val2).height), new Vector2(0.5f, 0.5f), 100f); _spriteCache[text] = val3; return val3; } catch { return null; } } public static GameObject CreateHUDElement(string spriteName, int stackPosition, Transform parentCanvas) { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_0075: 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_009f: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0118: 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_012e: Unknown result type (might be due to invalid IL or missing references) //IL_0138: 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_016c: Unknown result type (might be due to invalid IL or missing references) if (_bundleLoadFailed || (Object)(object)parentCanvas == (Object)null) { return null; } LoadBundle(); if (!_spriteCache.TryGetValue(spriteName, out var value)) { return null; } if (_hudElements.TryGetValue(spriteName, out var value2) && (Object)(object)value2 != (Object)null) { Object.Destroy((Object)(object)value2); } GameObject val = new GameObject("UpgradeHUD_" + spriteName); val.transform.SetParent(parentCanvas, false); RectTransform obj = val.AddComponent(); obj.anchorMin = new Vector2(1f, 0f); obj.anchorMax = new Vector2(1f, 0f); obj.pivot = new Vector2(1f, 0f); obj.sizeDelta = new Vector2(105f, 32f); obj.anchoredPosition = new Vector2(-10f, 10f); Image val2 = val.AddComponent(); val2.sprite = value; val2.type = (Type)0; val2.preserveAspect = true; ((Graphic)val2).raycastTarget = false; GameObject val3 = new GameObject("CooldownFill"); val3.transform.SetParent(val.transform, false); RectTransform obj2 = val3.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; Image val4 = val3.AddComponent(); val4.sprite = GetWhiteFillSprite(); ((Graphic)val4).color = new Color(0f, 0.8f, 0f, 0.25f); val4.type = (Type)3; val4.fillMethod = (FillMethod)0; val4.fillOrigin = 0; val4.fillAmount = 0f; ((Graphic)val4).raycastTarget = false; val3.SetActive(false); _hudElements[spriteName] = val; _hudImages[spriteName] = val2; _fillBars[spriteName] = val4; RegisterStackElement(spriteName, stackPosition, 32f); if ((Object)(object)val.GetComponent() == (Object)null) { val.AddComponent(); } RefreshStackLayout(); RefreshTheme(); return val; } public static GameObject CreateIconKeyHUDElement(string elementKey, string iconKey, string labelText, int stackPosition, Transform parentCanvas) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_006c: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00f0: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025e: 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_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parentCanvas == (Object)null || string.IsNullOrWhiteSpace(elementKey)) { return null; } if (_hudElements.TryGetValue(elementKey, out var value) && (Object)(object)value != (Object)null) { SetHUDElementLabel(elementKey, labelText); return value; } Sprite val = LoadUpgradeIconSprite(iconKey); GameObject val2 = new GameObject("UpgradeHUD_" + elementKey); val2.transform.SetParent(parentCanvas, false); RectTransform obj = val2.AddComponent(); obj.anchorMin = new Vector2(1f, 0f); obj.anchorMax = new Vector2(1f, 0f); obj.pivot = new Vector2(1f, 0f); obj.sizeDelta = new Vector2(105f, 32f); obj.anchoredPosition = new Vector2(-10f, 10f); Image val3 = val2.AddComponent(); val3.sprite = GetWhiteFillSprite(); ((Graphic)val3).color = new Color(0f, 0.32f, 0f, 0.58f); ((Graphic)val3).raycastTarget = false; AddBorder(val2.transform, new Color(0.65f, 1f, 0.12f, 0.9f)); GameObject val4 = new GameObject("Icon"); val4.transform.SetParent(val2.transform, false); RectTransform obj2 = val4.AddComponent(); obj2.anchorMin = new Vector2(0f, 0.5f); obj2.anchorMax = new Vector2(0f, 0.5f); obj2.pivot = new Vector2(0.5f, 0.5f); obj2.sizeDelta = new Vector2(24f, 24f); obj2.anchoredPosition = new Vector2(18f, 0f); Image obj3 = val4.AddComponent(); obj3.sprite = (((Object)(object)val != (Object)null) ? val : GetWhiteFillSprite()); obj3.preserveAspect = true; ((Graphic)obj3).color = (Color)(((Object)(object)val != (Object)null) ? Color.white : new Color(0.9098039f, 20f / 51f, 14f / 85f, 1f)); ((Graphic)obj3).raycastTarget = false; GameObject val5 = new GameObject("Divider"); val5.transform.SetParent(val2.transform, false); RectTransform obj4 = val5.AddComponent(); obj4.anchorMin = new Vector2(0f, 0f); obj4.anchorMax = new Vector2(0f, 1f); obj4.pivot = new Vector2(0.5f, 0.5f); obj4.offsetMin = new Vector2(38f, 4f); obj4.offsetMax = new Vector2(40f, -4f); Image obj5 = val5.AddComponent(); obj5.sprite = GetWhiteFillSprite(); ((Graphic)obj5).color = new Color(0.65f, 1f, 0.12f, 0.7f); ((Graphic)obj5).raycastTarget = false; TextMeshProUGUI val6 = new GameObject("Label").AddComponent(); ((TMP_Text)val6).transform.SetParent(val2.transform, false); ((TMP_Text)val6).text = labelText ?? ""; ((TMP_Text)val6).fontSize = 9f; ((TMP_Text)val6).enableAutoSizing = true; ((TMP_Text)val6).fontSizeMin = 6f; ((TMP_Text)val6).fontSizeMax = 9f; ((TMP_Text)val6).enableWordWrapping = false; ((TMP_Text)val6).overflowMode = (TextOverflowModes)1; ((TMP_Text)val6).alignment = (TextAlignmentOptions)4097; ((Graphic)val6).color = new Color(1f, 0.45f, 0.08f, 1f); ((Graphic)val6).raycastTarget = false; ApplyHudTextStyle(val6, 9f, 6f, 9f, (TextAlignmentOptions)4097, new Color(1f, 0.45f, 0.08f, 1f)); RectTransform component = ((Component)val6).GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(46f, 1f); component.offsetMax = new Vector2(-4f, -1f); GameObject val7 = new GameObject("CooldownFill"); val7.transform.SetParent(val2.transform, false); RectTransform obj6 = val7.AddComponent(); obj6.anchorMin = Vector2.zero; obj6.anchorMax = Vector2.one; obj6.offsetMin = Vector2.zero; obj6.offsetMax = Vector2.zero; Image val8 = val7.AddComponent(); val8.sprite = GetWhiteFillSprite(); ((Graphic)val8).color = new Color(0f, 0.8f, 0f, 0.24f); val8.type = (Type)3; val8.fillMethod = (FillMethod)0; val8.fillOrigin = 0; val8.fillAmount = 0f; ((Graphic)val8).raycastTarget = false; val7.SetActive(false); _hudElements[elementKey] = val2; _hudImages[elementKey] = val3; _fillBars[elementKey] = val8; _labelTexts[elementKey] = val6; RegisterStackElement(elementKey, stackPosition, 32f); if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } RefreshStackLayout(); RefreshTheme(); return val2; } public static GameObject CreateLargeIconKeyHUDElement(string elementKey, string iconKey, string labelText, int stackPosition, Transform parentCanvas) { //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Expected O, but got Unknown //IL_006c: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: 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_00f0: 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_012a: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_0152: Unknown result type (might be due to invalid IL or missing references) //IL_0167: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_01a5: Unknown result type (might be due to invalid IL or missing references) //IL_01f7: 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_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0211: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_0234: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_025e: 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_0287: Unknown result type (might be due to invalid IL or missing references) //IL_02b6: Unknown result type (might be due to invalid IL or missing references) //IL_02cb: Unknown result type (might be due to invalid IL or missing references) //IL_0359: Unknown result type (might be due to invalid IL or missing references) //IL_0395: Unknown result type (might be due to invalid IL or missing references) //IL_03b1: Unknown result type (might be due to invalid IL or missing references) //IL_03c6: Unknown result type (might be due to invalid IL or missing references) //IL_03db: Unknown result type (might be due to invalid IL or missing references) //IL_03ef: Unknown result type (might be due to invalid IL or missing references) //IL_03fe: Unknown result type (might be due to invalid IL or missing references) //IL_0403: Unknown result type (might be due to invalid IL or missing references) //IL_0415: Unknown result type (might be due to invalid IL or missing references) //IL_041c: Unknown result type (might be due to invalid IL or missing references) //IL_0427: Unknown result type (might be due to invalid IL or missing references) //IL_0432: Unknown result type (might be due to invalid IL or missing references) //IL_043c: Unknown result type (might be due to invalid IL or missing references) //IL_0446: Unknown result type (might be due to invalid IL or missing references) //IL_0470: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parentCanvas == (Object)null || string.IsNullOrWhiteSpace(elementKey)) { return null; } if (_hudElements.TryGetValue(elementKey, out var value) && (Object)(object)value != (Object)null) { SetHUDElementLabel(elementKey, labelText); return value; } Sprite val = LoadUpgradeIconSprite(iconKey); GameObject val2 = new GameObject("UpgradeHUD_" + elementKey); val2.transform.SetParent(parentCanvas, false); RectTransform obj = val2.AddComponent(); obj.anchorMin = new Vector2(1f, 0f); obj.anchorMax = new Vector2(1f, 0f); obj.pivot = new Vector2(1f, 0f); obj.sizeDelta = new Vector2(190f, 58f); obj.anchoredPosition = new Vector2(-10f, 10f); Image val3 = val2.AddComponent(); val3.sprite = GetWhiteFillSprite(); ((Graphic)val3).color = new Color(0f, 0.32f, 0f, 0.58f); ((Graphic)val3).raycastTarget = false; AddBorder(val2.transform, new Color(0.65f, 1f, 0.12f, 0.9f)); GameObject val4 = new GameObject("Icon"); val4.transform.SetParent(val2.transform, false); RectTransform obj2 = val4.AddComponent(); obj2.anchorMin = new Vector2(0f, 0.5f); obj2.anchorMax = new Vector2(0f, 0.5f); obj2.pivot = new Vector2(0.5f, 0.5f); obj2.sizeDelta = new Vector2(30f, 30f); obj2.anchoredPosition = new Vector2(22f, 0f); Image obj3 = val4.AddComponent(); obj3.sprite = (((Object)(object)val != (Object)null) ? val : GetWhiteFillSprite()); obj3.preserveAspect = true; ((Graphic)obj3).color = (Color)(((Object)(object)val != (Object)null) ? Color.white : new Color(0.9098039f, 20f / 51f, 14f / 85f, 1f)); ((Graphic)obj3).raycastTarget = false; GameObject val5 = new GameObject("Divider"); val5.transform.SetParent(val2.transform, false); RectTransform obj4 = val5.AddComponent(); obj4.anchorMin = new Vector2(0f, 0f); obj4.anchorMax = new Vector2(0f, 1f); obj4.pivot = new Vector2(0.5f, 0.5f); obj4.offsetMin = new Vector2(48f, 5f); obj4.offsetMax = new Vector2(50f, -5f); Image obj5 = val5.AddComponent(); obj5.sprite = GetWhiteFillSprite(); ((Graphic)obj5).color = new Color(0.65f, 1f, 0.12f, 0.7f); ((Graphic)obj5).raycastTarget = false; TextMeshProUGUI val6 = new GameObject("Label").AddComponent(); ((TMP_Text)val6).transform.SetParent(val2.transform, false); ((TMP_Text)val6).text = labelText ?? ""; ((TMP_Text)val6).fontSize = 8.5f; ((TMP_Text)val6).enableAutoSizing = true; ((TMP_Text)val6).fontSizeMin = 5.8f; ((TMP_Text)val6).fontSizeMax = 8.5f; ((TMP_Text)val6).enableWordWrapping = false; ((TMP_Text)val6).overflowMode = (TextOverflowModes)1; ((TMP_Text)val6).alignment = (TextAlignmentOptions)513; ((Graphic)val6).color = new Color(1f, 0.55f, 0.12f, 1f); ((Graphic)val6).raycastTarget = false; ApplyHudTextStyle(val6, 8.5f, 5.8f, 8.5f, (TextAlignmentOptions)513, new Color(1f, 0.55f, 0.12f, 1f)); RectTransform component = ((Component)val6).GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(58f, 5f); component.offsetMax = new Vector2(-6f, -5f); GameObject val7 = new GameObject("CooldownFill"); val7.transform.SetParent(val2.transform, false); RectTransform obj6 = val7.AddComponent(); obj6.anchorMin = Vector2.zero; obj6.anchorMax = Vector2.one; obj6.offsetMin = Vector2.zero; obj6.offsetMax = Vector2.zero; Image val8 = val7.AddComponent(); val8.sprite = GetWhiteFillSprite(); ((Graphic)val8).color = new Color(0f, 0.8f, 0f, 0.24f); val8.type = (Type)3; val8.fillMethod = (FillMethod)0; val8.fillOrigin = 0; val8.fillAmount = 0f; ((Graphic)val8).raycastTarget = false; val7.SetActive(false); _hudElements[elementKey] = val2; _hudImages[elementKey] = val3; _fillBars[elementKey] = val8; _labelTexts[elementKey] = val6; RegisterStackElement(elementKey, stackPosition, 58f); if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } RefreshStackLayout(); RefreshTheme(); return val2; } public static GameObject CreateLargeSpriteHUDElement(string elementKey, string spriteName, string labelText, int stackPosition, Transform parentCanvas) { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Expected O, but got Unknown //IL_0077: 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_00a1: 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_00ca: 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_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_0202: Unknown result type (might be due to invalid IL or missing references) //IL_0217: 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_023a: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0251: Unknown result type (might be due to invalid IL or missing references) //IL_0258: Unknown result type (might be due to invalid IL or missing references) //IL_0263: Unknown result type (might be due to invalid IL or missing references) //IL_026e: Unknown result type (might be due to invalid IL or missing references) //IL_0278: Unknown result type (might be due to invalid IL or missing references) //IL_0282: Unknown result type (might be due to invalid IL or missing references) //IL_02ac: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)parentCanvas == (Object)null || string.IsNullOrWhiteSpace(elementKey)) { return null; } if (_hudElements.TryGetValue(elementKey, out var value) && (Object)(object)value != (Object)null) { SetHUDElementLabel(elementKey, labelText); return value; } Sprite val = LoadHudSprite(spriteName); if ((Object)(object)val == (Object)null) { return null; } GameObject val2 = new GameObject("UpgradeHUD_" + elementKey); val2.transform.SetParent(parentCanvas, false); RectTransform obj = val2.AddComponent(); obj.anchorMin = new Vector2(1f, 0f); obj.anchorMax = new Vector2(1f, 0f); obj.pivot = new Vector2(1f, 0f); obj.sizeDelta = new Vector2(190f, 58f); obj.anchoredPosition = new Vector2(-10f, 10f); Image val3 = val2.AddComponent(); val3.sprite = val; val3.type = (Type)0; val3.preserveAspect = true; ((Graphic)val3).color = Color.white; ((Graphic)val3).raycastTarget = false; TextMeshProUGUI val4 = new GameObject("Label").AddComponent(); ((TMP_Text)val4).transform.SetParent(val2.transform, false); ((TMP_Text)val4).text = labelText ?? ""; ((TMP_Text)val4).fontSize = 8.2f; ((TMP_Text)val4).enableAutoSizing = true; ((TMP_Text)val4).fontSizeMin = 5.6f; ((TMP_Text)val4).fontSizeMax = 8.2f; ((TMP_Text)val4).enableWordWrapping = false; ((TMP_Text)val4).overflowMode = (TextOverflowModes)1; ((TMP_Text)val4).alignment = (TextAlignmentOptions)513; ((Graphic)val4).color = new Color(0.9098039f, 20f / 51f, 14f / 85f, 1f); ((Graphic)val4).raycastTarget = false; ApplyHudTextStyle(val4, 8.2f, 5.6f, 8.2f, (TextAlignmentOptions)513, new Color(0.9098039f, 20f / 51f, 14f / 85f, 1f)); RectTransform component = ((Component)val4).GetComponent(); component.anchorMin = new Vector2(0f, 0f); component.anchorMax = new Vector2(1f, 1f); component.offsetMin = new Vector2(58f, 5f); component.offsetMax = new Vector2(-7f, -5f); GameObject val5 = new GameObject("CooldownFill"); val5.transform.SetParent(val2.transform, false); RectTransform obj2 = val5.AddComponent(); obj2.anchorMin = Vector2.zero; obj2.anchorMax = Vector2.one; obj2.offsetMin = Vector2.zero; obj2.offsetMax = Vector2.zero; Image val6 = val5.AddComponent(); val6.sprite = GetWhiteFillSprite(); ((Graphic)val6).color = new Color(1f, 0.52f, 0.12f, 0.18f); val6.type = (Type)3; val6.fillMethod = (FillMethod)0; val6.fillOrigin = 0; val6.fillAmount = 0f; ((Graphic)val6).raycastTarget = false; val5.SetActive(false); _hudElements[elementKey] = val2; _hudImages[elementKey] = val3; _fillBars[elementKey] = val6; _labelTexts[elementKey] = val4; RegisterStackElement(elementKey, stackPosition, 58f); if ((Object)(object)val2.GetComponent() == (Object)null) { val2.AddComponent(); } RefreshStackLayout(); RefreshTheme(); return val2; } internal static void RefreshTheme() { //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) //IL_0006: 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_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_0032: Unknown result type (might be due to invalid IL or missing references) //IL_006b: 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_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0169: Unknown result type (might be due to invalid IL or missing references) Color accent = UiTheme.Accent; Color panel = UiTheme.Panel; Color faint = UiTheme.Faint; Sprite whiteFillSprite = GetWhiteFillSprite(); foreach (TextMeshProUGUI value in _labelTexts.Values) { TintPreservingAlpha((Graphic)(object)value, accent); } foreach (Image value2 in _fillBars.Values) { TintPreservingAlpha((Graphic)(object)value2, faint); } foreach (GameObject value3 in _hudElements.Values) { if ((Object)(object)value3 == (Object)null) { continue; } Image[] componentsInChildren = value3.GetComponentsInChildren(true); foreach (Image val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !_fillBars.ContainsValue(val)) { string name = ((Object)((Component)val).gameObject).name; if (name.StartsWith("Border") || name == "Divider") { TintPreservingAlpha((Graphic)(object)val, accent); } else if ((Object)(object)((Component)val).gameObject == (Object)(object)value3 && (Object)(object)val.sprite == (Object)(object)whiteFillSprite) { TintPreservingAlpha((Graphic)(object)val, panel); } else if (name == "Icon" && (Object)(object)val.sprite == (Object)(object)whiteFillSprite) { TintPreservingAlpha((Graphic)(object)val, accent); } } } } } private static void TintPreservingAlpha(Graphic graphic, Color color) { //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) if (!((Object)(object)graphic == (Object)null)) { color.a = graphic.color.a; graphic.color = color; } } public static void SetHUDElementLabel(string elementKey, string labelText) { if (_labelTexts.TryGetValue(elementKey, out var value) && (Object)(object)value != (Object)null) { ((TMP_Text)value).text = labelText ?? ""; } } private static void RegisterStackElement(string spriteName, int stackPosition, float elementHeight) { if (!_stackOrder.Contains(spriteName)) { _stackOrder.Add(spriteName); } _stackPositions[spriteName] = stackPosition; _stackHeights[spriteName] = Mathf.Max(32f, elementHeight); _stackOrder.Sort(delegate(string a, string b) { int value; int num = (_stackPositions.TryGetValue(a, out value) ? value : 0); int value3; int value2 = (_stackPositions.TryGetValue(b, out value3) ? value3 : 0); int num2 = num.CompareTo(value2); return (num2 == 0) ? string.CompareOrdinal(a, b) : num2; }); } internal static void RefreshStackLayout() { //IL_0050: Unknown result type (might be due to invalid IL or missing references) float num = 10f; for (int i = 0; i < _stackOrder.Count; i++) { string key = _stackOrder[i]; if (_hudElements.TryGetValue(key, out var value) && !((Object)(object)value == (Object)null) && value.activeSelf) { RectTransform component = value.GetComponent(); if (!((Object)(object)component == (Object)null)) { component.anchoredPosition = new Vector2(-10f, num); float value2; float num2 = (_stackHeights.TryGetValue(key, out value2) ? value2 : 32f); num += num2 + 3f; } } } } public static void SetCooldownActive(string spriteName, bool active) { //IL_0019: 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_0036: Unknown result type (might be due to invalid IL or missing references) if (_hudImages.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { Color color = ((Graphic)value).color; color.a = (active ? 0.35f : 1f); ((Graphic)value).color = color; } if (_fillBars.TryGetValue(spriteName, out var value2) && (Object)(object)value2 != (Object)null) { ((Component)value2).gameObject.SetActive(active); } } public static void UpdateFillBar(string spriteName, float normalizedTimeRemaining) { if (_fillBars.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { value.fillAmount = Mathf.Clamp01(normalizedTimeRemaining); } } public static GameObject GetHUDElement(string spriteName) { _hudElements.TryGetValue(spriteName, out var value); return value; } public static void DestroyHUDElement(string spriteName) { if (_hudElements.TryGetValue(spriteName, out var value) && (Object)(object)value != (Object)null) { Object.Destroy((Object)(object)value); } _hudElements.Remove(spriteName); _hudImages.Remove(spriteName); _fillBars.Remove(spriteName); _labelTexts.Remove(spriteName); _stackOrder.Remove(spriteName); _stackPositions.Remove(spriteName); _stackHeights.Remove(spriteName); RefreshStackLayout(); } public static void DestroyAllHUDElements() { foreach (KeyValuePair hudElement in _hudElements) { if ((Object)(object)hudElement.Value != (Object)null) { Object.Destroy((Object)(object)hudElement.Value); } } _hudElements.Clear(); _hudImages.Clear(); _fillBars.Clear(); _labelTexts.Clear(); _stackOrder.Clear(); _stackPositions.Clear(); _stackHeights.Clear(); } public static Sprite LoadUpgradeIconSprite(string iconKey) { return UpgradeIconLoader.LoadUpgradeIconSprite(iconKey); } private static string FindHudSpritePath(string spriteName) { string directoryName = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string fullPath = Path.GetFullPath(Path.Combine(Application.dataPath, "..")); string text = spriteName + ".png"; string[] array = new string[4] { Path.Combine(directoryName ?? "", "Assets", "UI", "HUD", text), Path.Combine(directoryName ?? "", "InteractiveAssets", "UI", "HUD", text), Path.Combine(fullPath, "BepInEx", "plugins", "y4ngz-Y4NGZUpgrades", "Assets", "UI", "HUD", text), Path.Combine(fullPath, "BepInEx", "plugins", "Y4NGZUpgrades", "Assets", "UI", "HUD", text) }; foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2) && File.Exists(text2)) { return text2; } } return null; } private static void AddBorder(Transform parent, Color color) { //IL_0010: 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_002e: 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_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: 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_006c: 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_0087: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_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_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) AddLine(parent, "Top", new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(0f, -2f), Vector2.zero, color); AddLine(parent, "Bottom", Vector2.zero, new Vector2(1f, 0f), Vector2.zero, new Vector2(0f, 2f), color); AddLine(parent, "Left", Vector2.zero, new Vector2(0f, 1f), Vector2.zero, new Vector2(2f, 0f), color); AddLine(parent, "Right", new Vector2(1f, 0f), Vector2.one, new Vector2(-2f, 0f), Vector2.zero, color); } private static void AddLine(Transform parent, string name, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin, Vector2 offsetMax, Color color) { //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_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002b: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("Border" + name); val.transform.SetParent(parent, false); RectTransform obj = val.AddComponent(); obj.anchorMin = anchorMin; obj.anchorMax = anchorMax; obj.offsetMin = offsetMin; obj.offsetMax = offsetMax; Image obj2 = val.AddComponent(); obj2.sprite = GetWhiteFillSprite(); ((Graphic)obj2).color = color; ((Graphic)obj2).raycastTarget = false; } } internal sealed class UpgradeHUDStackDriver : MonoBehaviour { private void OnEnable() { UpgradeHUDManager.RefreshStackLayout(); } private void OnDisable() { UpgradeHUDManager.RefreshStackLayout(); } } } namespace Y4NGZUpgrades.Gui { internal static class CompanyInputWatchdogLatch { private const string WatchdogTypeName = "Y4NGZCompany.Experience.Diagnostics.LocalInputStateWatchdog, Y4NGZCompany"; private static bool _resolved; private static MethodInfo _push; private static MethodInfo _pop; private static bool _held; internal static void Push() { if (_held || !TryResolve()) { return; } try { _push.Invoke(null, null); _held = true; } catch { } } internal static void Pop() { if (!_held) { return; } _held = false; if (!TryResolve()) { return; } try { _pop.Invoke(null, null); } catch { } } private static bool TryResolve() { if (_resolved) { if (_push != null) { return _pop != null; } return false; } _resolved = true; try { Type type = Type.GetType("Y4NGZCompany.Experience.Diagnostics.LocalInputStateWatchdog, Y4NGZCompany", throwOnError: false); if (type == null) { return false; } _push = type.GetMethod("PushExternalMenuLatch", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); _pop = type.GetMethod("PopExternalMenuLatch", BindingFlags.Static | BindingFlags.Public, null, Type.EmptyTypes, null); } catch { _push = null; _pop = null; } if (_push != null) { return _pop != null; } return false; } } public class IngameKeybinds : LcInputActions { [InputAction("/p", Name = "PurchaseMenu")] public InputAction PurchaseMenu { get; set; } [InputAction("/g", Name = "[Y4NGZ] Shadow Step")] public InputAction ShadowStep { get; set; } [InputAction("/q", Name = "[Y4NGZ] Foreman Ping")] public InputAction ForemanPing { get; set; } [InputAction("/r", Name = "[Y4NGZ] Rally Call")] public InputAction RallyCall { get; set; } [InputAction("/y", Name = "[Y4NGZ] Field Tablet")] public InputAction FieldTablet { get; set; } [InputAction("/j", Name = "[Y4NGZ] Command Net Transmit")] public InputAction CommandNetTransmit { get; set; } [InputAction("/v", Name = "[Y4NGZ] Worklight Beacon")] public InputAction WorklightBeacon { get; set; } [InputAction("/middleButton", Name = "[Y4NGZ] Courier Drone Command")] public InputAction CourierDroneCommand { get; set; } [InputAction("/escape", Name = "[Y4NGZ] Player Menu Close")] public InputAction PlayerMenuClose { get; set; } [InputAction("/q", Name = "[Y4NGZ] Player Menu Previous Section")] public InputAction PlayerMenuPreviousSection { get; set; } [InputAction("/e", Name = "[Y4NGZ] Player Menu Next Section")] public InputAction PlayerMenuNextSection { get; set; } [InputAction("/w", Name = "[Y4NGZ] Player Menu Up")] public InputAction PlayerMenuUp { get; set; } [InputAction("/s", Name = "[Y4NGZ] Player Menu Down")] public InputAction PlayerMenuDown { get; set; } [InputAction("/a", Name = "[Y4NGZ] Player Menu Left")] public InputAction PlayerMenuLeft { get; set; } [InputAction("/d", Name = "[Y4NGZ] Player Menu Right")] public InputAction PlayerMenuRight { get; set; } [InputAction("/enter", Name = "[Y4NGZ] Player Menu Select")] public InputAction PlayerMenuSelect { get; set; } [InputAction("/leftArrow", Name = "[Y4NGZ] Tablet Previous Tab")] public InputAction TabletPreviousTab { get; set; } [InputAction("/rightArrow", Name = "[Y4NGZ] Tablet Next Tab")] public InputAction TabletNextTab { get; set; } [InputAction("/upArrow", Name = "[Y4NGZ] Tablet Up")] public InputAction TabletUp { get; set; } [InputAction("/downArrow", Name = "[Y4NGZ] Tablet Down")] public InputAction TabletDown { get; set; } [InputAction("/enter", Name = "[Y4NGZ] Tablet Activate")] public InputAction TabletActivate { get; set; } [InputAction("/leftButton", Name = "[Y4NGZ] Tablet Primary Action")] public InputAction TabletPrimaryAction { get; set; } [InputAction("/backspace", Name = "[Y4NGZ] Tablet Back")] public InputAction TabletBack { get; set; } [InputAction("/equals", Name = "[Y4NGZ] Tablet Zoom In")] public InputAction TabletZoomIn { get; set; } [InputAction("/minus", Name = "[Y4NGZ] Tablet Zoom Out")] public InputAction TabletZoomOut { get; set; } [InputAction("/escape", Name = "[Y4NGZ] Drone Pilot Exit")] public InputAction DronePilotExit { get; set; } [InputAction("/space", Name = "[Y4NGZ] Drone Pilot Ascend")] public InputAction DronePilotAscend { get; set; } [InputAction("/leftCtrl", Name = "[Y4NGZ] Drone Pilot Descend")] public InputAction DronePilotDescend { get; set; } [InputAction("/leftButton", Name = "[Y4NGZ] Drone Pilot Flame")] public InputAction DronePilotFlame { get; set; } [InputAction("/rightButton", Name = "[Y4NGZ] Drone Pilot Grenade")] public InputAction DronePilotGrenade { get; set; } [InputAction("/e", Name = "[Y4NGZ] Drone Pilot Lift")] public InputAction DronePilotLift { get; set; } [InputAction("/f", Name = "[Y4NGZ] Drone Pilot Light")] public InputAction DronePilotLight { get; set; } [InputAction("/1", Name = "[Y4NGZ] Hotbar Slot 1")] public InputAction HotbarSlot1 { get; set; } [InputAction("/2", Name = "[Y4NGZ] Hotbar Slot 2")] public InputAction HotbarSlot2 { get; set; } [InputAction("/3", Name = "[Y4NGZ] Hotbar Slot 3")] public InputAction HotbarSlot3 { get; set; } [InputAction("/4", Name = "[Y4NGZ] Hotbar Slot 4")] public InputAction HotbarSlot4 { get; set; } [InputAction("/5", Name = "[Y4NGZ] Hotbar Slot 5")] public InputAction HotbarSlot5 { get; set; } [InputAction("/6", Name = "[Y4NGZ] Hotbar Slot 6")] public InputAction HotbarSlot6 { get; set; } [InputAction("/7", Name = "[Y4NGZ] Hotbar Slot 7")] public InputAction HotbarSlot7 { get; set; } internal IEnumerable AllActions { get { yield return PurchaseMenu; yield return ShadowStep; yield return ForemanPing; yield return RallyCall; yield return FieldTablet; yield return CommandNetTransmit; yield return WorklightBeacon; yield return CourierDroneCommand; yield return PlayerMenuClose; yield return PlayerMenuPreviousSection; yield return PlayerMenuNextSection; yield return PlayerMenuUp; yield return PlayerMenuDown; yield return PlayerMenuLeft; yield return PlayerMenuRight; yield return PlayerMenuSelect; yield return TabletPreviousTab; yield return TabletNextTab; yield return TabletUp; yield return TabletDown; yield return TabletActivate; yield return TabletPrimaryAction; yield return TabletBack; yield return TabletZoomIn; yield return TabletZoomOut; yield return DronePilotExit; yield return DronePilotAscend; yield return DronePilotDescend; yield return DronePilotFlame; yield return DronePilotGrenade; yield return DronePilotLift; yield return DronePilotLight; yield return HotbarSlot1; yield return HotbarSlot2; yield return HotbarSlot3; yield return HotbarSlot4; yield return HotbarSlot5; yield return HotbarSlot6; yield return HotbarSlot7; } } internal IEnumerable GameplayReservationActions { get { yield return PurchaseMenu; yield return ShadowStep; yield return ForemanPing; yield return RallyCall; yield return FieldTablet; yield return CommandNetTransmit; yield return WorklightBeacon; yield return CourierDroneCommand; yield return HotbarSlot1; yield return HotbarSlot2; yield return HotbarSlot3; yield return HotbarSlot4; yield return HotbarSlot5; yield return HotbarSlot6; yield return HotbarSlot7; } } } internal static class LegacyKeybindMigration { private readonly struct LegacyBinding { internal ConfigEntry Entry { get; } internal InputAction Action { get; } internal string Label { get; } internal LegacyBinding(ConfigEntry entry, InputAction action, string label) { Entry = entry; Action = action; Label = label; } } private readonly struct PendingOverride { internal InputAction Action { get; } internal int BindingIndex { get; } internal string Path { get; } internal BindingOverride Record { get; } internal PendingOverride(InputAction action, int bindingIndex, string path, BindingOverride record) { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) Action = action; BindingIndex = bindingIndex; Path = path; Record = record; } } private const string ActionMapId = "com.y4ngz.upgrades.IngameKeybinds"; internal static bool TryMigrate(IngameKeybinds actions, ConfigEntry shadowStep, ConfigEntry ping, ConfigEntry fieldTablet, ConfigEntry commandNet, ConfigEntry worklight, ConfigEntry dronePointer) { //IL_01f5: 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_01fc: Unknown result type (might be due to invalid IL or missing references) //IL_00e9: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_01d1: Unknown result type (might be due to invalid IL or missing references) //IL_02a7: Unknown result type (might be due to invalid IL or missing references) if (actions == null) { return false; } LegacyBinding[] array = new LegacyBinding[6] { new LegacyBinding(shadowStep, actions.ShadowStep, "Shadow Step"), new LegacyBinding(ping, actions.ForemanPing, "Foreman Ping"), new LegacyBinding(fieldTablet, actions.FieldTablet, "Field Tablet"), new LegacyBinding(commandNet, actions.CommandNetTransmit, "Command Net"), new LegacyBinding(worklight, actions.WorklightBeacon, "Worklight Beacon"), new LegacyBinding(dronePointer, actions.CourierDroneCommand, "Courier Drone Command") }; List list = new List(); for (int i = 0; i < array.Length; i++) { LegacyBinding legacyBinding = array[i]; if (legacyBinding.Entry == null || legacyBinding.Action == null) { continue; } int num = UpgradeInput.FindKeyboardMouseBindingIndex(legacyBinding.Action); if (num < 0) { continue; } InputBinding val = legacyBinding.Action.bindings[num]; if (((InputBinding)(ref val)).hasOverrides) { continue; } string text = ToControlPath(legacyBinding.Entry.Value); if (string.IsNullOrWhiteSpace(text)) { ManualLogSource log = Y4NGZUpgrades.Plugin.Log; if (log != null) { log.LogWarning((object)("[Config] Could not migrate " + legacyBinding.Label + " key '" + legacyBinding.Entry.Value + "'. Its InputUtils default will be used; the original remains in the config backup.")); } } else if (!string.Equals(((InputBinding)(ref val)).effectivePath, text, StringComparison.OrdinalIgnoreCase)) { list.Add(new PendingOverride(legacyBinding.Action, num, text, new BindingOverride { action = legacyBinding.Action.name, origPath = ((InputBinding)(ref val)).path, path = text, groups = ((InputBinding)(ref val)).groups })); } } if (list.Count == 0) { return true; } try { BindingOverrideType val2 = ResolveStorageType(); string jsonPath = BindingOverrideTypeExtensions.GetJsonPath(val2, "com.y4ngz.upgrades.IngameKeybinds"); BindingOverrides val3 = LoadOverrides(jsonPath); for (int j = 0; j < list.Count; j++) { val3.overrides.Add(list[j].Record); } WriteAtomically(jsonPath, val3.AsJson()); for (int k = 0; k < list.Count; k++) { PendingOverride pendingOverride = list[k]; InputActionRebindingExtensions.ApplyBindingOverride(pendingOverride.Action, pendingOverride.BindingIndex, pendingOverride.Path); } ManualLogSource log2 = Y4NGZUpgrades.Plugin.Log; if (log2 != null) { log2.LogInfo((object)$"[Config] Migrated {list.Count} legacy control override(s) into InputUtils {val2} bindings."); } return true; } catch (Exception ex) { ManualLogSource log3 = Y4NGZUpgrades.Plugin.Log; if (log3 != null) { log3.LogWarning((object)("[Config] Legacy controls remain in Y4NGZUpgrades.cfg because InputUtils override persistence failed safely: " + ex.Message)); } return false; } } private static BindingOverrideType ResolveStorageType() { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 ConfigEntry bindingOverridePriority = InputUtilsConfig.bindingOverridePriority; if (bindingOverridePriority != null && (int)bindingOverridePriority.Value == 2) { return (BindingOverrideType)0; } return (BindingOverrideType)1; } private static BindingOverrides LoadOverrides(string path) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (!File.Exists(path)) { return new BindingOverrides(); } string text = File.ReadAllText(path); if (!string.IsNullOrWhiteSpace(text)) { return BindingOverrides.FromJson(text); } return new BindingOverrides(); } private static void WriteAtomically(string destination, string json) { string directoryName = Path.GetDirectoryName(destination); if (!string.IsNullOrWhiteSpace(directoryName)) { Directory.CreateDirectory(directoryName); } string text = destination + ".y4ngz-migration.tmp"; try { File.WriteAllText(text, json, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false)); if (File.Exists(destination)) { File.Replace(text, destination, null); } else { File.Move(text, destination); } } finally { if (File.Exists(text)) { File.Delete(text); } } } private unsafe static string ToControlPath(string value) { //IL_029a: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(value)) { return null; } string text = value.Trim(); if (text.StartsWith("/", StringComparison.OrdinalIgnoreCase) || text.StartsWith("/", StringComparison.OrdinalIgnoreCase)) { return text; } switch (text.ToLowerInvariant()) { case "middlebutton": case "middlemouse": case "mousemiddle": case "mmb": return "/middleButton"; case "rightbutton": case "rmb": case "mouseright": case "rightmouse": return "/rightButton"; case "mouseforward": case "mouse4": case "m4": case "forwardbutton": return "/forwardButton"; case "backbutton": case "mouse5": case "m5": case "mouseback": return "/backButton"; default: { if (!Enum.TryParse(text, ignoreCase: true, out Key result) || (int)result == 0) { return null; } string text2 = ((object)(*(Key*)(&result))/*cast due to .constrained prefix*/).ToString(); if (text2.StartsWith("Digit", StringComparison.OrdinalIgnoreCase)) { text2 = text2.Substring("Digit".Length); } else if (text2.Length > 0) { text2 = char.ToLowerInvariant(text2[0]) + text2.Substring(1); } return "/" + text2; } } } } internal static class MenuAudio { private const string SfxFolder = "MenuSfx"; private const string ClickFile = "click.wav"; private const string ExitFile = "exit.wav"; private const string DenyFile = "deny.wav"; private static readonly string[] NavFiles = new string[2] { "menu01.wav", "menu02.wav" }; private static readonly string[] PurchaseFiles = new string[4] { "upgrade01.wav", "upgrade02.wav", "upgrade03.wav", "upgrade04.wav" }; private const float ClickVolume = 0.3f; private const float NavVolume = 0.36f; private const float ExitVolume = 0.4f; private const float PurchaseVolume = 0.44f; private const float DenyVolume = 0.4f; private static AudioClip _clickClip; private static AudioClip _exitClip; private static AudioClip _denyClip; private static readonly AudioClip[] _navClips = (AudioClip[])(object)new AudioClip[NavFiles.Length]; private static readonly AudioClip[] _purchaseClips = (AudioClip[])(object)new AudioClip[PurchaseFiles.Length]; private static bool _loadStarted; private static AudioSource _fallbackSource; internal static void Preload() { if (!_loadStarted) { MonoBehaviour instance = (MonoBehaviour)(object)Plugin.Instance; if (!((Object)(object)instance == (Object)null) && ((Behaviour)instance).isActiveAndEnabled) { _loadStarted = true; instance.StartCoroutine(LoadAll()); } } } internal static void PlayClick() { if (!TryPlay(_clickClip, 0.3f)) { UI.PlayHover(); } } internal static void PlayNav() { if (!TryPlay(PickRandom(_navClips), 0.36f)) { UI.PlayHover(); } } internal static void PlayExit() { if (!TryPlay(_exitClip, 0.4f)) { UI.PlayClose(); } } internal static void PlayDeny() { if (!TryPlay(_denyClip, 0.4f) && !UI.PlayDeny()) { TryPlay(_exitClip, 0.4f); } } internal static void PlayPurchase(int tier) { int num = ((_purchaseClips.Length != 0) ? ((Mathf.Max(1, tier) - 1) % _purchaseClips.Length) : 0); if (!TryPlay((num >= 0 && num < _purchaseClips.Length) ? _purchaseClips[num] : null, 0.44f)) { UI.PlayPurchase(); } } internal static void PlayPurchaseRandom() { if (!TryPlay(PickRandom(_purchaseClips), 0.44f)) { UI.PlayPurchase(); } } private static AudioClip PickRandom(AudioClip[] pool) { if (pool == null || pool.Length == 0) { return null; } int num = Random.Range(0, pool.Length); for (int i = 0; i < pool.Length; i++) { AudioClip val = pool[(num + i) % pool.Length]; if ((Object)(object)val != (Object)null) { return val; } } return null; } private static bool TryPlay(AudioClip clip, float volume) { if ((Object)(object)clip == (Object)null) { return false; } float num = volume * Mathf.Clamp01((Plugin.MenuSoundVolume != null) ? Plugin.MenuSoundVolume.Value : 1f); if (num <= 0.001f) { return true; } HUDManager instance = HUDManager.Instance; if ((Object)(object)instance != (Object)null && (Object)(object)instance.UIAudio != (Object)null) { instance.UIAudio.PlayOneShot(clip, num); return true; } AudioSource val = EnsureFallbackSource(); if ((Object)(object)val == (Object)null) { return false; } val.PlayOneShot(clip, num); return true; } private static AudioSource EnsureFallbackSource() { //IL_0018: 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_0023: Expected O, but got Unknown if ((Object)(object)_fallbackSource != (Object)null) { return _fallbackSource; } GameObject val = new GameObject("Y4NGZ_MenuAudio"); Object.DontDestroyOnLoad((Object)val); _fallbackSource = val.AddComponent(); _fallbackSource.playOnAwake = false; _fallbackSource.loop = false; _fallbackSource.spatialBlend = 0f; return _fallbackSource; } private static IEnumerator LoadAll() { yield return LoadClip("click.wav", delegate(AudioClip clip) { _clickClip = clip; }); yield return LoadClip("exit.wav", delegate(AudioClip clip) { _exitClip = clip; }); yield return LoadClip("deny.wav", delegate(AudioClip clip) { _denyClip = clip; }, required: false); for (int i = 0; i < NavFiles.Length; i++) { int index = i; yield return LoadClip(NavFiles[index], delegate(AudioClip clip) { _navClips[index] = clip; }); } for (int i = 0; i < PurchaseFiles.Length; i++) { int index2 = i; yield return LoadClip(PurchaseFiles[index2], delegate(AudioClip clip) { _purchaseClips[index2] = clip; }); } } private static IEnumerator LoadClip(string fileName, Action assign, bool required = true) { string path = ResolvePath(fileName); if (string.IsNullOrEmpty(path)) { if (required) { ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogWarning((object)("[PMenu] Menu sound missing: Assets/UI/MenuSfx/" + fileName)); } } yield break; } UnityWebRequest request = UnityWebRequestMultimedia.GetAudioClip(new Uri(path).AbsoluteUri, (AudioType)20); try { yield return request.SendWebRequest(); if ((int)request.result != 1) { ManualLogSource customLogger2 = Plugin.CustomLogger; if (customLogger2 != null) { customLogger2.LogWarning((object)("[PMenu] Failed loading menu sound '" + path + "': " + request.error)); } yield break; } AudioClip content = DownloadHandlerAudioClip.GetContent(request); if ((Object)(object)content == (Object)null) { yield break; } ((Object)content).name = "Y4NGZ_Menu_" + Path.GetFileNameWithoutExtension(fileName); assign(content); } finally { ((IDisposable)request)?.Dispose(); } } private static string ResolvePath(string fileName) { string text = Path.GetDirectoryName(typeof(MenuAudio).Assembly.Location) ?? string.Empty; string[] array = new string[4] { Path.Combine(text, "Assets", "UI", "MenuSfx", fileName), Path.Combine(text, "InteractiveAssets", "UI", "MenuSfx", fileName), Path.Combine(Paths.PluginPath, "y4ngz-Y4NGZUpgrades", "Assets", "UI", "MenuSfx", fileName), Path.Combine(Paths.PluginPath, "Y4NGZUpgrades", "Assets", "UI", "MenuSfx", fileName) }; foreach (string text2 in array) { if (File.Exists(text2)) { return text2; } } return null; } } public class MenuController : MonoBehaviour { private GameObject _root; private CanvasGroup _canvasGroup; private RectTransform _panelRt; private bool _closing; private int _frameOpenedOn = -1; public static bool IsOpen; private const float OpenDuration = 0.18f; private const float CloseDuration = 0.12f; private static readonly HashSet _loggedKeyboardFaults = new HashSet(StringComparer.Ordinal); private static readonly string[] _objectFieldsToClear = new string[5] { "_selectedEmoteForPurchase", "_previewingEmote", "_selectedCosmeticForPurchase", "_selectedCosmeticLabel", "_selectedCosmeticTypeLabel" }; private static readonly string[] _previewFieldsToPreserve = new string[11] { "_employeePreviewTexture", "_employeePreviewRoot", "_employeePreviewCamera", "_employeePreviewTicker", "_employeePreviewModel", "_previewBodyMesh", "_previewSourceMesh", "_previewSourcePlayer", "_previewSpineRoot", "_previewReplacementSource", "_previewReplacementRejected" }; public void Init(GameObject root) { _root = root; _canvasGroup = _root.GetComponent(); if ((Object)(object)_canvasGroup == (Object)null) { _canvasGroup = _root.AddComponent(); } Transform val = _root.transform.Find("Panel"); if ((Object)(object)val != (Object)null) { _panelRt = ((Component)val).GetComponent(); } IsOpen = true; _frameOpenedOn = Time.frameCount; ((MonoBehaviour)this).StartCoroutine(AnimateOpen()); } private void Update() { if (_closing || Time.frameCount == _frameOpenedOn) { return; } bool flag = false; try { flag = PurchaseMenu.IsTextInputFocused(); } catch (Exception e) { LogKeyboardFaultOnce(e); } IngameKeybinds keybinds = Plugin.Keybinds; if (UpgradeInput.WasPressed(keybinds?.PlayerMenuClose) || (!flag && UpgradeInput.WasPressed(keybinds?.PurchaseMenu))) { CloseMenu(); return; } try { PurchaseMenu.HandleKeyboardNavigation(); } catch (Exception e2) { LogKeyboardFaultOnce(e2); } } private static void LogKeyboardFaultOnce(Exception e) { if (e == null) { return; } string item = e.GetType().FullName + "|" + e.Message + "|" + e.StackTrace; if (_loggedKeyboardFaults.Add(item)) { ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogError((object)$"[PMenu] Keyboard navigation failed: {e}"); } } } private void OnDisable() { try { ReleaseVanillaMenuLatch(); } catch { } IsOpen = false; } private static void ReleaseVanillaMenuLatch() { PlayerControllerB val = StartOfRound.Instance?.localPlayerController; if ((Object)(object)val != (Object)null && (Object)(object)val.quickMenuManager != (Object)null) { val.quickMenuManager.isMenuOpen = false; } CompanyInputWatchdogLatch.Pop(); } private void ApplyMenuScale() { //IL_0014: 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) if ((Object)(object)_panelRt != (Object)null) { ((Transform)_panelRt).localScale = Vector3.one * PurchaseMenu.MenuScale; } } private IEnumerator AnimateOpen() { _canvasGroup.alpha = 0f; ApplyMenuScale(); float t = 0f; while (t < 0.18f) { t += Time.unscaledDeltaTime; float num = Mathf.Clamp01(t / 0.18f); float alpha = 1f - Mathf.Pow(1f - num, 3f); _canvasGroup.alpha = alpha; yield return null; } _canvasGroup.alpha = 1f; ApplyMenuScale(); } public void CloseMenu() { if (!_closing) { _closing = true; MenuAudio.PlayExit(); ((MonoBehaviour)this).StartCoroutine(AnimateClose()); } } private IEnumerator AnimateClose() { float startAlpha = (((Object)(object)_canvasGroup != (Object)null) ? _canvasGroup.alpha : 1f); float t = 0f; while (t < 0.12f) { t += Time.unscaledDeltaTime; float num = Mathf.Clamp01(t / 0.12f); float num2 = num * num * num; if ((Object)(object)_canvasGroup != (Object)null) { _canvasGroup.alpha = Mathf.Lerp(startAlpha, 0f, num2); } yield return null; } try { ReleaseVanillaMenuLatch(); Cursor.visible = false; Cursor.lockState = (CursorLockMode)1; } catch { } IsOpen = false; try { typeof(PurchaseMenu).GetMethod("StopEmotePreview", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null); } catch { } try { typeof(PurchaseMenu).GetMethod("HideEmployeePreview", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null); } catch { } try { PurchaseMenu.ClearKeyboardFocus(); } catch { } ClearPurchaseMenuStatics(); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } } private static bool ShouldPreservePurchaseMenuStatic(string fieldName) { for (int i = 0; i < _previewFieldsToPreserve.Length; i++) { if (fieldName == _previewFieldsToPreserve[i]) { return true; } } return false; } private static void ClearPurchaseMenuStatics() { FieldInfo[] fields = typeof(PurchaseMenu).GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (fieldInfo.IsLiteral || fieldInfo.IsInitOnly || ShouldPreservePurchaseMenuStatic(fieldInfo.Name)) { continue; } if (typeof(Object).IsAssignableFrom(fieldInfo.FieldType)) { fieldInfo.SetValue(null, null); continue; } for (int j = 0; j < _objectFieldsToClear.Length; j++) { if (fieldInfo.Name == _objectFieldsToClear[j]) { fieldInfo.SetValue(null, null); break; } } } } } internal sealed class CurrencyManager { internal static readonly CurrencyManager Instance = new CurrencyManager(); public int CurrencyAmount { get { return ProgressionApi.AvailableTokens; } set { ProgressionApi.SetUpgradeCurrency(value); } } public int TokensAmount { get { return CurrencyAmount; } set { CurrencyAmount = value; } } public int TokenAmount { get { return CurrencyAmount; } set { CurrencyAmount = value; } } public int MarksAmount { get { return CurrencyAmount; } set { CurrencyAmount = value; } } public int BxpAmount { get { return CurrencyAmount; } set { CurrencyAmount = value; } } public bool TrySpend(int amount) { if (amount <= 0) { return true; } if (ProgressionApi.AvailableTokens < amount) { return false; } ProgressionApi.AddTokens(-amount); return true; } public void SetCurrencyAmount(int amount) { CurrencyAmount = amount; } public void SetTokensAmount(int amount) { CurrencyAmount = amount; } public void SetTokenAmount(int amount) { CurrencyAmount = amount; } public void SetMarksAmount(int amount) { CurrencyAmount = amount; } public void SetBxpAmount(int amount) { CurrencyAmount = amount; } public int GetCurrencyAmountFromCredits(int credits) { return Mathf.Max(0, credits); } public bool RequestPlayerTokenTrade(ulong targetId, int tokenAmount) { ManualLogSource log = Y4NGZUpgrades.Interactive.Plugin.Log; if (log != null) { log.LogWarning((object)$"[Y4NGZ Trade] Refused transfer of {tokenAmount} token(s) to {targetId}: trade sync is not available yet."); } return false; } } internal static class UpgradeApi { public static IReadOnlyList GetUpgradeNodes() { return Y4NGZUpgradeManager.GetUpgradeNodes(); } public static Y4NGZUpgradePurchaseResult TriggerUpgradeRankup(Y4NGZUpgradeNode node, int quotedPrice = -1) { if (node == null) { return Y4NGZUpgradePurchaseResult.UnknownUpgrade; } Y4NGZUpgradePurchaseResult y4NGZUpgradePurchaseResult = Y4NGZUpgradeManager.Purchase(node.Id, quotedPrice); if (y4NGZUpgradePurchaseResult != Y4NGZUpgradePurchaseResult.Success) { ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogWarning((object)$"[Y4NGZMenu] Purchase of '{node.Name}' returned {y4NGZUpgradePurchaseResult}."); } } return y4NGZUpgradePurchaseResult; } } [Serializable] internal class PlayerLevelData { public List suits = new List(); public List cosmetics = new List(); } internal static class PlayerLevelStore { private static PlayerLevelData _data; private static string _key; private static string SaveDir => Path.Combine(Paths.ConfigPath, "Y4NGZPlayerLevel"); private static bool TryGetCurrentKey(out string key) { return SaveKey.TryGetCurrent(out key); } private static string GetPath(string key) { return Path.Combine(SaveDir, SanitizeFileName(key) + ".json"); } private static string SanitizeFileName(string raw) { char[] invalidFileNameChars = Path.GetInvalidFileNameChars(); char[] array = raw.ToCharArray(); for (int i = 0; i < array.Length; i++) { if (Array.IndexOf(invalidFileNameChars, array[i]) >= 0) { array[i] = '_'; } } return new string(array); } public static PlayerLevelData Get() { if (!TryGetCurrentKey(out var key)) { _key = null; _data = new PlayerLevelData(); return _data; } if (_data != null && _key == key) { return _data; } _key = key; string path = GetPath(key); AdoptLegacyBareSlotFile(key, path); if (File.Exists(path)) { try { _data = JsonUtility.FromJson(File.ReadAllText(path)) ?? new PlayerLevelData(); } catch { _data = new PlayerLevelData(); } } else { _data = new PlayerLevelData(); } PlayerLevelData data = _data; if (data.suits == null) { data.suits = new List(); } data = _data; if (data.cosmetics == null) { data.cosmetics = new List(); } return _data; } private static void AdoptLegacyBareSlotFile(string key, string identityPath) { try { if (File.Exists(identityPath) || key.IndexOf('#') < 0 || !SaveIdentityCleanupPolicy.TryGetManagedSlotName(key, out var saveFileName)) { return; } string path = GetPath(saveFileName); if (File.Exists(path)) { if (!Directory.Exists(SaveDir)) { Directory.CreateDirectory(SaveDir); } File.Move(path, identityPath); ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogInfo((object)("[PlayerLevelStore] adopted legacy '" + saveFileName + ".json' into '" + Path.GetFileName(identityPath) + "'.")); } } } catch (Exception ex) { ManualLogSource customLogger2 = Plugin.CustomLogger; if (customLogger2 != null) { customLogger2.LogWarning((object)("[PlayerLevelStore] legacy adoption failed: " + ex.Message)); } } } public static void Save() { if (_data == null || string.IsNullOrWhiteSpace(_key)) { return; } try { if (!Directory.Exists(SaveDir)) { Directory.CreateDirectory(SaveDir); } File.WriteAllText(GetPath(_key), JsonUtility.ToJson((object)_data, true)); } catch (Exception ex) { ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogWarning((object)("[PlayerLevelStore] save failed: " + ex.Message)); } } } public static void ResetCurrentSave() { if (!SaveKey.TryGetCurrentExistingOrSlot(out var key)) { _key = null; _data = new PlayerLevelData(); } else { DeleteForKey(key); } } internal static bool DeleteForKey(string key) { bool result = false; try { string path = GetPath(key); if (File.Exists(path)) { File.Delete(path); result = true; } } catch (Exception ex) { ManualLogSource customLogger = Plugin.CustomLogger; if (customLogger != null) { customLogger.LogWarning((object)("[PlayerLevelStore] reset failed: " + ex.Message)); } } if (string.Equals(_key, key, StringComparison.OrdinalIgnoreCase)) { _key = null; _data = new PlayerLevelData(); } return result; } public static void Reload() { _data = null; _key = null; } } public class PlayerMenuHint : MonoBehaviour { private GameObject _canvasGo; private TMP_Text _label; private string _bindingPath; private void Update() { if (EnsureCanvas()) { RefreshBindingLabel(); _canvasGo.SetActive(ShouldShow()); } } private bool ShouldShow() { string reason; return Plugin.CanOpenPurchaseMenu(out reason); } private bool EnsureCanvas() { //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Expected O, but got Unknown //IL_0089: 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) //IL_00b3: 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_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_canvasGo != (Object)null) { return true; } if ((Object)(object)HUDManager.Instance == (Object)null || (Object)(object)HUDManager.Instance.playerScreenTexture == (Object)null) { return false; } Canvas canvas = ((Graphic)HUDManager.Instance.playerScreenTexture).canvas; if ((Object)(object)canvas == (Object)null) { return false; } _canvasGo = new GameObject("Y4NGZ_PlayerMenuHint"); _canvasGo.transform.SetParent(((Component)canvas).transform, false); RectTransform obj = _canvasGo.AddComponent(); obj.anchorMin = new Vector2(0.5f, 0f); obj.anchorMax = new Vector2(0.5f, 0f); obj.pivot = new Vector2(0.5f, 0f); obj.anchoredPosition = new Vector2(0f, 120f); obj.sizeDelta = new Vector2(420f, 30f); _label = (TMP_Text)(object)_canvasGo.AddComponent(); _label.text = "Press [P] for player menu"; _label.fontSize = 14f; _label.alignment = (TextAlignmentOptions)514; ((Graphic)_label).color = new Color(1f, 1f, 1f, 0.55f); ((Graphic)_label).raycastTarget = false; _label.enableWordWrapping = false; TMP_FontAsset terminalFont = UI.GetTerminalFont(); if ((Object)(object)terminalFont != (Object)null) { _label.font = terminalFont; } RefreshBindingLabel(); return true; } private void RefreshBindingLabel() { if (!((Object)(object)_label == (Object)null)) { string text = UpgradeInput.EffectivePath(Plugin.Keybinds?.PurchaseMenu); if (!string.Equals(_bindingPath, text, StringComparison.Ordinal)) { _bindingPath = text; string text2 = UpgradeInput.DisplayLabel(Plugin.Keybinds?.PurchaseMenu, "P"); _label.text = "Press [" + text2 + "] for player menu"; } } } private void OnDestroy() { if ((Object)(object)_canvasGo != (Object)null) { Object.Destroy((Object)(object)_canvasGo); } _canvasGo = null; _label = null; } } internal sealed class Plugin : MonoBehaviour { public static ManualLogSource CustomLogger; internal static Y4NGZConfigScope ConfigScope; internal static IngameKeybinds Keybinds; public static ConfigEntry onlyInOrbit; public static ConfigEntry onlyOnShip; public static ConfigEntry extendedLog; public static ConfigEntry SuitPrice; public static ConfigEntry CosmeticPrice; public static ConfigEntry MenuSoundVolume; public static ConfigEntry MenuScale; private int _lastPressFrame = -1; internal static Plugin Instance { get; private set; } internal static void Initialize(Y4NGZConfigScope config, ManualLogSource logger, MonoBehaviour host) { if (!((Object)(object)host == (Object)null)) { CustomLogger = logger; ConfigScope = config; Plugin plugin = ((Component)host).GetComponent(); if ((Object)(object)plugin == (Object)null) { plugin = ((Component)host).gameObject.AddComponent(); } Instance = plugin; plugin.Configure(); } } internal static void Shutdown() { ExtraSlotManager.UnbindHotbarActions(Keybinds); Keybinds = null; Instance = null; } private void Configure() { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Expected O, but got Unknown ConfigSetup(); if (Keybinds == null) { Keybinds = new IngameKeybinds(); ExtraSlotManager.BindHotbarActions(Keybinds); } MenuAudio.Preload(); if ((Object)(object)GameObject.Find("Y4NGZ_PlayerMenuHintHost") == (Object)null) { GameObject val = new GameObject("Y4NGZ_PlayerMenuHintHost"); Object.DontDestroyOnLoad((Object)val); val.AddComponent(); } ManualLogSource customLogger = CustomLogger; if (customLogger != null) { customLogger.LogInfo((object)"Y4NGZ player menu host initialized."); } } public static void ExtendedLogging(string msg, LogLevel level = (LogLevel)16) { //IL_001d: Unknown result type (might be due to invalid IL or missing references) if (extendedLog != null && extendedLog.Value) { ManualLogSource customLogger = CustomLogger; if (customLogger != null) { customLogger.Log(level, (object)msg); } } } public void ConfigSetup() { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Expected O, but got Unknown //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Expected O, but got Unknown //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Expected O, but got Unknown //IL_01d6: Unknown result type (might be due to invalid IL or missing references) //IL_01fc: Expected O, but got Unknown onlyInOrbit = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Availability", "Only In Orbit", false, "Allow the player menu only while the ship is in orbit.", new LegacyConfigKey("Player Menu", "Only In Orbit")); onlyOnShip = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Availability", "Only On Ship", true, "Allow the player menu only while the local player is aboard the ship.", new LegacyConfigKey("Player Menu", "Only On Ship")); extendedLog = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Troubleshooting", "Extended Logging", false, "Write extra player-menu diagnostics to the BepInEx log.", new LegacyConfigKey("Player Menu", "Extended Logging")); SuitPrice = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Appearance Prices", "Suit Cost", 5, new ConfigDescription("Upgrade-token cost to unlock one suit.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty()), new LegacyConfigKey("Player Cosmetics - Prices", "Suit Price")); CosmeticPrice = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Appearance Prices", "Cosmetic Cost", 3, new ConfigDescription("Upgrade-token cost to unlock one MoreCompany cosmetic.", (AcceptableValueBase)(object)new AcceptableValueRange(0, 999), Array.Empty()), new LegacyConfigKey("Player Cosmetics - Prices", "Cosmetic Price")); MenuSoundVolume = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Appearance", "Sound Volume", 1f, new ConfigDescription("Volume multiplier for player-menu clicks, section changes, purchases, and exit sounds.", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 1f), Array.Empty()), new LegacyConfigKey("Player Menu", "Menu Sound Volume")); MenuScale = Y4NGZConfigFiles.BindMigrated(ConfigScope, "Appearance", "Menu Scale", 1f, new ConfigDescription("Size multiplier for the EMPLOYEE FILE menu. Applied the next time the menu opens.", (AcceptableValueBase)(object)new AcceptableValueRange(0.75f, 1.5f), Array.Empty()), new LegacyConfigKey("Player Menu", "Menu Scale")); if (SuitPrice.Value == 50) { SuitPrice.Value = 5; } if (CosmeticPrice.Value == 25) { CosmeticPrice.Value = 3; } } public void tryShowMenu() { if (!CanOpenPurchaseMenu(out var reason)) { ExtendedLogging("[PMenu] P press ignored: " + reason, (LogLevel)16); return; } try { MenuAudio.Preload(); PurchaseMenu.initMenu(); UiTheme.Refresh(); } catch (Exception arg) { ManualLogSource customLogger = CustomLogger; if (customLogger != null) { customLogger.LogError((object)$"[PMenu] Failed to open purchase menu: {arg}"); } } } internal static bool CanOpenPurchaseMenu(out string reason) { reason = string.Empty; if (MenuController.IsOpen) { reason = "menu already open"; return false; } StartOfRound instance = StartOfRound.Instance; if ((Object)(object)instance == (Object)null) { reason = "StartOfRound unavailable"; return false; } PlayerControllerB localPlayerController = instance.localPlayerController; if ((Object)(object)localPlayerController == (Object)null) { reason = "local player unavailable"; return false; } if ((Object)(object)localPlayerController.quickMenuManager != (Object)null && localPlayerController.quickMenuManager.isMenuOpen) { reason = "quick menu open"; return false; } if (onlyInOrbit != null && onlyInOrbit.Value && !instance.inShipPhase) { reason = "only-in-orbit enabled while not in orbit"; return false; } if (onlyOnShip != null && onlyOnShip.Value && !IsPlayerShipSide(instance, localPlayerController)) { reason = "only-on-ship enabled while not ship-side"; return false; } if (localPlayerController.inTerminalMenu) { reason = "terminal open"; return false; } if (localPlayerController.isTypingChat) { reason = "chat typing"; return false; } return true; } private static bool IsPlayerShipSide(StartOfRound round, PlayerControllerB player) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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) if ((Object)(object)round == (Object)null || (Object)(object)player == (Object)null) { return false; } if (round.inShipPhase || player.isInHangarShipRoom || player.isInElevator) { return true; } try { Collider shipBounds = round.shipBounds; int result; if ((Object)(object)shipBounds != (Object)null) { Bounds bounds = shipBounds.bounds; result = (((Bounds)(ref bounds)).Contains(((Component)player).transform.position + Vector3.up * 0.25f) ? 1 : 0); } else { result = 0; } return (byte)result != 0; } catch { return false; } } private void Update() { if (UpgradeInput.WasPressed(Keybinds?.PurchaseMenu) && _lastPressFrame != Time.frameCount) { _lastPressFrame = Time.frameCount; tryShowMenu(); } } } internal static class Palette { public static readonly Color Transparent = new Color(0f, 0f, 0f, 0f); public static Color BgOverlay => Tone(0.42f, 0.44f); public static Color Backframe => Tone(0.5f, 0.86f); public static Color BgPanel => Tone(0.74f, 0.72f); public static Color BgHeader => Tone(0.92f, 0.78f); public static Color BgRow => Tone(0.62f, 0.64f); public static Color BgRowHover => Tone(0.86f, 0.78f); public static Color BgInput => Tone(0.7f, 0.66f); public static Color Separator => WithAlpha(UiTheme.Accent, 0.72f); public static Color BorderHot => WithAlpha(UiTheme.Accent, 0.88f); public static Color BorderDim => WithAlpha(UiTheme.Accent, 0.38f); public static Color Accent => UiTheme.Accent; public static Color Primary => UiTheme.Accent; public static Color Body => Color.Lerp(UiTheme.Dim, Color.white, 0.38f); public static Color Dim => UiTheme.Dim; public static Color Lore => Color.Lerp(UiTheme.Dim, UiTheme.Accent, 0.28f); public static Color RowButtonText => Color.Lerp(UiTheme.Accent, Color.white, 0.72f); public static Color NavText => WithAlpha(UiTheme.Accent, 0.92f); public static Color Danger => UiTheme.Danger; public static Color Warning => UiTheme.Warning; public static Color Muted => UiTheme.Muted; public static Color Locked => new Color(0.56f, 0.56f, 0.56f, 0.9f); public static Color Gold => Highlight; public static Color Sale => SaleTint(); public static Color ScrollTrack => WithAlpha(Color.Lerp(UiTheme.Panel, Color.black, 0.45f), 0.85f); public static Color ScrollHandle => WithAlpha(UiTheme.Accent, 0.88f); public static Color Shell => WithAlpha(Color.Lerp(Color.black, UiTheme.Panel, 0.22f), 0.98f); public static Color TypeSpeed => UiTheme.Accent; public static Color TypeDefense => Color.Lerp(UiTheme.Dim, UiTheme.Accent, 0.35f); public static Color TypeOffense => UiTheme.Accent; public static Color TypeStealth => Color.Lerp(UiTheme.Panel, UiTheme.Dim, 0.72f); public static Color TypeLoot => Highlight; public static Color TypeTeam => Color.Lerp(UiTheme.Dim, UiTheme.Accent, 0.58f); public static Color BtnNormal => Tone(0.72f, 0.62f); public static Color BtnHighlight => Tone(0.96f, 0.78f); public static Color BtnActive => WithAlpha(Color.Lerp(UiTheme.Panel, UiTheme.Accent, 0.3f), 0.94f); public static Color BtnDisabled => Tone(0.38f, 0.46f); public static Color BtnDanger => WithAlpha(Color.Lerp(UiTheme.Panel, Danger, 0.24f), 0.44f); public static Color BtnDangerHl => WithAlpha(Color.Lerp(UiTheme.Panel, Danger, 0.38f), 0.64f); private static Color Highlight => Color.Lerp(UiTheme.Accent, Color.white, 0.44f); private static Color SaleTint() { //IL_0000: 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_002b: 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_003b: 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) float num = default(float); float num2 = default(float); float num3 = default(float); Color.RGBToHSV(UiTheme.Accent, ref num, ref num2, ref num3); Color val = Color.HSVToRGB(Mathf.Repeat(num + 0.11f, 1f), num2, num3); val.a = UiTheme.Accent.a; return Color.Lerp(val, Color.white, 0.3f); } private static Color Tone(float intensity, float alpha) { //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) //IL_000a: 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_0018: 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) Color panel = UiTheme.Panel; Color accent = UiTheme.Accent; return WithAlpha(Color.Lerp(panel, accent, Mathf.Clamp01(intensity) * 0.22f), alpha); } private static Color WithAlpha(Color color, float alpha) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) color.a = alpha; return color; } public static Color Shade(Color tint, float strength, float alpha) { //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) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) return WithAlpha(Color.Lerp(Color.black, tint, Mathf.Clamp01(strength)), alpha); } public static Color Alpha(Color color, float alpha) { //IL_0000: 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) return WithAlpha(color, alpha); } public static Color UpgradeRow(bool hasEnough, bool maxed, bool onSale) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) if (maxed) { return Gold; } if (onSale) { return Sale; } if (!hasEnough) { return Warning; } return Accent; } } internal static class UI { private static readonly Dictionary _scanlineTextures = new Dictionary(); private static readonly Dictionary _panelTextures = new Dictionary(); private static readonly Dictionary _grimeTextures = new Dictionary(); private static GameObject _cachedLevelUpBox; private static TMP_FontAsset _terminalFont; private static AudioClip _hoverClip; private static AudioClip _confirmClip; private static AudioClip _denyClip; private static AudioClip _closeClip; private static bool _soundResolved; private static bool _confirmFromTerminal; private static float _nextSoundResolveTime; private const float SoundResolveInterval = 5f; private static Terminal _terminal; private static FieldInfo _terminalBuyField; private static bool _terminalBuyFieldSearched; public static GameObject MakeCanvas(string name) { //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_0024: 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_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Expected O, but got Unknown GameObject val = new GameObject(name); Canvas obj = val.AddComponent(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 200; obj.pixelPerfect = true; CanvasScaler obj2 = val.AddComponent(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.matchWidthOrHeight = 0.5f; obj2.referencePixelsPerUnit = 100f; obj2.dynamicPixelsPerUnit = 100f; val.AddComponent(); return val; } public static GameObject MakePanel(string name, Transform parent, Color color, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin = default(Vector2), Vector2 offsetMax = default(Vector2)) { //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_0013: 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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Expected O, but got Unknown GameObject val = new GameObject(name); val.transform.SetParent(parent, false); ((Graphic)val.AddComponent()).color = color; RectTransform component = val.GetComponent(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = offsetMin; component.offsetMax = offsetMax; return val; } public static GameObject CloneBorderedPanel(string name, Transform parent, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin = default(Vector2), Vector2 offsetMax = default(Vector2)) { //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_015f: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) //IL_016e: Unknown result type (might be due to invalid IL or missing references) //IL_0176: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_cachedLevelUpBox == (Object)null) { _cachedLevelUpBox = GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpBox"); if ((Object)(object)_cachedLevelUpBox == (Object)null) { _cachedLevelUpBox = GameObject.Find("/Systems/UI/Canvas/EndgameStats/Grade") ?? GameObject.Find("/Systems/UI/Canvas/EndgameStats/DaysInCompany") ?? GameObject.Find("/Systems/UI/Canvas/EndgameStats/Collected"); } if ((Object)(object)_cachedLevelUpBox == (Object)null) { _cachedLevelUpBox = FindInactiveVanillaBorderedPanel(); } } if ((Object)(object)_cachedLevelUpBox == (Object)null) { return null; } GameObject val = Object.Instantiate(_cachedLevelUpBox, parent); ((Object)val).name = name; val.SetActive(true); TMP_Text[] componentsInChildren = val.GetComponentsInChildren(true); foreach (TMP_Text obj in componentsInChildren) { obj.text = ""; ((Behaviour)obj).enabled = false; } Graphic[] componentsInChildren2 = val.GetComponentsInChildren(true); for (int i = 0; i < componentsInChildren2.Length; i++) { componentsInChildren2[i].raycastTarget = false; } Animator[] components = val.GetComponents(); for (int i = 0; i < components.Length; i++) { Object.Destroy((Object)(object)components[i]); } LayoutGroup[] components2 = val.GetComponents(); for (int i = 0; i < components2.Length; i++) { Object.Destroy((Object)(object)components2[i]); } ContentSizeFitter[] components3 = val.GetComponents(); for (int i = 0; i < components3.Length; i++) { Object.Destroy((Object)(object)components3[i]); } RectTransform val2 = val.GetComponent(); if ((Object)(object)val2 == (Object)null) { val2 = val.AddComponent(); } val2.anchorMin = anchorMin; val2.anchorMax = anchorMax; val2.offsetMin = offsetMin; val2.offsetMax = offsetMax; ((Transform)val2).localScale = Vector3.one; ((Transform)val2).localRotation = Quaternion.identity; return val; } private static GameObject FindInactiveVanillaBorderedPanel() { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) try { GameObject[] array = Resources.FindObjectsOfTypeAll(); string[] array2 = new string[5] { "LevelUpBox", "Collected", "Grade", "DaysInCompany", "EndgameStats" }; foreach (string value in array2) { foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null)) { Scene scene = val.scene; if (((Scene)(ref scene)).name != null && ((Object)val).name.IndexOf(value, StringComparison.OrdinalIgnoreCase) >= 0 && (Object)(object)val.GetComponent() != (Object)null && (Object)(object)val.GetComponentInChildren(true) != (Object)null) { return val; } } } } } catch { } return null; } public static bool VanillaPanelsAvailable() { if ((Object)(object)_cachedLevelUpBox != (Object)null) { return true; } _cachedLevelUpBox = GameObject.Find("/Systems/UI/Canvas/EndgameStats/LevelUp/LevelUpBox"); if ((Object)(object)_cachedLevelUpBox == (Object)null) { _cachedLevelUpBox = GameObject.Find("/Systems/UI/Canvas/EndgameStats/Grade"); } return (Object)(object)_cachedLevelUpBox != (Object)null; } public static TMP_Text MakeText(string name, Transform parent, string text, float fontSize, Color color, TextAlignmentOptions align = (TextAlignmentOptions)513) { //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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); TextMeshProUGUI val2 = val.AddComponent(); TMP_FontAsset terminalFont = GetTerminalFont(); if ((Object)(object)terminalFont != (Object)null) { ((TMP_Text)val2).font = terminalFont; } ((TMP_Text)val2).text = text; ((TMP_Text)val2).fontSize = Mathf.Round(fontSize); ((Graphic)val2).color = color; ((TMP_Text)val2).alignment = align; ((TMP_Text)val2).extraPadding = true; ((Component)val2).GetComponent().anchorMin = Vector2.zero; ((Component)val2).GetComponent().anchorMax = Vector2.one; ((Component)val2).GetComponent().offsetMin = new Vector2(6f, 2f); ((Component)val2).GetComponent().offsetMax = new Vector2(-6f, -2f); return (TMP_Text)(object)val2; } public static (Button btn, TMP_Text label) MakeButton(string name, Transform parent, string text, float fontSize, Color bgColor, Color hlColor, Color textColor, Vector2 anchorMin, Vector2 anchorMax, Vector2 offsetMin = default(Vector2), Vector2 offsetMax = default(Vector2)) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001a: 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_0030: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: 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_005e: 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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0083: 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_00a5: 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_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: 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) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); ((Graphic)val.AddComponent()).color = bgColor; RectTransform component = val.GetComponent(); component.anchorMin = anchorMin; component.anchorMax = anchorMax; component.offsetMin = offsetMin; component.offsetMax = offsetMax; Button obj = val.AddComponent