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 EnableLogging; public static ConfigEntry EnableLaser; public static ConfigEntry UseCustomColor; public static ConfigEntry CustomLaserColor; public static ConfigEntry LaserStartWidth; public static ConfigEntry LaserEndWidth; public static ConfigEntry LaserMaxDistance; public static ConfigEntry LaserLightIntensity; public static ConfigEntry LaserLightRange; public static ConfigEntry ToggleLaserKey; public static ConfigEntry AutoEnableOnGrab; public static ConfigEntry EnableDropBeamInnerWhite; public static ConfigEntry GhostPreviewMode; public static ConfigEntry UseCustomGhostColor; public static ConfigEntry CustomGhostColor; public static ConfigEntry GhostOpacity; public static ConfigEntry GhostEmissionIntensity; public static ConfigEntry GhostUpdateFrameInterval; public static ConfigEntry HighlightCycleForwardKey; public static ConfigEntry HighlightCycleBackwardKey; public static ConfigEntry DebugStopOverrideKey; public static ConfigEntry EnableDebugVisuals; public static ConfigEntry EnableHitDiagnostics; public static ConfigEntry AppliedConfigSchemaVersion; public static ConfigEntry 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("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("Laser Settings", "EnableLaser", true, "Master toggle for enabling/disabling the laser."); UseCustomColor = ((BaseUnityPlugin)this).Config.Bind("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("Laser Settings", "CustomLaserColor", Color.red, "The color the laser will use if UseCustomColor is true."); LaserStartWidth = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "LaserStartWidth", 0.04f, "The width of the laser at its start."); LaserEndWidth = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "LaserEndWidth", 0.03f, "The width of the laser at its end."); LaserMaxDistance = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "LaserMaxDistance", 500f, "Maximum distance the laser can scan downward."); LaserLightIntensity = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "LaserLightIntensity", 5.5f, "Intensity (brightness) of the laser glow light."); LaserLightRange = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "LaserLightRange", 0.5f, "Range (radius) of the laser glow light."); ToggleLaserKey = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "ToggleLaserKey", "L", "Key to press for toggling the laser on/off."); AutoEnableOnGrab = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "AutoEnableOnGrab", true, "If true, the laser will automatically enable when the player grabs an object."); EnableDropBeamInnerWhite = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "EnableDropBeamInnerWhite", true, "If true, shows a white inner core in the drop beam when above cart bounds."); GhostPreviewMode = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "GhostPreviewMode", 1, "Ghost preview behavior: 0 = never, 1 = on cart, 2 = always."); UseCustomGhostColor = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "UseCustomGhostColor", false, "If true, the ghost preview uses CustomGhostColor instead of laser color."); CustomGhostColor = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "CustomGhostColor", new Color(0f, 1f, 1f, 1f), "Ghost preview tint color when UseCustomGhostColor is true."); GhostOpacity = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "GhostOpacity", 0.35f, "Ghost preview opacity from 0.0 (invisible) to 1.0 (solid)."); GhostEmissionIntensity = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "GhostEmissionIntensity", 0.6f, "Ghost preview emission intensity multiplier."); GhostUpdateFrameInterval = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "GhostUpdateFrameInterval", 1, "Number of frames between ghost position updates. Higher values reduce update frequency."); HighlightCycleForwardKey = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "HighlightCycleForwardKey", "UpArrow", "Key used in debug mode to cycle cart highlight layers forward."); HighlightCycleBackwardKey = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "HighlightCycleBackwardKey", "DownArrow", "Key used in debug mode to cycle cart highlight layers backward."); DebugStopOverrideKey = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "DebugStopOverrideKey", "Return", "Debug-only key that temporarily changes laser/ghost stop behavior while held."); EnableDebugVisuals = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "EnableDebugVisuals", true, "If true, allows debug visualizers/highlighters when debug mode is active."); EnableHitDiagnostics = ((BaseUnityPlugin)this).Config.Bind("Laser Settings", "EnableHitDiagnostics", false, "If true, emits periodic hit diagnostics and stop-selection logs."); } private void BindInternalConfig() { AppliedConfigSchemaVersion = ((BaseUnityPlugin)this).Config.Bind("Internal", "AppliedConfigSchemaVersion", "2026-05-10.2", ""); PendingMigrationBackupPath = ((BaseUnityPlugin)this).Config.Bind("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 CachedCartInCartVolumes = new List(); 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(); 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(); if ((Object)(object)component != (Object)null) { CachedCartInCartVolumes.Add(component); } } } } } internal static class ConfigMigrationService { public static void ApplyIfOutdated(ConfigFile configFile, ConfigEntry appliedSchemaVersion, ConfigEntry 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) ? "" : 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 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(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(); 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 markersByCollider = new Dictionary(); private readonly HashSet liveColliders = new HashSet(); 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(); foreach (PhysGrabCart val in array) { if ((Object)(object)val == (Object)null) { continue; } Collider[] componentsInChildren = ((Component)val).GetComponentsInChildren(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 list = new List(); foreach (KeyValuePair 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 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(); if ((Object)(object)component != (Object)null) { component.enabled = false; } Renderer component2 = val2.GetComponent(); 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 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(); } _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 branches = new Dictionary(); 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(); 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 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 ghostRenderers = new List(); 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 lastGhostCandidateHits = new List(); private string lastGhostCandidateSource = "none"; public DropLaserBeam(LineRenderer dropBeamLine, LineRenderer grabBeamOverlayLine, LineRenderer dropBeamOverlayLine, Light dropBeamLight, GameObject sourceBeamObject, LineRenderer sourceBeamLine, PhysGrabber playerGrabber, HashSet 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(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 list = new List(); 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 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 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 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(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_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) target.localPosition = source.localPosition; target.localRotation = source.localRotation; target.localScale = source.localScale; } private static void CopyVisualComponents(GameObject source, GameObject target) { //IL_008a: Unknown result type (might be due to invalid IL or missing references) MeshFilter component = source.GetComponent(); if ((Object)(object)component != (Object)null) { target.AddComponent().sharedMesh = component.sharedMesh; } MeshRenderer component2 = source.GetComponent(); if ((Object)(object)component2 != (Object)null) { MeshRenderer obj = target.AddComponent(); ((Renderer)obj).sharedMaterials = ((Renderer)component2).sharedMaterials; ((Renderer)obj).enabled = ((Renderer)component2).enabled; } SkinnedMeshRenderer component3 = source.GetComponent(); if ((Object)(object)component3 != (Object)null) { SkinnedMeshRenderer obj2 = target.AddComponent(); obj2.sharedMesh = component3.sharedMesh; ((Renderer)obj2).sharedMaterials = ((Renderer)component3).sharedMaterials; ((Renderer)obj2).enabled = ((Renderer)component3).enabled; ((Renderer)obj2).localBounds = ((Renderer)component3).localBounds; obj2.updateWhenOffscreen = component3.updateWhenOffscreen; } } private void SetGhostVisible(bool visible) { //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ghostRoot == (Object)null) { return; } if (!visible) { ghostRoot.SetActive(false); return; } ghostRoot.SetActive(true); Material val = (((Object)(object)sourceBeamLine != (Object)null && (Object)(object)((Renderer)sourceBeamLine).material != (Object)null) ? ((Renderer)sourceBeamLine).material : ((Renderer)dropBeamLine).material); if ((Object)(object)val == (Object)null) { ghostRoot.SetActive(false); return; } float opacity = Mathf.Clamp01(Plugin.GhostOpacity.Value); float emissionIntensity = Mathf.Max(0f, Plugin.GhostEmissionIntensity.Value); Color tint = (Plugin.UseCustomGhostColor.Value ? Plugin.CustomGhostColor.Value : DropLaserColorManager.GetFinalLaserColor(val)); foreach (GhostRendererState ghostRenderer in ghostRenderers) { if (ghostRenderer != null && !((Object)(object)ghostRenderer.Renderer == (Object)null) && !((Object)(object)ghostRenderer.Material == (Object)null)) { DropLaserMaterialService.MirrorMaterialAppearance(ghostRenderer.Material, val); ApplyGhostTint(ghostRenderer.Material, tint, emissionIntensity); ApplyGhostOpacity(ghostRenderer.Material, opacity); } } } private void DestroyGhost() { if ((Object)(object)ghostRoot != (Object)null) { Object.Destroy((Object)(object)ghostRoot); } ghostRoot = null; ghostSource = null; } private bool IsPartOfHeldObject(GameObject hitObject, GameObject heldObject) { if ((Object)(object)hitObject == (Object)null || (Object)(object)heldObject == (Object)null) { return false; } Transform val = hitObject.transform; while ((Object)(object)val != (Object)null) { if ((Object)(object)((Component)val).gameObject == (Object)(object)heldObject) { return true; } val = val.parent; } return false; } private static void ApplyLaserMaterialAppearance(Material target, Material sourceLaserMaterial, Color color, float alpha, float emissionScale) { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_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_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)target == (Object)null) && !((Object)(object)sourceLaserMaterial == (Object)null)) { if (sourceLaserMaterial.HasProperty("_MainTex") && target.HasProperty("_MainTex")) { target.SetTexture("_MainTex", sourceLaserMaterial.GetTexture("_MainTex")); target.mainTextureOffset = sourceLaserMaterial.mainTextureOffset; target.mainTextureScale = sourceLaserMaterial.mainTextureScale; } Color color2 = default(Color); ((Color)(ref color2))..ctor(color.r, color.g, color.b, alpha); DropLaserMaterialService.WriteColor(target, color2); if (target.HasProperty("_EmissionColor")) { target.SetColor("_EmissionColor", new Color(color.r, color.g, color.b, emissionScale)); } } } private static void ApplyGhostOpacity(Material material, float opacity) { DropLaserMaterialService.ApplyOpacityToKnownColorProperties(material, opacity); } private static void ApplyGhostTint(Material material, Color tint, float emissionIntensity) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)material == (Object)null)) { DropLaserMaterialService.WriteColor(material, new Color(tint.r, tint.g, tint.b, 1f)); if (material.HasProperty("_EmissionColor")) { material.SetColor("_EmissionColor", tint * emissionIntensity); } } } private static Bounds GetObjectBounds(GameObject root) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Collider[] componentsInChildren = root.GetComponentsInChildren(true); if (componentsInChildren.Length != 0) { Bounds bounds = componentsInChildren[0].bounds; for (int i = 1; i < componentsInChildren.Length; i++) { ((Bounds)(ref bounds)).Encapsulate(componentsInChildren[i].bounds); } return bounds; } Renderer[] componentsInChildren2 = root.GetComponentsInChildren(true); if (componentsInChildren2.Length != 0) { Bounds bounds2 = componentsInChildren2[0].bounds; for (int j = 1; j < componentsInChildren2.Length; j++) { ((Bounds)(ref bounds2)).Encapsulate(componentsInChildren2[j].bounds); } return bounds2; } return new Bounds(root.transform.position, Vector3.one * 0.1f); } private void DumpBeamHitsIfNeeded(PhysGrabObject heldObject, bool isAboveCart) { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_02a8: Unknown result type (might be due to invalid IL or missing references) //IL_02ad: Unknown result type (might be due to invalid IL or missing references) //IL_039f: Unknown result type (might be due to invalid IL or missing references) //IL_03a4: Unknown result type (might be due to invalid IL or missing references) //IL_0518: Unknown result type (might be due to invalid IL or missing references) //IL_051d: Unknown result type (might be due to invalid IL or missing references) if (!Plugin.EnableLogging.Value || !Plugin.EnableHitDiagnostics.Value || debugService.IsDebugModeActive || !isAboveCart || Time.time < nextRegularHitDumpTime) { return; } nextRegularHitDumpTime = Time.time + 5f; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("[DropLaser] Regular mode beam hits (sorted by distance):"); List list = new List(); for (int i = 0; i < lastBeamHitCount; i++) { RaycastHit item = raycastHitBuffer[i]; if (!((Object)(object)((RaycastHit)(ref item)).collider == (Object)null)) { list.Add(item); } } List list2 = list.OrderBy((RaycastHit h) => ((RaycastHit)(ref h)).distance).ToList(); int num = 0; for (int j = 0; j < list2.Count; j++) { RaycastHit hit = list2[j]; GameObject gameObject = ((Component)((RaycastHit)(ref hit)).collider).gameObject; bool flag = IsValidBeamHit(hit, heldObject); stringBuilder.Append(" #").Append(num + 1).Append(" | obj='") .Append(((Object)gameObject).name) .Append("' | tag='") .Append(gameObject.tag) .Append("' | layer=") .Append(gameObject.layer) .Append("('") .Append(LayerMask.LayerToName(gameObject.layer)) .Append("')") .Append(" | dist=") .Append(((RaycastHit)(ref hit)).distance.ToString("0.###")) .Append(" | valid=") .Append(flag ? "yes" : "no") .AppendLine(); num++; } if (num == 0) { stringBuilder.AppendLine(" (no hits)"); } Vector3 point; if (hasLastChosenBeamStopInfo && lastChosenBeamStopInfo.HasHit) { StringBuilder stringBuilder2 = stringBuilder.Append(" chosen-beam: obj='").Append(lastChosenBeamStopInfo.ObjectName).Append("' | tag='") .Append(lastChosenBeamStopInfo.Tag) .Append("' | layer=") .Append(lastChosenBeamStopInfo.Layer) .Append("('") .Append(LayerMask.LayerToName(lastChosenBeamStopInfo.Layer)) .Append("')") .Append(" | dist="); float distance = lastChosenBeamStopInfo.Distance; StringBuilder stringBuilder3 = stringBuilder2.Append(distance.ToString("0.###")).Append(" | point="); point = lastChosenBeamStopInfo.Point; stringBuilder3.Append(((Vector3)(ref point)).ToString("F3")).AppendLine(); } else { stringBuilder.AppendLine(" chosen-beam: none"); } if (hasLastChosenGhostStopInfo && lastChosenGhostStopInfo.HasHit) { StringBuilder stringBuilder4 = stringBuilder.Append(" chosen-ghost: obj='").Append(lastChosenGhostStopInfo.ObjectName).Append("' | tag='") .Append(lastChosenGhostStopInfo.Tag) .Append("' | layer=") .Append(lastChosenGhostStopInfo.Layer) .Append("('") .Append(LayerMask.LayerToName(lastChosenGhostStopInfo.Layer)) .Append("')") .Append(" | dist="); float distance = lastChosenGhostStopInfo.Distance; StringBuilder stringBuilder5 = stringBuilder4.Append(distance.ToString("0.###")).Append(" | point="); point = lastChosenGhostStopInfo.Point; stringBuilder5.Append(((Vector3)(ref point)).ToString("F3")).AppendLine(); } else { stringBuilder.AppendLine(" chosen-ghost: none"); } stringBuilder.AppendLine(" ghost-candidates (" + lastGhostCandidateSource + "):"); if (lastGhostCandidateHits.Count == 0) { stringBuilder.AppendLine(" (none)"); } else { List list3 = (from h in lastGhostCandidateHits where h.HasHit orderby h.Distance select h).ToList(); for (int k = 0; k < list3.Count; k++) { HitDebugInfo hitDebugInfo = list3[k]; StringBuilder stringBuilder6 = stringBuilder.Append(" #").Append(k + 1).Append(" | obj='") .Append(hitDebugInfo.ObjectName) .Append("' | tag='") .Append(hitDebugInfo.Tag) .Append("' | layer=") .Append(hitDebugInfo.Layer) .Append("('") .Append(LayerMask.LayerToName(hitDebugInfo.Layer)) .Append("')") .Append(" | dist="); float distance = hitDebugInfo.Distance; StringBuilder stringBuilder7 = stringBuilder6.Append(distance.ToString("0.###")).Append(" | point="); point = hitDebugInfo.Point; stringBuilder7.Append(((Vector3)(ref point)).ToString("F3")).AppendLine(); } } Plugin.log.LogWarning((object)stringBuilder.ToString()); } } public static class DropLaserColorManager { public static Color GetFinalLaserColor(Material beamMat) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: 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_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) if (Plugin.UseCustomColor.Value) { return ClampColor(Plugin.CustomLaserColor.Value); } Color val = Color.white; Color val2 = Color.black; if ((Object)(object)beamMat != (Object)null) { if (beamMat.HasProperty("_Color")) { val = beamMat.GetColor("_Color"); } if (beamMat.HasProperty("_EmissionColor")) { val2 = beamMat.GetColor("_EmissionColor"); } } return ClampColor(val + val2); } private static Color ClampColor(Color color) { //IL_0002: 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_0026: 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_0048: Unknown result type (might be due to invalid IL or missing references) color.r = Mathf.Clamp01(color.r); color.g = Mathf.Clamp01(color.g); color.b = Mathf.Clamp01(color.b); color.a = Mathf.Clamp01(color.a); return color; } } public class DropLaserController : MonoBehaviour { private static readonly HashSet IgnoredCartParts = new HashSet { "In Cart", "Capsule Mid", "Capsule Left", "Capsule Right" }; private LineRenderer dropBeamLine; private LineRenderer grabBeamOverlayLine; private LineRenderer dropBeamOverlayLine; private Light dropBeamLight; private DropLaserBeam dropLaserBeam; private GameObject sourceBeamObject; private LineRenderer sourceBeamLine; private PhysGrabber playerGrabber; private bool isActive; private void Awake() { if (!Plugin.EnableLaser.Value) { Plugin.log.LogWarning((object)"[DropLaser] Laser system disabled via config. Destroying DropLaserController..."); Object.Destroy((Object)(object)((Component)this).gameObject); return; } DropLaserLogger.Info("[DropLaser] Awake called"); SetupLineRenderer(); SetupLaserLight(); SceneManager.sceneLoaded += HandleSceneLoaded; } private void Start() { DropLaserLogger.Info("[DropLaser] Start called"); TryFindPlayerBeam(); if ((Object)(object)sourceBeamObject != (Object)null && (Object)(object)sourceBeamLine != (Object)null && (Object)(object)playerGrabber != (Object)null) { dropLaserBeam = new DropLaserBeam(dropBeamLine, grabBeamOverlayLine, dropBeamOverlayLine, dropBeamLight, sourceBeamObject, sourceBeamLine, playerGrabber, IgnoredCartParts); } } private void Update() { if (!isActive || dropLaserBeam == null) { return; } try { dropLaserBeam.UpdateBeam(); } catch (Exception arg) { Plugin.log.LogError((object)$"[DropLaser] Beam subsystem failure (isolated): {arg}"); } } public void Toggle() { isActive = !isActive; if ((Object)(object)dropBeamLine != (Object)null) { ((Renderer)dropBeamLine).enabled = isActive; } if ((Object)(object)dropBeamLight != (Object)null) { ((Behaviour)dropBeamLight).enabled = isActive; } if (!isActive && (Object)(object)grabBeamOverlayLine != (Object)null) { ((Renderer)grabBeamOverlayLine).enabled = false; } if (!isActive && (Object)(object)dropBeamOverlayLine != (Object)null) { ((Renderer)dropBeamOverlayLine).enabled = false; } if (!isActive) { dropLaserBeam?.Dispose(); } DropLaserLogger.Info("[DropLaser] Laser toggled " + (isActive ? "ON" : "OFF")); } public void DisableLaser() { if ((Object)(object)dropBeamLine != (Object)null) { ((Renderer)dropBeamLine).enabled = false; } if ((Object)(object)dropBeamLight != (Object)null) { ((Behaviour)dropBeamLight).enabled = false; } if ((Object)(object)grabBeamOverlayLine != (Object)null) { ((Renderer)grabBeamOverlayLine).enabled = false; } if ((Object)(object)dropBeamOverlayLine != (Object)null) { ((Renderer)dropBeamOverlayLine).enabled = false; } isActive = false; dropLaserBeam?.Dispose(); } private void OnDestroy() { SceneManager.sceneLoaded -= HandleSceneLoaded; dropLaserBeam?.Dispose(); DropLaserLogger.Info("[DropLaser] OnDestroy called - DropLaserController cleaned up."); } private void SetupLineRenderer() { //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_00ca: Unknown result type (might be due to invalid IL or missing references) dropBeamLine = ((Component)this).gameObject.AddComponent(); ConfigureLineRenderer(dropBeamLine); Shader val = Shader.Find("Particles/Standard Unlit") ?? Shader.Find("Unlit/Color") ?? Shader.Find("Sprites/Default"); if ((Object)(object)val == (Object)null) { Plugin.log.LogError((object)"[DropLaser] Failed to find a line renderer shader. Disabling controller setup."); return; } ((Renderer)dropBeamLine).material = DropLaserMaterialService.CreateTransparentLineMaterial(val); float num = Plugin.LaserStartWidth?.Value ?? 0.04f; float num2 = Plugin.LaserEndWidth?.Value ?? 0.03f; dropBeamLine.startWidth = num; dropBeamLine.endWidth = num2; Color red = Color.red; dropBeamLine.startColor = red; dropBeamLine.endColor = red; ((Renderer)dropBeamLine).enabled = false; try { grabBeamOverlayLine = CreateOverlayLine("GrabBeamOverlayLine", val, num, num2); dropBeamOverlayLine = CreateOverlayLine("DropBeamOverlayLine", val, num, num2); } catch (Exception ex) { grabBeamOverlayLine = null; dropBeamOverlayLine = null; Plugin.log.LogWarning((object)("[DropLaser] Overlay beam setup failed; continuing without overlay: " + ex.Message)); } } private void ConfigureLineRenderer(LineRenderer lineRenderer) { lineRenderer.positionCount = 2; ((Renderer)lineRenderer).shadowCastingMode = (ShadowCastingMode)0; ((Renderer)lineRenderer).receiveShadows = false; lineRenderer.useWorldSpace = true; lineRenderer.textureMode = (LineTextureMode)0; lineRenderer.numCapVertices = 8; lineRenderer.numCornerVertices = 2; } private LineRenderer CreateOverlayLine(string objectName, Shader shader, float baseStartWidth, float baseEndWidth) { //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_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(objectName); val.transform.SetParent(((Component)this).transform, false); LineRenderer val2 = val.AddComponent(); ConfigureLineRenderer(val2); ((Renderer)val2).material = DropLaserMaterialService.CreateTransparentLineMaterial(shader); val2.startWidth = baseStartWidth * 0.35f; val2.endWidth = baseEndWidth * 0.35f; val2.startColor = Color.white; val2.endColor = Color.white; ((Renderer)val2).enabled = false; return val2; } private void SetupLaserLight() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) dropBeamLight = new GameObject("DropLaserLight").AddComponent(); dropBeamLight.type = (LightType)2; dropBeamLight.range = Plugin.LaserLightRange.Value; dropBeamLight.intensity = Plugin.LaserLightIntensity.Value; ((Behaviour)dropBeamLight).enabled = false; } private void TryFindPlayerBeam() { //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Expected O, but got Unknown bool flag = PhotonNetwork.PlayerList.Length < 1; PhysGrabber[] array = Object.FindObjectsOfType(); foreach (PhysGrabber val in array) { PhotonView component = ((Component)val).GetComponent(); if (flag) { playerGrabber = val; DropLaserLogger.Info("[DropLaser] Singleplayer detected - attaching to first PhysGrabber."); break; } if ((Object)(object)component != (Object)null && component.IsMine) { playerGrabber = val; DropLaserLogger.Info("[DropLaser] Multiplayer detected - attached to local player's PhysGrabber."); break; } } if ((Object)(object)playerGrabber == (Object)null) { Plugin.log.LogWarning((object)"[DropLaser] Could not find local player's PhysGrabber!"); return; } sourceBeamObject = playerGrabber.GetBeamObject(); if ((Object)(object)sourceBeamObject == (Object)null) { Plugin.log.LogWarning((object)"[DropLaser] Beam GameObject is null!"); return; } DropLaserLogger.Info("[DropLaser] Beam GameObject found!"); sourceBeamLine = sourceBeamObject.GetComponent(); if ((Object)(object)sourceBeamLine == (Object)null) { Plugin.log.LogWarning((object)"[DropLaser] GrabBeam has no LineRenderer!"); return; } DropLaserLogger.Info("[DropLaser] GrabBeam LineRenderer found!"); if ((Object)(object)((Renderer)sourceBeamLine).material != (Object)null) { ((Renderer)dropBeamLine).material = new Material(((Renderer)sourceBeamLine).material); DropLaserMaterialService.ConfigureTransparentMaterial(((Renderer)dropBeamLine).material); Shader shader = ((Renderer)dropBeamLine).material.shader; DropLaserLogger.Info("[DropLaser] Cloned grab beam material shader: " + ((shader != null) ? ((Object)shader).name : null)); } } private void HandleSceneLoaded(Scene scene, LoadSceneMode mode) { DropLaserLogger.Info("[DropLaser] New scene loaded - destroying old DropLaserController instance."); Object.Destroy((Object)(object)((Component)this).gameObject); } } }