Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ObjectDropLaser v1.1.5
ObjectDropLaserMod.dll
Decompiled 3 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using ObjectDropLaserMod.Components; using ObjectDropLaserMod.GrabDetection; using ObjectDropLaserMod.Patches; using ObjectDropLaserMod.Systems; using ObjectDropLaserMod.Utils; using Photon.Pun; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyCompany("ObjectDropLaserMod")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+bfefc7cb04246bdb1169ab9baaa5193d4862c04a")] [assembly: AssemblyProduct("ObjectDropLaserMod")] [assembly: AssemblyTitle("ObjectDropLaserMod")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.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 ObjectDropLaserMod { [BepInPlugin("com.repo.droplaser", "Drop Laser Mod", "1.0.9")] public class Plugin : BaseUnityPlugin { private const string ConfigSchemaVersion = "2026-05-10.2"; public static ManualLogSource log; public static ConfigEntry<bool> EnableLogging; public static ConfigEntry<bool> EnableLaser; public static ConfigEntry<bool> UseCustomColor; public static ConfigEntry<Color> CustomLaserColor; public static ConfigEntry<float> LaserStartWidth; public static ConfigEntry<float> LaserEndWidth; public static ConfigEntry<float> LaserMaxDistance; public static ConfigEntry<float> LaserLightIntensity; public static ConfigEntry<float> LaserLightRange; public static ConfigEntry<string> ToggleLaserKey; public static ConfigEntry<bool> AutoEnableOnGrab; public static ConfigEntry<bool> EnableDropBeamInnerWhite; public static ConfigEntry<int> GhostPreviewMode; public static ConfigEntry<bool> UseCustomGhostColor; public static ConfigEntry<Color> CustomGhostColor; public static ConfigEntry<float> GhostOpacity; public static ConfigEntry<float> GhostEmissionIntensity; public static ConfigEntry<int> GhostUpdateFrameInterval; public static ConfigEntry<string> HighlightCycleForwardKey; public static ConfigEntry<string> HighlightCycleBackwardKey; public static ConfigEntry<string> DebugStopOverrideKey; public static ConfigEntry<bool> EnableDebugVisuals; public static ConfigEntry<bool> EnableHitDiagnostics; public static ConfigEntry<string> AppliedConfigSchemaVersion; public static ConfigEntry<string> PendingMigrationBackupPath; private void Awake() { log = ((BaseUnityPlugin)this).Logger; Harmony.CreateAndPatchAll(typeof(Plugin).Assembly, (string)null); log.LogInfo((object)"[DropLaser] Harmony patches applied."); BindGeneralConfig(); BindLaserConfig(); BindInternalConfig(); ConfigMigrationService.ApplyIfOutdated(((BaseUnityPlugin)this).Config, AppliedConfigSchemaVersion, PendingMigrationBackupPath, "2026-05-10.2", log); } private void BindGeneralConfig() { EnableLogging = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "EnableLogging", false, "Enable detailed log output (disable for cleaner console)"); } private void BindLaserConfig() { //IL_0050: 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) EnableLaser = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableLaser", true, "Master toggle for enabling/disabling the laser."); UseCustomColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "UseCustomColor", false, "If true, forces the laser to use a custom color instead of copying the beam's color."); CustomLaserColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Laser Settings", "CustomLaserColor", Color.red, "The color the laser will use if UseCustomColor is true."); LaserStartWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserStartWidth", 0.04f, "The width of the laser at its start."); LaserEndWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserEndWidth", 0.03f, "The width of the laser at its end."); LaserMaxDistance = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserMaxDistance", 500f, "Maximum distance the laser can scan downward."); LaserLightIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserLightIntensity", 5.5f, "Intensity (brightness) of the laser glow light."); LaserLightRange = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "LaserLightRange", 0.5f, "Range (radius) of the laser glow light."); ToggleLaserKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "ToggleLaserKey", "L", "Key to press for toggling the laser on/off."); AutoEnableOnGrab = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "AutoEnableOnGrab", true, "If true, the laser will automatically enable when the player grabs an object."); EnableDropBeamInnerWhite = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableDropBeamInnerWhite", true, "If true, shows a white inner core in the drop beam when above cart bounds."); GhostPreviewMode = ((BaseUnityPlugin)this).Config.Bind<int>("Laser Settings", "GhostPreviewMode", 1, "Ghost preview behavior: 0 = never, 1 = on cart, 2 = always."); UseCustomGhostColor = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "UseCustomGhostColor", false, "If true, the ghost preview uses CustomGhostColor instead of laser color."); CustomGhostColor = ((BaseUnityPlugin)this).Config.Bind<Color>("Laser Settings", "CustomGhostColor", new Color(0f, 1f, 1f, 1f), "Ghost preview tint color when UseCustomGhostColor is true."); GhostOpacity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "GhostOpacity", 0.35f, "Ghost preview opacity from 0.0 (invisible) to 1.0 (solid)."); GhostEmissionIntensity = ((BaseUnityPlugin)this).Config.Bind<float>("Laser Settings", "GhostEmissionIntensity", 0.6f, "Ghost preview emission intensity multiplier."); GhostUpdateFrameInterval = ((BaseUnityPlugin)this).Config.Bind<int>("Laser Settings", "GhostUpdateFrameInterval", 1, "Number of frames between ghost position updates. Higher values reduce update frequency."); HighlightCycleForwardKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "HighlightCycleForwardKey", "UpArrow", "Key used in debug mode to cycle cart highlight layers forward."); HighlightCycleBackwardKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "HighlightCycleBackwardKey", "DownArrow", "Key used in debug mode to cycle cart highlight layers backward."); DebugStopOverrideKey = ((BaseUnityPlugin)this).Config.Bind<string>("Laser Settings", "DebugStopOverrideKey", "Return", "Debug-only key that temporarily changes laser/ghost stop behavior while held."); EnableDebugVisuals = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableDebugVisuals", true, "If true, allows debug visualizers/highlighters when debug mode is active."); EnableHitDiagnostics = ((BaseUnityPlugin)this).Config.Bind<bool>("Laser Settings", "EnableHitDiagnostics", false, "If true, emits periodic hit diagnostics and stop-selection logs."); } private void BindInternalConfig() { AppliedConfigSchemaVersion = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "AppliedConfigSchemaVersion", "2026-05-10.2", ""); PendingMigrationBackupPath = ((BaseUnityPlugin)this).Config.Bind<string>("Internal", "PendingMigrationBackupPath", string.Empty, ""); } } } namespace ObjectDropLaserMod.Utils { public static class CartStateAccessors { private const float CartVolumeRefreshIntervalSeconds = 0.25f; private static readonly Type PhysGrabInCartType = AccessTools.TypeByName("PhysGrabInCart"); private static readonly FieldInfo InCartObjectsField = ((PhysGrabInCartType != null) ? AccessTools.Field(PhysGrabInCartType, "inCartObjects") : null); private static readonly Type CartObjectType = AccessTools.TypeByName("PhysGrabInCart+CartObject"); private static readonly FieldInfo CartObjectPhysGrabObjectField = ((CartObjectType != null) ? AccessTools.Field(CartObjectType, "physGrabObject") : null); private static readonly Type PhysGrabCartType = AccessTools.TypeByName("PhysGrabCart"); private static readonly FieldInfo PhysGrabCartInCartField = ((PhysGrabCartType != null) ? AccessTools.Field(PhysGrabCartType, "inCart") : null); private static readonly List<BoxCollider> CachedCartInCartVolumes = new List<BoxCollider>(); private static float nextCartVolumeRefreshTime; public static bool IsObjectTrackedInCart(PhysGrabObject heldObject) { if ((Object)(object)heldObject == (Object)null || InCartObjectsField == null || CartObjectPhysGrabObjectField == null) { return false; } Object val = Object.FindObjectOfType(PhysGrabInCartType); if (val == (Object)null) { return false; } if (!(InCartObjectsField.GetValue(val) is IEnumerable enumerable)) { return false; } foreach (object item in enumerable) { if (item != null && (Object)/*isinst with value type is only supported in some contexts*/ == (Object)(object)heldObject) { return true; } } return false; } public static bool IsGameObjectTrackedInCart(GameObject hitObject) { if ((Object)(object)hitObject == (Object)null) { return false; } PhysGrabObject componentInParent = hitObject.GetComponentInParent<PhysGrabObject>(); if ((Object)(object)componentInParent == (Object)null) { return false; } return IsObjectTrackedInCart(componentInParent); } public static bool IsPointInsideAnyCartInCartBounds(Vector3 point) { //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_0027: Unknown result type (might be due to invalid IL or missing references) RefreshCartVolumeCacheIfNeeded(); for (int i = 0; i < CachedCartInCartVolumes.Count; i++) { BoxCollider val = CachedCartInCartVolumes[i]; if ((Object)(object)val != (Object)null) { Bounds bounds = ((Collider)val).bounds; if (((Bounds)(ref bounds)).Contains(point)) { return true; } } } return false; } public static bool IsPointAboveAnyCartInCartBounds(Vector3 point) { //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_0033: 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_0047: 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_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) //IL_0075: 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_0090: Unknown result type (might be due to invalid IL or missing references) RefreshCartVolumeCacheIfNeeded(); for (int i = 0; i < CachedCartInCartVolumes.Count; i++) { BoxCollider val = CachedCartInCartVolumes[i]; if (!((Object)(object)val == (Object)null)) { Bounds bounds = ((Collider)val).bounds; bool num = point.x >= ((Bounds)(ref bounds)).min.x && point.x <= ((Bounds)(ref bounds)).max.x; bool flag = point.z >= ((Bounds)(ref bounds)).min.z && point.z <= ((Bounds)(ref bounds)).max.z; bool flag2 = point.y >= ((Bounds)(ref bounds)).max.y; if (num && flag && flag2) { return true; } } } return false; } private static void RefreshCartVolumeCacheIfNeeded() { if (Time.time < nextCartVolumeRefreshTime) { return; } nextCartVolumeRefreshTime = Time.time + 0.25f; CachedCartInCartVolumes.Clear(); if (PhysGrabCartType == null || PhysGrabCartInCartField == null) { return; } Object[] array = Object.FindObjectsOfType(PhysGrabCartType); foreach (object obj in array) { if (obj == null) { continue; } object? value = PhysGrabCartInCartField.GetValue(obj); Transform val = (Transform)((value is Transform) ? value : null); if (!((Object)(object)val == (Object)null)) { BoxCollider component = ((Component)val).GetComponent<BoxCollider>(); if ((Object)(object)component != (Object)null) { CachedCartInCartVolumes.Add(component); } } } } } internal static class ConfigMigrationService { public static void ApplyIfOutdated(ConfigFile configFile, ConfigEntry<string> appliedSchemaVersion, ConfigEntry<string> pendingBackupPath, string targetSchemaVersion, ManualLogSource logger) { if (configFile == null || appliedSchemaVersion == null || pendingBackupPath == null || string.IsNullOrWhiteSpace(targetSchemaVersion)) { return; } string text = appliedSchemaVersion.Value ?? string.Empty; bool flag = FileContainsSchemaMarker(configFile.ConfigFilePath); bool num = string.Equals(text, targetSchemaVersion, StringComparison.Ordinal); if (num) { TryFinalizePreviousMigrationBackup(configFile, pendingBackupPath, logger); } if (!(num && flag)) { string text2 = (string.IsNullOrWhiteSpace(text) ? "<none>" : text); if (logger != null) { logger.LogInfo((object)("[DropLaser][ConfigMigration] Updating config schema from " + text2 + " to " + targetSchemaVersion + ".")); } string text3 = TryCreateBackup(configFile.ConfigFilePath, logger); pendingBackupPath.Value = text3 ?? string.Empty; appliedSchemaVersion.Value = targetSchemaVersion; configFile.Save(); if (logger != null) { logger.LogInfo((object)"[DropLaser][ConfigMigration] Config migration complete."); } } } private static string TryCreateBackup(string configPath, ManualLogSource logger) { if (string.IsNullOrWhiteSpace(configPath) || !File.Exists(configPath)) { return null; } try { string directoryName = Path.GetDirectoryName(configPath); string? fileName = Path.GetFileName(configPath); string text = DateTime.UtcNow.ToString("yyyyMMdd-HHmmss"); string text2 = fileName + ".bak-" + text; string text3 = (string.IsNullOrWhiteSpace(directoryName) ? text2 : Path.Combine(directoryName, text2)); File.Copy(configPath, text3, overwrite: false); if (logger != null) { logger.LogInfo((object)("[DropLaser][ConfigMigration] Backup created: " + text3)); } return text3; } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("[DropLaser][ConfigMigration] Failed to create config backup: " + ex.Message)); } return null; } } private static void TryFinalizePreviousMigrationBackup(ConfigFile configFile, ConfigEntry<string> pendingBackupPath, ManualLogSource logger) { string text = pendingBackupPath.Value ?? string.Empty; if (string.IsNullOrWhiteSpace(text)) { return; } try { if (File.Exists(text)) { File.Delete(text); if (logger != null) { logger.LogInfo((object)("[DropLaser][ConfigMigration] Removed migration backup after successful load: " + text)); } } else if (logger != null) { logger.LogInfo((object)("[DropLaser][ConfigMigration] Pending backup already missing (treated as clean): " + text)); } } catch (Exception ex) { if (logger != null) { logger.LogWarning((object)("[DropLaser][ConfigMigration] Failed to remove migration backup: " + ex.Message)); } return; } pendingBackupPath.Value = string.Empty; configFile.Save(); } private static bool FileContainsSchemaMarker(string configPath) { if (string.IsNullOrWhiteSpace(configPath) || !File.Exists(configPath)) { return false; } try { return File.ReadAllText(configPath).IndexOf("AppliedConfigSchemaVersion", StringComparison.Ordinal) >= 0; } catch { return false; } } } public static class DropLaserInputHelper { public static bool IsConfiguredKeyDown(string configuredKey) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!TryParseKey(configuredKey, out var keyCode)) { return false; } return Input.GetKeyDown(keyCode); } public static bool IsConfiguredKeyHeld(string configuredKey) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (!TryParseKey(configuredKey, out var keyCode)) { return false; } return Input.GetKey(keyCode); } public static bool TryParseKey(string configuredKey, out KeyCode keyCode) { keyCode = (KeyCode)0; if (string.IsNullOrWhiteSpace(configuredKey)) { return false; } return Enum.TryParse<KeyCode>(configuredKey, ignoreCase: true, out keyCode); } } public static class DropLaserLogger { public static void Info(string message) { if (Plugin.EnableLogging.Value) { Plugin.log.LogInfo((object)message); } } public static void Warning(string message) { if (Plugin.EnableLogging.Value) { Plugin.log.LogWarning((object)message); } } public static void Error(string message) { Plugin.log.LogError((object)message); } } public static class PhysGrabberAccessors { private static readonly FieldInfo grabbedObjField = AccessTools.Field(typeof(PhysGrabber), "grabbedPhysGrabObject"); private static readonly FieldInfo beamField = AccessTools.Field(typeof(PhysGrabber), "physGrabBeam"); public static PhysGrabObject GetGrabbedObject(this PhysGrabber instance) { object? value = grabbedObjField.GetValue(instance); return (PhysGrabObject)((value is PhysGrabObject) ? value : null); } public static GameObject GetBeamObject(this PhysGrabber instance) { object? value = beamField.GetValue(instance); return (GameObject)((value is GameObject) ? value : null); } } } namespace ObjectDropLaserMod.Systems { public sealed class DropLaserBeamDebugService { private const float DoublePressWindowSeconds = 0.35f; private readonly DropLaserCartDebugVisualizer cartDebugVisualizer; private readonly DropLaserCartPartHighlighter cartPartHighlighter; private bool cartDebugModeActive; private float lastDebugTogglePressTime = -999f; private bool debugStopOverrideLoggedActive; private bool debugVisualsWereRunning; public bool IsDebugModeActive => cartDebugModeActive; public DropLaserBeamDebugService() { cartDebugVisualizer = new DropLaserCartDebugVisualizer(); cartPartHighlighter = new DropLaserCartPartHighlighter(); } public void Tick() { if (!AreDebugSystemsEnabled()) { ForceDisableDebugSystems(); return; } UpdateDebugModeToggle(); UpdateDebugStopOverrideLogState(); bool flag = ShouldRunDebugVisuals(); if (flag) { cartPartHighlighter.Update(); } else if (debugVisualsWereRunning) { cartPartHighlighter.Dispose(); } debugVisualsWereRunning = flag; } public void RenderBeamHits(Vector3 beamStart, RaycastHit[] hitBuffer, int hitCount, PhysGrabObject heldObject) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!AreDebugSystemsEnabled()) { cartDebugVisualizer.Hide(); } else if (ShouldRunDebugVisuals()) { cartDebugVisualizer.RenderHits(beamStart, hitBuffer, hitCount, heldObject); } else { cartDebugVisualizer.Hide(); } } public bool IsDebugStopOverrideActive() { if (!AreDebugSystemsEnabled()) { return false; } if (!cartDebugModeActive) { return false; } return DropLaserInputHelper.IsConfiguredKeyHeld(Plugin.DebugStopOverrideKey.Value); } public void HideVisuals() { cartDebugVisualizer.Hide(); } public void Dispose() { cartDebugVisualizer.Dispose(); cartPartHighlighter.Dispose(); debugVisualsWereRunning = false; } private void UpdateDebugModeToggle() { if (!AreDebugSystemsEnabled() || !DropLaserInputHelper.IsConfiguredKeyDown(Plugin.DebugStopOverrideKey.Value)) { return; } if (Time.time - lastDebugTogglePressTime <= 0.35f) { cartDebugModeActive = !cartDebugModeActive; lastDebugTogglePressTime = -999f; if (!cartDebugModeActive) { cartPartHighlighter.Dispose(); cartDebugVisualizer.Hide(); } Plugin.log.LogWarning((object)("[DropLaser] Cart debug mode is now " + (cartDebugModeActive ? "ENABLED" : "DISABLED") + ".")); } else { lastDebugTogglePressTime = Time.time; } } private void UpdateDebugStopOverrideLogState() { if (AreDebugSystemsEnabled() && Plugin.EnableHitDiagnostics.Value) { bool flag = IsDebugStopOverrideActive(); if (flag != debugStopOverrideLoggedActive) { debugStopOverrideLoggedActive = flag; DropLaserLogger.Info("[DropLaser] Debug stop override (hold " + Plugin.DebugStopOverrideKey.Value + ") is now " + (flag ? "ACTIVE" : "INACTIVE") + "."); } } } private bool ShouldRunDebugVisuals() { if (AreDebugSystemsEnabled() && cartDebugModeActive) { return Plugin.EnableDebugVisuals.Value; } return false; } private static bool AreDebugSystemsEnabled() { return Plugin.EnableLogging.Value; } private void ForceDisableDebugSystems() { cartDebugModeActive = false; debugStopOverrideLoggedActive = false; debugVisualsWereRunning = false; cartPartHighlighter.Dispose(); cartDebugVisualizer.Hide(); } } public sealed class DropLaserCartDebugVisualizer { private const int MaxDebugLines = 64; private const float LineWidth = 0.01f; private readonly int physGrabObjectCartLayer; private readonly int cartWheelsLayer; private readonly int physGrabObjectTriggerLayer; private readonly LineRenderer[] linePool = (LineRenderer[])(object)new LineRenderer[64]; private readonly GameObject root; public DropLaserCartDebugVisualizer() { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Expected O, but got Unknown physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart"); cartWheelsLayer = LayerMask.NameToLayer("CartWheels"); physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger"); root = new GameObject("DropLaserCartDebugVisualizer"); Object.DontDestroyOnLoad((Object)(object)root); root.SetActive(false); } public void RenderHits(Vector3 origin, RaycastHit[] hits, int hitCount, PhysGrabObject heldObject) { //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_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_0066: 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_007f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)root == (Object)null || hits == null || hitCount <= 0) { Hide(); return; } root.SetActive(true); int num = 0; for (int i = 0; i < hitCount; i++) { if (num >= 64) { break; } RaycastHit val = hits[i]; if (!((Object)(object)((RaycastHit)(ref val)).collider == (Object)null)) { LineRenderer orCreateLine = GetOrCreateLine(num); num++; Color endColor = (orCreateLine.startColor = ClassifyColor(((Component)((RaycastHit)(ref val)).collider).gameObject, heldObject)); orCreateLine.endColor = endColor; orCreateLine.SetPosition(0, origin); orCreateLine.SetPosition(1, ((RaycastHit)(ref val)).point); ((Renderer)orCreateLine).enabled = true; } } for (int j = num; j < 64; j++) { if ((Object)(object)linePool[j] != (Object)null) { ((Renderer)linePool[j]).enabled = false; } } } public void Hide() { if ((Object)(object)root != (Object)null) { root.SetActive(false); } } public void Dispose() { if ((Object)(object)root != (Object)null) { Object.Destroy((Object)(object)root); } } private LineRenderer GetOrCreateLine(int index) { //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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Expected O, but got Unknown if ((Object)(object)linePool[index] != (Object)null) { return linePool[index]; } GameObject val = new GameObject("DropLaserDebugHitLine_" + index); val.transform.SetParent(root.transform, false); LineRenderer val2 = val.AddComponent<LineRenderer>(); val2.useWorldSpace = true; val2.textureMode = (LineTextureMode)0; val2.positionCount = 2; val2.numCapVertices = 4; val2.numCornerVertices = 2; val2.startWidth = 0.01f; val2.endWidth = 0.01f; ((Renderer)val2).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)val2).receiveShadows = false; ((Renderer)val2).enabled = false; Shader val3 = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color"); if ((Object)(object)val3 != (Object)null) { Material material = new Material(val3); ((Renderer)val2).material = material; } linePool[index] = val2; return val2; } private Color ClassifyColor(GameObject hitObject, PhysGrabObject heldObject) { //IL_0009: 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_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_008f: 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_0089: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)hitObject == (Object)null) { return Color.white; } if (IsPartOfHeldObject(hitObject, heldObject)) { return Color.gray; } if (hitObject.CompareTag("Cart")) { return Color.green; } int layer = hitObject.layer; if (physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer) { return Color.green; } if (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer) { return new Color(1f, 0.5f, 0f); } if (cartWheelsLayer >= 0 && layer == cartWheelsLayer) { return Color.yellow; } return Color.cyan; } private static bool IsPartOfHeldObject(GameObject candidate, PhysGrabObject heldObject) { if ((Object)(object)candidate == (Object)null || (Object)(object)heldObject == (Object)null) { return false; } Transform val = candidate.transform; Transform transform = ((Component)heldObject).transform; while ((Object)(object)val != (Object)null) { if ((Object)(object)val == (Object)(object)transform) { return true; } val = val.parent; } return false; } } public sealed class DropLaserCartPartHighlighter { private enum HighlightCategory { InCartTrigger, CartBody, CartWheels, OtherCart } public enum HighlightMode { All, InCartOnly, CartBodyOnly, CartWheelsOnly, OtherCartOnly } private readonly Dictionary<Collider, GameObject> markersByCollider = new Dictionary<Collider, GameObject>(); private readonly HashSet<Collider> liveColliders = new HashSet<Collider>(); private readonly int physGrabObjectCartLayer; private readonly int cartWheelsLayer; private readonly int physGrabObjectTriggerLayer; private readonly Shader debugShader; private float nextRefreshTime; private HighlightMode currentMode; public static HighlightMode ActiveMode { get; private set; } public static bool IsGameObjectHighlightedForCurrentMode(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return false; } if (!TryGetCategoryForGameObject(gameObject, out var category)) { return false; } return ShouldShowCategoryStatic(category, ActiveMode); } public static bool IsGameObjectCartBody(GameObject gameObject) { if ((Object)(object)gameObject == (Object)null) { return false; } if (!TryGetCategoryForGameObject(gameObject, out var category)) { return false; } return category == HighlightCategory.CartBody; } public DropLaserCartPartHighlighter() { physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart"); cartWheelsLayer = LayerMask.NameToLayer("CartWheels"); physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger"); debugShader = Shader.Find("Sprites/Default") ?? Shader.Find("Unlit/Color"); } public void Update() { HandleCycleInput(); if (Time.time >= nextRefreshTime) { nextRefreshTime = Time.time + 0.5f; RebuildColliderSet(); } UpdateMarkerTransforms(); } public void Dispose() { ClearAllMarkers(); } private void RebuildColliderSet() { liveColliders.Clear(); PhysGrabCart[] array = Object.FindObjectsOfType<PhysGrabCart>(); foreach (PhysGrabCart val in array) { if ((Object)(object)val == (Object)null) { continue; } Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren<Collider>(true); foreach (Collider val2 in componentsInChildren) { if ((Object)(object)val2 == (Object)null || !ShouldHighlight(val2)) { continue; } liveColliders.Add(val2); if (!markersByCollider.ContainsKey(val2)) { GameObject val3 = CreateMarkerForCollider(val2); if ((Object)(object)val3 != (Object)null) { markersByCollider[val2] = val3; } } } } List<Collider> list = new List<Collider>(); foreach (KeyValuePair<Collider, GameObject> item in markersByCollider) { if ((Object)(object)item.Key == (Object)null || !liveColliders.Contains(item.Key)) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)item.Value); } list.Add(item.Key); } } for (int k = 0; k < list.Count; k++) { markersByCollider.Remove(list[k]); } } private void UpdateMarkerTransforms() { foreach (KeyValuePair<Collider, GameObject> item in markersByCollider) { Collider key = item.Key; GameObject value = item.Value; if (!((Object)(object)key == (Object)null) && !((Object)(object)value == (Object)null)) { HighlightCategory category = GetCategory(key); bool flag = ShouldShowCategory(category); value.SetActive(flag); if (flag) { SyncMarkerTransform(key, value.transform); } } } } private GameObject CreateMarkerForCollider(Collider collider) { //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_0018: 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_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) PrimitiveType val = (PrimitiveType)3; if (collider is SphereCollider) { val = (PrimitiveType)0; } else if (collider is CapsuleCollider) { val = (PrimitiveType)1; } GameObject val2 = GameObject.CreatePrimitive(val); ((Object)val2).name = "DropLaserCartDebugMarker_" + ((Object)collider).name; Object.DontDestroyOnLoad((Object)(object)val2); Collider component = val2.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { component.enabled = false; } Renderer component2 = val2.GetComponent<Renderer>(); if ((Object)(object)component2 == (Object)null || (Object)(object)debugShader == (Object)null) { Object.Destroy((Object)(object)val2); return null; } Material val3 = new Material(debugShader); val3.color = GetColorForCollider(collider); component2.material = val3; component2.shadowCastingMode = (ShadowCastingMode)0; component2.receiveShadows = false; SyncMarkerTransform(collider, val2.transform); return val2; } private void SyncMarkerTransform(Collider source, Transform markerTransform) { //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_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_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_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_007e: 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_00a2: 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) //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_01a3: 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_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_01c3: 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_00f6: 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_010a: 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_015a: 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_016f: Unknown result type (might be due to invalid IL or missing references) //IL_0174: Unknown result type (might be due to invalid IL or missing references) //IL_0185: 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) BoxCollider val = (BoxCollider)(object)((source is BoxCollider) ? source : null); if (val != null) { markerTransform.SetPositionAndRotation(((Component)source).transform.TransformPoint(val.center), ((Component)source).transform.rotation); markerTransform.localScale = Vector3.Scale(val.size, ((Component)source).transform.lossyScale); return; } SphereCollider val2 = (SphereCollider)(object)((source is SphereCollider) ? source : null); if (val2 != null) { float num = val2.radius * 2f; markerTransform.position = ((Component)source).transform.TransformPoint(val2.center); markerTransform.rotation = ((Component)source).transform.rotation; markerTransform.localScale = new Vector3(num * ((Component)source).transform.lossyScale.x, num * ((Component)source).transform.lossyScale.y, num * ((Component)source).transform.lossyScale.z); return; } CapsuleCollider val3 = (CapsuleCollider)(object)((source is CapsuleCollider) ? source : null); if (val3 != null) { float num2 = val3.radius * 2f; Vector3 lossyScale = ((Component)source).transform.lossyScale; Vector3 localScale = default(Vector3); ((Vector3)(ref localScale))..ctor(num2 * lossyScale.x, num2 * lossyScale.y, num2 * lossyScale.z); float height = val3.height; if (val3.direction == 0) { localScale.x = height * lossyScale.x; } else if (val3.direction == 1) { localScale.y = height * lossyScale.y; } else { localScale.z = height * lossyScale.z; } markerTransform.position = ((Component)source).transform.TransformPoint(val3.center); markerTransform.rotation = ((Component)source).transform.rotation; markerTransform.localScale = localScale; } else { Bounds bounds = source.bounds; markerTransform.position = ((Bounds)(ref bounds)).center; markerTransform.rotation = Quaternion.identity; bounds = source.bounds; markerTransform.localScale = ((Bounds)(ref bounds)).size; } } private bool ShouldHighlight(Collider collider) { GameObject gameObject = ((Component)collider).gameObject; if (gameObject.CompareTag("Cart")) { return true; } int layer = gameObject.layer; if ((physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer) || (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer) || (cartWheelsLayer >= 0 && layer == cartWheelsLayer)) { return true; } string name = ((Object)gameObject).name; if (!name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase) && !name.Contains("Cart Wall Collider")) { return name.Equals("In Cart", StringComparison.OrdinalIgnoreCase); } return true; } private Color GetColorForCollider(Collider collider) { //IL_001f: 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_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) return (Color)(GetCategory(collider) switch { HighlightCategory.InCartTrigger => new Color(0f, 1f, 0f, 0.25f), HighlightCategory.CartBody => new Color(1f, 0.5f, 0f, 0.25f), HighlightCategory.CartWheels => new Color(1f, 1f, 0f, 0.25f), _ => new Color(0f, 1f, 1f, 0.2f), }); } private HighlightCategory GetCategory(Collider collider) { GameObject gameObject = ((Component)collider).gameObject; int layer = gameObject.layer; if (gameObject.CompareTag("Cart") || (physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer)) { return HighlightCategory.InCartTrigger; } if (physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer) { return HighlightCategory.CartBody; } if (cartWheelsLayer >= 0 && layer == cartWheelsLayer) { return HighlightCategory.CartWheels; } return HighlightCategory.OtherCart; } private bool ShouldShowCategory(HighlightCategory category) { return ShouldShowCategoryStatic(category, currentMode); } private void HandleCycleInput() { if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.HighlightCycleForwardKey.Value)) { CycleMode(1); } if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.HighlightCycleBackwardKey.Value)) { CycleMode(-1); } } private void CycleMode(int delta) { int length = Enum.GetValues(typeof(HighlightMode)).Length; int num = (int)(currentMode + delta) % length; if (num < 0) { num += length; } currentMode = (HighlightMode)num; ActiveMode = currentMode; DropLaserLogger.Info("[DropLaser] Cart highlight mode: " + currentMode); } private static bool ShouldShowCategoryStatic(HighlightCategory category, HighlightMode mode) { return mode switch { HighlightMode.All => true, HighlightMode.InCartOnly => category == HighlightCategory.InCartTrigger, HighlightMode.CartBodyOnly => category == HighlightCategory.CartBody, HighlightMode.CartWheelsOnly => category == HighlightCategory.CartWheels, HighlightMode.OtherCartOnly => category == HighlightCategory.OtherCart, _ => true, }; } private static bool TryGetCategoryForGameObject(GameObject gameObject, out HighlightCategory category) { category = HighlightCategory.OtherCart; int num = LayerMask.NameToLayer("PhysGrabObjectTrigger"); int num2 = LayerMask.NameToLayer("PhysGrabObjectCart"); int num3 = LayerMask.NameToLayer("CartWheels"); bool flag = false; bool flag2 = false; bool flag3 = false; bool flag4 = false; bool flag5 = false; bool flag6 = false; bool flag7 = false; Transform val = gameObject.transform; while ((Object)(object)val != (Object)null) { GameObject gameObject2 = ((Component)val).gameObject; int layer = gameObject2.layer; string name = ((Object)gameObject2).name; if (gameObject2.CompareTag("Cart")) { flag = true; } if (num >= 0 && layer == num) { flag2 = true; } if (num2 >= 0 && layer == num2) { flag3 = true; } if (num3 >= 0 && layer == num3) { flag4 = true; } if (name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase)) { flag5 = true; } if (name.Contains("Cart Wall Collider")) { flag6 = true; } if (name.Equals("In Cart", StringComparison.OrdinalIgnoreCase)) { flag7 = true; } val = val.parent; } if (!(flag || flag2 || flag3 || flag4 || flag5 || flag6 || flag7)) { return false; } if (flag || flag2) { category = HighlightCategory.InCartTrigger; return true; } if (flag3 || flag6) { category = HighlightCategory.CartBody; return true; } if (flag4 || flag5) { category = HighlightCategory.CartWheels; return true; } category = HighlightCategory.OtherCart; return true; } private void ClearAllMarkers() { foreach (KeyValuePair<Collider, GameObject> item in markersByCollider) { if ((Object)(object)item.Value != (Object)null) { Object.Destroy((Object)(object)item.Value); } } markersByCollider.Clear(); liveColliders.Clear(); } } public class DropLaserManager { private static DropLaserManager _inst; private DropLaserController _ctrl; public static DropLaserManager Instance => _inst ?? (_inst = new DropLaserManager()); public void ToggleLaser() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if ((Object)(object)_ctrl == (Object)null) { GameObject val = new GameObject("DropLaserController"); _ctrl = val.AddComponent<DropLaserController>(); } _ctrl.Toggle(); } public void ForceDisableLaser() { if ((Object)(object)_ctrl == (Object)null) { DropLaserLogger.Info("[DropLaserManager] ForceDisableLaser called but _ctrl is NULL!"); } else if ((Object)(object)((Component)_ctrl).gameObject == (Object)null) { DropLaserLogger.Info("[DropLaserManager] ForceDisableLaser: _ctrl exists but its GameObject is DESTROYED!"); } else { DropLaserLogger.Info($"[DropLaserManager] ForceDisableLaser: _ctrl OK. GameObject name: {((Object)((Component)_ctrl).gameObject).name}, Active: {((Component)_ctrl).gameObject.activeSelf}"); } if ((Object)(object)_ctrl != (Object)null) { _ctrl.DisableLaser(); DropLaserLogger.Info("[DropLaserManager] Laser force-disabled after item release."); } else { DropLaserLogger.Warning("[DropLaserManager] ForceDisableLaser called, but controller was null."); } } public bool HasController() { if ((Object)(object)_ctrl != (Object)null) { return (Object)(object)((Component)_ctrl).gameObject != (Object)null; } return false; } } public static class DropLaserMaterialService { public static Material CreateTransparentLineMaterial(Shader shader) { //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_0017: Expected O, but got Unknown //IL_0018: Expected O, but got Unknown if ((Object)(object)shader == (Object)null) { return null; } Material val = new Material(shader); ConfigureTransparentMaterial(val); return val; } public static void ConfigureTransparentMaterial(Material material) { if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Mode")) { material.SetFloat("_Mode", 2f); } material.SetInt("_SrcBlend", 5); material.SetInt("_DstBlend", 10); material.SetInt("_ZWrite", 0); material.DisableKeyword("_ALPHATEST_ON"); material.EnableKeyword("_ALPHABLEND_ON"); material.DisableKeyword("_ALPHAPREMULTIPLY_ON"); material.renderQueue = 3000; } } public static void SyncFromSourceBeam(Material target, Material source) { //IL_0048: 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_0084: 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_00e4: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !((Object)(object)source == (Object)null)) { if (source.HasProperty("_MainTex") && target.HasProperty("_MainTex")) { target.SetTexture("_MainTex", source.GetTexture("_MainTex")); target.mainTextureOffset = source.mainTextureOffset; target.mainTextureScale = source.mainTextureScale; } if (source.HasProperty("_Color") && target.HasProperty("_Color")) { target.SetColor("_Color", source.GetColor("_Color")); } if (source.HasProperty("_BaseColor") && target.HasProperty("_BaseColor")) { target.SetColor("_BaseColor", source.GetColor("_BaseColor")); } if (source.HasProperty("_EmissionColor") && target.HasProperty("_EmissionColor")) { target.SetColor("_EmissionColor", source.GetColor("_EmissionColor")); } } } public static void MirrorMaterialAppearance(Material target, Material source) { if (!((Object)(object)target == (Object)null) && !((Object)(object)source == (Object)null)) { if ((Object)(object)target.shader != (Object)(object)source.shader) { target.shader = source.shader; } target.CopyPropertiesFromMaterial(source); target.shaderKeywords = source.shaderKeywords; target.renderQueue = source.renderQueue; } } public static void WriteColor(Material material, Color color) { //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) if (!((Object)(object)material == (Object)null)) { if (material.HasProperty("_Color")) { material.SetColor("_Color", color); } if (material.HasProperty("_BaseColor")) { material.SetColor("_BaseColor", color); } } } public static void ApplyOpacityToKnownColorProperties(Material material, float opacity) { if (!((Object)(object)material == (Object)null)) { float alpha = Mathf.Clamp01(opacity); ApplyAlphaIfPresent(material, "_Color", alpha); ApplyAlphaIfPresent(material, "_BaseColor", alpha); ApplyAlphaIfPresent(material, "_TintColor", alpha); } } private static void ApplyAlphaIfPresent(Material material, string propertyName, float alpha) { //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_001c: Unknown result type (might be due to invalid IL or missing references) if (material.HasProperty(propertyName)) { Color color = material.GetColor(propertyName); color.a = alpha; material.SetColor(propertyName, color); } } } public sealed class DropLaserOverlayService { private const float InnerWidthMultiplier = 0.35f; private const float InnerAlphaBoost = 1.8f; private const float InnerMinAlpha = 0.2f; private const float InnerEmission = 1.1f; public void Disable(LineRenderer overlayLine) { if ((Object)(object)overlayLine != (Object)null) { ((Renderer)overlayLine).enabled = false; } } public void SyncInnerOverlay(LineRenderer overlayLine, LineRenderer sourceLine, bool allowOverlay) { //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_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_004f: 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_009c: 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_00c4: 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_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)overlayLine == (Object)null || (Object)(object)sourceLine == (Object)null) { return; } if (!allowOverlay || !((Renderer)sourceLine).enabled || sourceLine.positionCount < 2) { ((Renderer)overlayLine).enabled = false; return; } Vector3 position = sourceLine.GetPosition(0); Vector3 position2 = sourceLine.GetPosition(sourceLine.positionCount - 1); overlayLine.positionCount = 2; overlayLine.SetPosition(0, position); overlayLine.SetPosition(1, position2); if (sourceLine.startWidth > 0f) { overlayLine.startWidth = sourceLine.startWidth * 0.35f; } if (sourceLine.endWidth > 0f) { overlayLine.endWidth = sourceLine.endWidth * 0.35f; } float num = ReadLineAlpha(sourceLine.startColor); float num2 = ReadLineAlpha(sourceLine.endColor); overlayLine.startColor = new Color(1f, 1f, 1f, num); overlayLine.endColor = new Color(1f, 1f, 1f, num2); if ((Object)(object)((Renderer)overlayLine).material != (Object)null) { DropLaserMaterialService.SyncFromSourceBeam(((Renderer)overlayLine).material, ((Renderer)sourceLine).material); float num3 = BoostAlpha(ReadMaterialAlpha(((Renderer)sourceLine).material)); DropLaserMaterialService.WriteColor(((Renderer)overlayLine).material, new Color(1f, 1f, 1f, num3)); if (((Renderer)overlayLine).material.HasProperty("_EmissionColor")) { ((Renderer)overlayLine).material.SetColor("_EmissionColor", Color.white * 1.1f); } } ((Renderer)overlayLine).enabled = true; } private static float ReadLineAlpha(Color color) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return BoostAlpha(color.a); } private static float ReadMaterialAlpha(Material sourceMaterial) { //IL_0022: 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)sourceMaterial == (Object)null) { return 1f; } if (sourceMaterial.HasProperty("_BaseColor")) { return sourceMaterial.GetColor("_BaseColor").a; } if (sourceMaterial.HasProperty("_Color")) { return sourceMaterial.GetColor("_Color").a; } return 1f; } private static float BoostAlpha(float alpha) { return Mathf.Clamp01(Mathf.Max(alpha * 1.8f, 0.2f)); } } public sealed class SagaOrchestrator { private sealed class BranchState { public int RetryAtFrame; public bool IsCutOff; public Exception LastFailure; public int LastFailureFrame; public int LastCutOffLogFrame; } private readonly ManualLogSource log; private readonly int retryDelayFrames; private readonly Dictionary<string, BranchState> branches = new Dictionary<string, BranchState>(); private static bool ShouldLogSagaLifecycle() { if (Plugin.EnableLogging != null) { return Plugin.EnableLogging.Value; } return false; } public SagaOrchestrator(ManualLogSource log, int retryDelayFrames = 180) { this.log = log; this.retryDelayFrames = Mathf.Max(1, retryDelayFrames); } public void Execute(string branchName, Action execute, Action compensate) { if (string.IsNullOrWhiteSpace(branchName)) { branchName = "unnamed"; } BranchState orCreateState = GetOrCreateState(branchName); if (orCreateState.IsCutOff && Time.frameCount < orCreateState.RetryAtFrame) { if (ShouldLogSagaLifecycle() && Time.frameCount >= orCreateState.LastCutOffLogFrame + 120) { string text = ((orCreateState.LastFailure != null) ? orCreateState.LastFailure.Message : "unknown"); log.LogWarning((object)$"[DropLaser:Saga] Branch '{branchName}' remains cut off until frame {orCreateState.RetryAtFrame} (last failure frame {orCreateState.LastFailureFrame}: {text})"); orCreateState.LastCutOffLogFrame = Time.frameCount; } return; } try { execute?.Invoke(); if (ShouldLogSagaLifecycle() && orCreateState.IsCutOff) { log.LogInfo((object)("[DropLaser:Saga] Branch '" + branchName + "' recovered and resumed.")); } orCreateState.IsCutOff = false; orCreateState.RetryAtFrame = 0; orCreateState.LastFailure = null; orCreateState.LastFailureFrame = 0; } catch (Exception lastFailure) { Exception arg = (orCreateState.LastFailure = lastFailure); orCreateState.LastFailureFrame = Time.frameCount; log.LogError((object)$"[DropLaser:Saga] Branch '{branchName}' failed at frame {Time.frameCount}: {arg}"); try { compensate?.Invoke(); } catch (Exception arg2) { log.LogError((object)$"[DropLaser:Saga] Branch '{branchName}' compensation failed: {arg2}"); } orCreateState.IsCutOff = true; orCreateState.RetryAtFrame = Time.frameCount + retryDelayFrames; orCreateState.LastCutOffLogFrame = Time.frameCount; if (ShouldLogSagaLifecycle()) { log.LogWarning((object)$"[DropLaser:Saga] Branch '{branchName}' cut off until frame {orCreateState.RetryAtFrame}."); } } } private BranchState GetOrCreateState(string branchName) { if (!branches.TryGetValue(branchName, out var value)) { value = new BranchState(); branches[branchName] = value; } return value; } } } namespace ObjectDropLaserMod.Patches { [HarmonyPatch(typeof(PhysGrabber), "Update")] public static class DropLaserInputPatch { private static bool Prefix(PhysGrabber __instance) { PhotonView component = ((Component)__instance).GetComponent<PhotonView>(); bool flag = PhotonNetwork.PlayerList.Length < 1; if (!flag && (Object)(object)component != (Object)null && !component.IsMine) { return true; } if (DropLaserInputHelper.IsConfiguredKeyDown(Plugin.ToggleLaserKey.Value)) { DropLaserLogger.Info("[DropLaserInputPatch] Local player pressed L (singleplayer: " + flag + ")."); DropLaserLogger.Info("[DropLaserInputPatch] Number on PlayerList = ) " + PhotonNetwork.PlayerList.Length); if (!GrabDetectionState.IsHoldingObject) { DropLaserLogger.Info("[DropLaserInputPatch] L pressed but not holding object ignoring toggle."); return true; } SimulateKeyPress(); } return true; } public static void SimulateKeyPress() { DropLaserManager instance = DropLaserManager.Instance; if (instance != null) { instance.ToggleLaser(); } else { Plugin.log.LogWarning((object)"[DropLaserInputPatch] DropLaserManager instance missing during SimulateKeyPress."); } } } } namespace ObjectDropLaserMod.GrabDetection { public static class GrabDetectionState { public static bool IsHoldingObject; } [HarmonyPatch(typeof(PhysGrabber), "ReleaseObject")] public static class GrabReleasePatch { private static void Postfix(PhysGrabber __instance) { string arg = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).name : "null"); int num = (((Object)(object)__instance != (Object)null) ? ((Object)__instance).GetInstanceID() : (-1)); DropLaserLogger.Info($"[GrabReleasePatch] ReleaseObject called on PhysGrabber: {arg} (InstanceID: {num})"); GrabDetectionState.IsHoldingObject = false; DropLaserLogger.Info("[GrabReleasePatch] IsHoldingObject = false"); if (DropLaserManager.Instance.HasController()) { DropLaserManager.Instance.ForceDisableLaser(); DropLaserLogger.Info("[GrabReleasePatch] ForceDisableLaser() called."); } } } [HarmonyPatch(typeof(PhysGrabber), "RayCheck")] public static class GrabStartPatch { private static void Postfix(PhysGrabber __instance, bool _grab) { if (_grab && __instance.grabbed) { GrabDetectionState.IsHoldingObject = true; DropLaserLogger.Info("[GrabStartPatch] Grab confirmed - IsHoldingObject = true"); if (Plugin.AutoEnableOnGrab.Value) { DropLaserLogger.Info("[GrabStartPatch] Auto-enabling laser due to object grab."); DropLaserInputPatch.SimulateKeyPress(); } } } } } namespace ObjectDropLaserMod.Components { public class DropLaserBeam { private sealed class GhostRendererState { public Renderer Renderer; public Material Material; } private readonly struct BeamFrameData { public readonly PhysGrabObject HeldObject; public readonly Vector3 BeamStart; public readonly Vector3 BeamHitPoint; public readonly bool ShouldShowGhost; public readonly bool ShouldRenderOverlay; public BeamFrameData(PhysGrabObject heldObject, Vector3 beamStart, Vector3 beamHitPoint, bool shouldShowGhost, bool shouldRenderOverlay) { //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) HeldObject = heldObject; BeamStart = beamStart; BeamHitPoint = beamHitPoint; ShouldShowGhost = shouldShowGhost; ShouldRenderOverlay = shouldRenderOverlay; } } private readonly struct HitDebugInfo { public readonly bool HasHit; public readonly string ObjectName; public readonly string Tag; public readonly int Layer; public readonly float Distance; public readonly Vector3 Point; public HitDebugInfo(RaycastHit hit) { //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_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) if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { HasHit = false; ObjectName = string.Empty; Tag = string.Empty; Layer = -1; Distance = 0f; Point = Vector3.zero; } else { HasHit = true; ObjectName = ((Object)((Component)((RaycastHit)(ref hit)).collider).gameObject).name; Tag = ((Component)((RaycastHit)(ref hit)).collider).gameObject.tag; Layer = ((Component)((RaycastHit)(ref hit)).collider).gameObject.layer; Distance = ((RaycastHit)(ref hit)).distance; Point = ((RaycastHit)(ref hit)).point; } } } private const float DefaultDowncastDistance = 50f; private const float LaserOriginVerticalOffset = 0.05f; private const float GhostRayStartOffset = 0.02f; private const float MinimumBeamLength = 0.01f; private const int RaycastBufferSize = 64; private const float FallbackBoundsSize = 0.1f; private const float EndTaperPortion = 0.03f; private const float EndTaperAlphaMultiplier = 0.6f; private const int StopLogIntervalFrames = 1000; private const float RegularHitDumpIntervalSeconds = 5f; private const float BottomNormalDotThreshold = 0.85f; private readonly LineRenderer dropBeamLine; private readonly LineRenderer grabBeamOverlayLine; private readonly LineRenderer dropBeamOverlayLine; private readonly Light dropBeamLight; private readonly GameObject sourceBeamObject; private readonly LineRenderer sourceBeamLine; private readonly PhysGrabber playerGrabber; private readonly HashSet<string> ignoredCartParts; private readonly RaycastHit[] raycastHitBuffer = (RaycastHit[])(object)new RaycastHit[64]; private readonly SagaOrchestrator saga; private readonly DropLaserOverlayService overlayService; private readonly DropLaserBeamDebugService debugService; private readonly int physGrabObjectCartLayer; private readonly int cartWheelsLayer; private readonly int physGrabObjectTriggerLayer; private readonly List<GhostRendererState> ghostRenderers = new List<GhostRendererState>(); private GameObject ghostRoot; private PhysGrabObject ghostSource; private int nextGhostUpdateFrame; private int nextGhostFailureLogFrame; private int nextBeamStopLogFrame; private int nextGhostStopLogFrame; private float nextRegularHitDumpTime; private int lastBeamHitCount; private HitDebugInfo lastChosenBeamStopInfo; private bool hasLastChosenBeamStopInfo; private HitDebugInfo lastChosenGhostStopInfo; private bool hasLastChosenGhostStopInfo; private readonly List<HitDebugInfo> lastGhostCandidateHits = new List<HitDebugInfo>(); private string lastGhostCandidateSource = "none"; public DropLaserBeam(LineRenderer dropBeamLine, LineRenderer grabBeamOverlayLine, LineRenderer dropBeamOverlayLine, Light dropBeamLight, GameObject sourceBeamObject, LineRenderer sourceBeamLine, PhysGrabber playerGrabber, HashSet<string> ignoredCartParts) { this.dropBeamLine = dropBeamLine; this.grabBeamOverlayLine = grabBeamOverlayLine; this.dropBeamOverlayLine = dropBeamOverlayLine; this.dropBeamLight = dropBeamLight; this.sourceBeamObject = sourceBeamObject; this.sourceBeamLine = sourceBeamLine; this.playerGrabber = playerGrabber; this.ignoredCartParts = ignoredCartParts; saga = new SagaOrchestrator(Plugin.log); overlayService = new DropLaserOverlayService(); debugService = new DropLaserBeamDebugService(); physGrabObjectCartLayer = LayerMask.NameToLayer("PhysGrabObjectCart"); cartWheelsLayer = LayerMask.NameToLayer("CartWheels"); physGrabObjectTriggerLayer = LayerMask.NameToLayer("PhysGrabObjectTrigger"); } public void UpdateBeam() { //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_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) if (!HasValidReferences()) { return; } debugService.Tick(); Material material = ((Renderer)sourceBeamLine).material; Material material2 = ((Renderer)dropBeamLine).material; Color laserColor = SyncBeamAppearance(material, material2); if (!TryBuildFrameData(out var frameData)) { HideBeamAndGhost(); return; } bool hasGhostStop = false; Vector3 ghostStopPoint = Vector3.zero; saga.Execute("ghost", delegate { hasGhostStop = UpdateGhostPreview(frameData.HeldObject, frameData.ShouldShowGhost, out ghostStopPoint); }, delegate { SetGhostVisible(visible: false); }); saga.Execute("beam", delegate { //IL_0016: 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_001b: 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_002f: Unknown result type (might be due to invalid IL or missing references) Vector3 targetStopPoint = (hasGhostStop ? ghostStopPoint : frameData.BeamHitPoint); UpdateBeamVisuals(frameData.BeamStart, targetStopPoint, laserColor); }, delegate { ((Renderer)dropBeamLine).enabled = false; ((Behaviour)dropBeamLight).enabled = false; }); saga.Execute("overlay", delegate { overlayService.SyncInnerOverlay(grabBeamOverlayLine, sourceBeamLine, frameData.ShouldRenderOverlay); overlayService.SyncInnerOverlay(dropBeamOverlayLine, dropBeamLine, frameData.ShouldRenderOverlay); }, delegate { overlayService.Disable(grabBeamOverlayLine); overlayService.Disable(dropBeamOverlayLine); }); } public void Dispose() { SetGhostVisible(visible: false); DestroyGhost(); debugService.Dispose(); } private bool HasValidReferences() { if ((Object)(object)playerGrabber != (Object)null && (Object)(object)sourceBeamLine != (Object)null && (Object)(object)sourceBeamObject != (Object)null) { return true; } Plugin.log.LogWarning((object)"[DropLaser] Critical references lost. Cannot update beam."); return false; } private static bool ShouldLogGhostWarnings() { if (Plugin.EnableLogging != null) { return Plugin.EnableLogging.Value; } return false; } private bool TryBuildFrameData(out BeamFrameData frameData) { //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_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003d: 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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) frameData = default(BeamFrameData); PhysGrabObject grabbedObject = playerGrabber.GetGrabbedObject(); if ((Object)(object)grabbedObject == (Object)null) { return false; } Vector3 val = CalculateBeamOrigin(grabbedObject); Vector3 beamHitPoint = val + Vector3.down * 50f; ResolveBeamHitPoint(val, grabbedObject, ref beamHitPoint, out var hitTrackedCartObject, out var stopInfo); LogStopInfoIfNeeded("Beam", stopInfo, ref nextBeamStopLogFrame); bool flag = CartStateAccessors.IsPointInsideAnyCartInCartBounds(beamHitPoint); bool flag2 = CartStateAccessors.IsPointAboveAnyCartInCartBounds(val); bool flag3 = hitTrackedCartObject || flag || flag2; DumpBeamHitsIfNeeded(grabbedObject, flag3); int num = Mathf.Clamp(Plugin.GhostPreviewMode.Value, 0, 2); bool shouldShowGhost = num == 2 || (num == 1 && flag3); bool shouldRenderOverlay = Plugin.EnableDropBeamInnerWhite.Value && flag3; frameData = new BeamFrameData(grabbedObject, val, beamHitPoint, shouldShowGhost, shouldRenderOverlay); return true; } private void HideBeamAndGhost() { ((Renderer)dropBeamLine).enabled = false; ((Behaviour)dropBeamLight).enabled = false; overlayService.Disable(grabBeamOverlayLine); overlayService.Disable(dropBeamOverlayLine); SetGhostVisible(visible: false); debugService.HideVisuals(); } private Color SyncBeamAppearance(Material sourceMaterial, Material dropMaterial) { //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_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_004e: 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_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_0030: Unknown result type (might be due to invalid IL or missing references) if (Plugin.UseCustomColor.Value) { Color value = Plugin.CustomLaserColor.Value; SetLineColor(value); ApplyLaserMaterialAppearance(dropMaterial, sourceMaterial, value, 1f, 1f); return value; } Color finalLaserColor = DropLaserColorManager.GetFinalLaserColor(sourceMaterial); DropLaserMaterialService.SyncFromSourceBeam(dropMaterial, sourceMaterial); SetLineColor(finalLaserColor); DropLaserMaterialService.WriteColor(dropMaterial, finalLaserColor); return finalLaserColor; } private void SetLineColor(Color color) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_001b: 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_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_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_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_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_007b: 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_008c: 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_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_00ae: 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_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_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_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_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_0111: 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) float num = 1f; float num2 = 0.6f; Gradient val = new Gradient(); val.SetKeys((GradientColorKey[])(object)new GradientColorKey[4] { new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0f), new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0.03f), new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 0.97f), new GradientColorKey(new Color(color.r, color.g, color.b, 1f), 1f) }, (GradientAlphaKey[])(object)new GradientAlphaKey[4] { new GradientAlphaKey(num2, 0f), new GradientAlphaKey(num, 0.03f), new GradientAlphaKey(num, 0.97f), new GradientAlphaKey(num2, 1f) }); dropBeamLine.colorGradient = val; } private Vector3 CalculateBeamOrigin(PhysGrabObject heldObject) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return CalculateBeamOrigin(((Component)heldObject).gameObject); } private Vector3 CalculateBeamOrigin(GameObject targetObject) { //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_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_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) Bounds objectBounds = GetObjectBounds(targetObject); Vector3 center = ((Bounds)(ref objectBounds)).center; center.y += 0.05f; center.y -= ((Bounds)(ref objectBounds)).extents.y; return center; } private void UpdateBeamVisuals(Vector3 beamStart, Vector3 targetStopPoint, Color laserColor) { //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_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_003f: 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_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_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) float num = Mathf.Min(targetStopPoint.y, beamStart.y - 0.01f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(beamStart.x, num, beamStart.z); ((Renderer)dropBeamLine).enabled = true; dropBeamLine.SetPosition(0, beamStart); dropBeamLine.SetPosition(1, val); ((Component)dropBeamLight).transform.position = val; dropBeamLight.color = new Color(laserColor.r, laserColor.g, laserColor.b, 1f); ((Behaviour)dropBeamLight).enabled = true; } private void ResolveBeamHitPoint(Vector3 beamStart, PhysGrabObject heldObject, ref Vector3 beamHitPoint, out bool hitTrackedCartObject, out HitDebugInfo stopInfo) { //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_003f: 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_0065: 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_00a3: Unknown result type (might be due to invalid IL or missing references) hitTrackedCartObject = false; stopInfo = default(HitDebugInfo); hasLastChosenBeamStopInfo = false; int num = (lastBeamHitCount = Physics.RaycastNonAlloc(beamStart, Vector3.down, raycastHitBuffer, Plugin.LaserMaxDistance.Value, -5, (QueryTriggerInteraction)2)); debugService.RenderBeamHits(beamStart, raycastHitBuffer, num, heldObject); float num2 = float.MaxValue; for (int i = 0; i < num; i++) { RaycastHit hit = raycastHitBuffer[i]; if (IsValidBeamHit(hit, heldObject) && !(((RaycastHit)(ref hit)).distance >= num2)) { num2 = ((RaycastHit)(ref hit)).distance; beamHitPoint = ((RaycastHit)(ref hit)).point; hitTrackedCartObject = CartStateAccessors.IsGameObjectTrackedInCart(((Component)((RaycastHit)(ref hit)).collider).gameObject); stopInfo = new HitDebugInfo(hit); lastChosenBeamStopInfo = stopInfo; hasLastChosenBeamStopInfo = true; } } } private bool IsValidBeamHit(RaycastHit hit, PhysGrabObject heldObject) { if ((Object)(object)((RaycastHit)(ref hit)).collider == (Object)null) { return false; } GameObject gameObject = ((Component)((RaycastHit)(ref hit)).collider).gameObject; if (ShouldIgnoreCartHit(gameObject, debugService.IsDebugStopOverrideActive())) { return false; } return !IsPartOfHeldObject(gameObject, ((Component)heldObject).gameObject); } private bool ShouldIgnoreCartHit(GameObject hitObject, bool debugStopOverrideActive) { if ((Object)(object)hitObject == (Object)null) { return false; } int layer = hitObject.layer; string name = ((Object)hitObject).name; bool flag = hitObject.CompareTag("Cart"); bool flag2 = physGrabObjectCartLayer >= 0 && layer == physGrabObjectCartLayer; bool flag3 = cartWheelsLayer >= 0 && layer == cartWheelsLayer; bool flag4 = physGrabObjectTriggerLayer >= 0 && layer == physGrabObjectTriggerLayer; bool flag5 = name.StartsWith("Capsule", StringComparison.OrdinalIgnoreCase); if (DropLaserCartPartHighlighter.IsGameObjectCartBody(hitObject)) { return false; } if (debugStopOverrideActive) { return !DropLaserCartPartHighlighter.IsGameObjectHighlightedForCurrentMode(hitObject); } if (flag || flag2 || flag4 || flag3 || flag5) { return true; } return ignoredCartParts.Contains(name); } private bool UpdateGhostPreview(PhysGrabObject heldObject, bool shouldShowGhost, out Vector3 ghostStopPoint) { //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_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) ghostStopPoint = Vector3.zero; if (!shouldShowGhost) { SetGhostVisible(visible: false); return false; } EnsureGhostForHeldObject(heldObject); if ((Object)(object)ghostRoot == (Object)null) { return false; } if (Time.frameCount >= nextGhostUpdateFrame) { int num = Mathf.Max(1, Plugin.GhostUpdateFrameInterval.Value); nextGhostUpdateFrame = Time.frameCount + num; if (!TryUpdateGhostTransform(heldObject)) { if (Time.frameCount >= nextGhostFailureLogFrame) { if (ShouldLogGhostWarnings()) { Plugin.log.LogWarning((object)"[DropLaser] Ghost transform update failed; hiding ghost for this frame."); } nextGhostFailureLogFrame = Time.frameCount + 120; } SetGhostVisible(visible: false); return false; } } SetGhostVisible(visible: true); ghostStopPoint = GetGhostStopPoint(); return true; } private bool TryUpdateGhostTransform(PhysGrabObject heldObject) { //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_0099: 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_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_00d5: 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_0065: 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) lastGhostCandidateHits.Clear(); lastGhostCandidateSource = "none"; if (!hasLastChosenBeamStopInfo || !lastChosenBeamStopInfo.HasHit) { hasLastChosenGhostStopInfo = false; return false; } float y = lastChosenBeamStopInfo.Point.y; HitDebugInfo info = lastChosenBeamStopInfo; lastGhostCandidateSource = "beam-ray"; if (TryResolveHighestObjectRaycastHit(heldObject, y, out var bestHigherHit)) { y = ((RaycastHit)(ref bestHigherHit)).point.y; info = (lastChosenGhostStopInfo = new HitDebugInfo(bestHigherHit)); hasLastChosenGhostStopInfo = true; } Bounds objectBounds = GetObjectBounds(((Component)heldObject).gameObject); float num = Mathf.Max(0f, ((Bounds)(ref objectBounds)).min.y - y); Vector3 val = ((Component)heldObject).transform.position - Vector3.up * num; ghostRoot.transform.SetPositionAndRotation(val, ((Component)heldObject).transform.rotation); lastChosenGhostStopInfo = info; hasLastChosenGhostStopInfo = true; LogStopInfoIfNeeded("Ghost", info, ref nextGhostStopLogFrame); return true; } private bool TryResolveHighestObjectRaycastHit(PhysGrabObject heldObject, float currentSurfaceY, out RaycastHit bestHigherHit) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) bestHigherHit = default(RaycastHit); lastGhostCandidateSource = "multi-ray"; bool result = false; float highestSurfaceY = currentSurfaceY; Collider[] componentsInChildren = ((Component)heldObject).GetComponentsInChildren<Collider>(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && val.enabled && TryResolveHighestRaycastHitFromCollider(val, heldObject, ref highestSurfaceY, ref bestHigherHit)) { result = true; } } return result; } private bool TryResolveHighestRaycastHitFromCollider(Collider collider, PhysGrabObject heldObject, ref float highestSurfaceY, ref RaycastHit bestHigherHit) { //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_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_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_0064: 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_0082: 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_00a2: Unknown result type (might be due to invalid IL or missing references) bool result = false; List<Vector3> list = new List<Vector3>(); CollectBottomFaceSamplePoints(collider, list); for (int i = 0; i < list.Count; i++) { int num = Physics.RaycastNonAlloc(list[i] + Vector3.up * 0.02f, Vector3.down, raycastHitBuffer, Plugin.LaserMaxDistance.Value, -5, (QueryTriggerInteraction)2); for (int j = 0; j < num; j++) { RaycastHit val = raycastHitBuffer[j]; if (IsValidBeamHit(val, heldObject)) { lastGhostCandidateHits.Add(new HitDebugInfo(val)); if (!(((RaycastHit)(ref val)).point.y <= highestSurfaceY)) { highestSurfaceY = ((RaycastHit)(ref val)).point.y; bestHigherHit = val; result = true; } } } } return result; } private static void CollectBottomFaceSamplePoints(Collider collider, List<Vector3> points) { //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_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_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) points.Clear(); if ((Object)(object)collider == (Object)null) { return; } BoxCollider val = (BoxCollider)(object)((collider is BoxCollider) ? collider : null); if (val != null) { AddBoxBottomFacePoints(val, points); return; } MeshCollider val2 = (MeshCollider)(object)((collider is MeshCollider) ? collider : null); if (val2 != null) { AddMeshBottomFacePoints(val2, points); if (points.Count > 0) { return; } } Bounds bounds = collider.bounds; points.Add(new Vector3(((Bounds)(ref bounds)).center.x, ((Bounds)(ref bounds)).min.y, ((Bounds)(ref bounds)).center.z)); } private static void AddBoxBottomFacePoints(BoxCollider box, List<Vector3> points) { //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_000f: 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_0025: 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_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_0043: 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_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_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_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_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_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_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_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_00c1: 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_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_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_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) Transform transform = ((Component)box).transform; Vector3 center = box.center; Vector3 val = box.size * 0.5f; float num = center.y - val.y; points.Add(transform.TransformPoint(new Vector3(center.x - val.x, num, center.z - val.z))); points.Add(transform.TransformPoint(new Vector3(center.x - val.x, num, center.z + val.z))); points.Add(transform.TransformPoint(new Vector3(center.x + val.x, num, center.z - val.z))); points.Add(transform.TransformPoint(new Vector3(center.x + val.x, num, center.z + val.z))); points.Add(transform.TransformPoint(new Vector3(center.x, num, center.z))); } private static void AddMeshBottomFacePoints(MeshCollider meshCollider, List<Vector3> points) { //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_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_0116: 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_012a: 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_012e: 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_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_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_00a6: 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_00bb: 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_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_00d3: 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_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_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_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_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) Mesh sharedMesh = meshCollider.sharedMesh; if ((Object)(object)sharedMesh == (Object)null) { return; } Vector3[] vertices = sharedMesh.vertices; Vector3[] normals = sharedMesh.normals; int[] triangles = sharedMesh.triangles; if (vertices == null || triangles == null || triangles.Length < 3) { return; } Transform transform = ((Component)meshCollider).transform; bool flag = normals != null && normals.Length == vertices.Length; for (int i = 0; i < triangles.Length; i += 3) { int num = triangles[i]; int num2 = triangles[i + 1]; int num3 = triangles[i + 2]; if (num >= 0 && num2 >= 0 && num3 >= 0 && num < vertices.Length && num2 < vertices.Length && num3 < vertices.Length) { Vector3 val2; bool flag2; if (flag) { Vector3 val = (normals[num] + normals[num2] + normals[num3]) / 3f; val2 = transform.TransformDirection(val); flag2 = Vector3.Dot(((Vector3)(ref val2)).normalized, Vector3.down) >= 0.85f; } else { Vector3 val3 = transform.TransformPoint(vertices[num]); Vector3 val4 = transform.TransformPoint(vertices[num2]); Vector3 val5 = transform.TransformPoint(vertices[num3]); val2 = Vector3.Cross(val4 - val3, val5 - val3); flag2 = Vector3.Dot(((Vector3)(ref val2)).normalized, Vector3.down) >= 0.85f; } if (flag2) { points.Add(transform.TransformPoint(vertices[num])); points.Add(transform.TransformPoint(vertices[num2])); points.Add(transform.TransformPoint(vertices[num3])); } } } } private static void LogStopInfoIfNeeded(string systemName, HitDebugInfo info, ref int nextLogFrame) { //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) if (Plugin.EnableLogging.Value && Plugin.EnableHitDiagnostics.Value && Time.frameCount >= nextLogFrame) { nextLogFrame = Time.frameCount + 1000; if (!info.HasHit) { DropLaserLogger.Info("[DropLaser] " + systemName + " stop: no valid hit."); return; } string text = LayerMask.LayerToName(info.Layer); string[] obj = new string[14] { "[DropLaser] ", systemName, " stop: object='", info.ObjectName, "', tag='", info.Tag, "', layer=", null, null, null, null, null, null, null }; int layer = info.Layer; obj[7] = layer.ToString(); obj[8] = "('"; obj[9] = text; obj[10] = "'), distance="; float distance = info.Distance; obj[11] = distance.ToString("0.###"); obj[12] = ", point="; Vector3 point = info.Point; obj[13] = ((Vector3)(ref point)).ToString("F3"); DropLaserLogger.Info(string.Concat(obj)); } } private Vector3 GetGhostStopPoint() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ghostRoot == (Object)null) { return Vector3.zero; } return CalculateBeamOrigin(ghostRoot); } private void EnsureGhostForHeldObject(PhysGrabObject heldObject) { //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_0164: Expected O, but got Unknown if ((Object)(object)heldObject == (Object)null || ((Object)(object)heldObject == (Object)(object)ghostSource && (Object)(object)ghostRoot != (Object)null)) { return; } DestroyGhost(); ghostSource = heldObject; ghostRenderers.Clear(); ghostRoot = CreateVisualOnlyGhostRoot(((Component)heldObject).gameObject); if ((Object)(object)ghostRoot == (Object)null) { if (ShouldLogGhostWarnings()) { Plugin.log.LogWarning((object)"[DropLaser] Failed to create visual-only ghost root."); } return; } ((Object)ghostRoot).name = ((Object)((Component)heldObject).gameObject).name + "_DropLaserGhost"; Object.DontDestroyOnLoad((Object)(object)ghostRoot); Renderer[] componentsInChildren = ghostRoot.GetComponentsInChildren<Renderer>(true); foreach (Renderer val in componentsInChildren) { if (val is LineRenderer || val is TrailRenderer) { val.enabled = false; continue; } Material val2 = (((Object)(object)sourceBeamLine != (Object)null && (Object)(object)((Renderer)sourceBeamLine).material != (Object)null) ? ((Renderer)sourceBeamLine).material : (((Object)(object)dropBeamLine != (Object)null) ? ((Renderer)dropBeamLine).material : val.sharedMaterial)); if ((Object)(object)val2 == (Object)null) { if (ShouldLogGhostWarnings()) { Plugin.log.LogWarning((object)("[DropLaser] Ghost renderer '" + ((Object)val).name + "' has no source material; skipping.")); } val.enabled = false; } else { Material material = (val.material = new Material(val2)); ghostRenderers.Add(new GhostRendererState { Renderer = val, Material = material }); } } if (ghostRenderers.Count == 0) { if (ShouldLogGhostWarnings()) { Plugin.log.LogWarning((object)"[DropLaser] Ghost had no supported renderers; disabling ghost preview for this object."); } DestroyGhost(); } else { ghostRoot.SetActive(false); } } private static GameObject CreateVisualOnlyGhostRoot(GameObject sourceRoot) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown if ((Object)(object)sourceRoot == (Object)null) { return null; } GameObject val = new GameObject(((Object)sourceRoot).name + "_GhostRoot"); CopyTransformOnly(sourceRoot.transform, val.transform); CopyVisualComponents(sourceRoot, val); BuildVisualHierarchy(sourceRoot.transform, val.transform); return val; } private static void BuildVisualHierarchy(Transform source, Transform targetParent) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown if (!((Object)(object)source == (Object)null) && !((Object)(object)targetParent == (Object)null)) { for (int i = 0; i < source.childCount; i++) { Transform child = source.GetChild(i); GameObject val = new GameObject(((Object)child).name); Transform transform = val.transform; transform.SetParent(targetParent, false); CopyTransformOnly(child, transform); CopyVisualComponents(((Component)child).gameObject, val); BuildVisualHierarchy(child, transform); } } } private static void CopyTransformOnly(Transform source, Transform target) { //IL_0