Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of HaulOfFame v1.0.2
plugins\HaulOfFame.dll
Decompiled 10 hours ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Text; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using HaulOfFame.Config; using HaulOfFame.Core; using HaulOfFame.Network; using HaulOfFame.UI; using HaulOfFame.Utils; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using UnityEngine; using UnityEngine.Rendering; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("HaulOfFame")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.2.0")] [assembly: AssemblyInformationalVersion("1.0.2")] [assembly: AssemblyProduct("HaulOfFame")] [assembly: AssemblyTitle("HaulOfFame")] [assembly: AssemblyVersion("1.0.2.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace HaulOfFame { [BepInPlugin("com.juanma.hauloffame", "HaulOfFame", "1.0.2")] [BepInProcess("REPO.exe")] public sealed class Plugin : BaseUnityPlugin { public const string PluginGuid = "com.juanma.hauloffame"; public const string PluginName = "HaulOfFame"; public const string PluginVersion = "1.0.2"; private static Plugin? _activeInstance; private ModConfig? _modConfig; private GameBindings? _bindings; private HaulController? _controller; private Harmony? _harmony; private void Awake() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Expected O, but got Unknown Scene activeScene = SceneManager.GetActiveScene(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HaulOfFame] Loaded v1.0.2"); ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}/Lifecycle] Awake: unity={1}, gameVersion={2}, scene={3}[{4}], config={5}", "HaulOfFame", Application.unityVersion, Application.version, ((Scene)(ref activeScene)).name, ((Scene)(ref activeScene)).buildIndex, ((BaseUnityPlugin)this).Config.ConfigFilePath)); _modConfig = new ModConfig(((BaseUnityPlugin)this).Config); _bindings = new GameBindings(((BaseUnityPlugin)this).Logger); if (_bindings.Resolve()) { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HaulOfFame/Bindings] Required game bindings resolved."); } else { ((BaseUnityPlugin)this).Logger.LogWarning((object)"[HaulOfFame/Bindings] One or more inspected fields are unavailable; affected captures will be skipped safely."); } try { _controller = new HaulController(_modConfig, _bindings, ((BaseUnityPlugin)this).Logger); } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("[HaulOfFame/Lifecycle] Initialization failed safely: " + ex.GetType().Name + ": " + ex.Message)); return; } _activeInstance = this; _harmony = new Harmony("com.juanma.hauloffame"); int num = 0; num += (InstallPatch(typeof(ExtractionPoint), "SpawnExtractingVisuals", "ValuableExtractingPrefix", prefix: true) ? 1 : 0); num += (InstallPatch(typeof(RoundDirector), "ExtractionCompleted", "ExtractionCompletedPostfix", prefix: false) ? 1 : 0); num += (InstallPatch(typeof(ItemValuableBox), "StartAbsorbLocal", "ValuableStoredPrefix", prefix: true) ? 1 : 0); num += (InstallPatch(typeof(ItemValuableBox), "OnExtracted", "ValuableBoxExtractedPrefix", prefix: true) ? 1 : 0); MethodInfo methodInfo = AccessTools.Method(typeof(Plugin), "GameUpdatePostfix", (Type[])null, (Type[])null); if (methodInfo != null) { num += (InstallUpdateHook(typeof(GameDirector), methodInfo) ? 1 : 0); num += (InstallUpdateHook(typeof(RunManager), methodInfo) ? 1 : 0); } SceneManager.sceneLoaded += OnSceneLoaded; SceneManager.activeSceneChanged += OnActiveSceneChanged; ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}/Lifecycle] Installed {1}/6 hooks. Ready to record extracted valuables.", "HaulOfFame", num)); } private void Update() { _controller?.Tick(Time.unscaledDeltaTime); } private static void GameUpdatePostfix() { _activeInstance?._controller?.Tick(Time.unscaledDeltaTime); } private static void ValuableExtractingPrefix(ExtractionPoint __instance, PhysGrabObject __0) { _activeInstance?._controller?.OnValuableExtracting(__instance, __0); } private static void ExtractionCompletedPostfix(RoundDirector __instance) { _activeInstance?._controller?.OnExtractionCompleted(__instance); } private static void ValuableStoredPrefix(ItemValuableBox __instance, PhysGrabObject __0) { _activeInstance?._controller?.OnValuableStored(__instance, __0); } private static void ValuableBoxExtractedPrefix(ItemValuableBox __instance) { _activeInstance?._controller?.OnValuableBoxExtracted(__instance); } private bool InstallPatch(Type gameType, string methodName, string patchName, bool prefix) { //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Expected O, but got Unknown //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(gameType, methodName, (Type[])null, (Type[])null); MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), patchName, (Type[])null, (Type[])null); if (methodInfo == null || methodInfo2 == null || _harmony == null) { ((BaseUnityPlugin)this).Logger.LogWarning((object)("[HaulOfFame/Hooks] Could not patch " + gameType.Name + "." + methodName + ".")); return false; } if (prefix) { _harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } else { _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); } ((BaseUnityPlugin)this).Logger.LogInfo((object)("[HaulOfFame/Hooks] Patched " + gameType.Name + "." + methodName + " (" + (prefix ? "prefix" : "postfix") + ").")); return true; } private bool InstallUpdateHook(Type gameType, MethodInfo postfix) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown MethodInfo methodInfo = AccessTools.Method(gameType, "Update", (Type[])null, (Type[])null); if (methodInfo == null || _harmony == null) { return false; } _harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(postfix), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); return true; } private void OnSceneLoaded(Scene scene, LoadSceneMode mode) { //IL_0034: 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) ((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("[{0}/Scene] Loaded: {1}[{2}], mode={3}, frame={4}.", "HaulOfFame", ((Scene)(ref scene)).name, ((Scene)(ref scene)).buildIndex, mode, Time.frameCount)); _controller?.HandleSceneChanged(scene); } private void OnActiveSceneChanged(Scene previous, Scene current) { ModConfig? modConfig = _modConfig; if (modConfig != null && modConfig.DebugLogging.Value) { ((BaseUnityPlugin)this).Logger.LogInfo((object)("[HaulOfFame/Scene] Active scene: " + ((Scene)(ref previous)).name + " -> " + ((Scene)(ref current)).name + ".")); } } private void OnDestroy() { ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HaulOfFame/Lifecycle] Shutdown started."); SceneManager.sceneLoaded -= OnSceneLoaded; SceneManager.activeSceneChanged -= OnActiveSceneChanged; Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } if ((Object)(object)_activeInstance == (Object)(object)this) { _activeInstance = null; } _controller?.Dispose(); _modConfig?.Dispose(); ((BaseUnityPlugin)this).Logger.LogInfo((object)"[HaulOfFame/Lifecycle] Shutdown complete."); } } } namespace HaulOfFame.Utils { internal static class TextureUtils { public static Sprite CreateRoundedRectSprite(string name, int width, int height, int radius, int borderThickness = 0) { //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Expected O, but got Unknown //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: Unknown result type (might be due to invalid IL or missing references) //IL_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) Texture2D val = new Texture2D(width, height, (TextureFormat)4, false) { name = name + "_Texture", filterMode = (FilterMode)1, wrapMode = (TextureWrapMode)1, hideFlags = (HideFlags)61 }; Color32[] array = (Color32[])(object)new Color32[width * height]; for (int i = 0; i < height; i++) { for (int j = 0; j < width; j++) { bool flag = InsideRoundedRect((float)j + 0.5f, (float)i + 0.5f, width, height, radius, 0); bool flag2 = borderThickness > 0 && InsideRoundedRect((float)j + 0.5f, (float)i + 0.5f, width, height, Mathf.Max(0, radius - borderThickness), borderThickness); array[i * width + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)((flag && !flag2) ? byte.MaxValue : 0)); } } val.SetPixels32(array); val.Apply(false, true); Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)width, (float)height), new Vector2(0.5f, 0.5f), 100f); ((Object)obj).name = name; ((Object)obj).hideFlags = (HideFlags)61; return obj; } private static bool InsideRoundedRect(float x, float y, int width, int height, int radius, int inset) { int num = width - inset; int num2 = height - inset; if (x < (float)inset || x > (float)num || y < (float)inset || y > (float)num2) { return false; } if (radius <= 0) { return true; } float num3 = Mathf.Clamp(x, (float)(inset + radius), (float)(num - radius)); float num4 = Mathf.Clamp(y, (float)(inset + radius), (float)(num2 - radius)); float num5 = x - num3; float num6 = y - num4; return num5 * num5 + num6 * num6 <= (float)(radius * radius); } } } namespace HaulOfFame.UI { public sealed class AnnouncementHud : IDisposable { private readonly ModConfig _config; private readonly GameObject _root; private readonly RectTransform _panel; private readonly CanvasGroup _canvasGroup; private readonly Image _panelImage; private readonly Image _accentImage; private readonly Text _title; private readonly Text _name; private readonly Text _details; private readonly Sprite _panelSprite; private readonly Font _font; private readonly bool _ownsFont; private readonly AudioClip _sound; private readonly AudioSource _audioSource; private float _elapsed; private float _duration; private bool _visible; public AnnouncementHud(ModConfig config) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0186: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Expected O, but got Unknown //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_01f3: Unknown result type (might be due to invalid IL or missing references) //IL_020d: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) //IL_02a0: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02d4: Unknown result type (might be due to invalid IL or missing references) //IL_02e9: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0312: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_035b: Unknown result type (might be due to invalid IL or missing references) //IL_036a: 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_03b3: Unknown result type (might be due to invalid IL or missing references) //IL_03c2: Unknown result type (might be due to invalid IL or missing references) //IL_03fc: Unknown result type (might be due to invalid IL or missing references) //IL_040b: Unknown result type (might be due to invalid IL or missing references) //IL_041a: Unknown result type (might be due to invalid IL or missing references) _config = config; _font = Font.CreateDynamicFontFromOSFont(new string[4] { "Bahnschrift SemiCondensed", "Arial Narrow", "Segoe UI Semibold", "Arial" }, 20); if ((Object)(object)_font != (Object)null) { _ownsFont = true; } else { _font = Resources.GetBuiltinResource<Font>("Arial.ttf"); } _panelSprite = TextureUtils.CreateRoundedRectSprite("HaulOfFame_BannerPanel", 300, 64, 6); _sound = CreateSound(); _root = new GameObject("HaulOfFame_Announcement") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_root); _audioSource = _root.AddComponent<AudioSource>(); _audioSource.playOnAwake = false; _audioSource.loop = false; _audioSource.spatialBlend = 0f; _audioSource.ignoreListenerPause = true; Canvas obj = _root.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 25000; CanvasScaler obj2 = _root.AddComponent<CanvasScaler>(); obj2.uiScaleMode = (ScaleMode)1; obj2.referenceResolution = new Vector2(1920f, 1080f); obj2.screenMatchMode = (ScreenMatchMode)0; obj2.matchWidthOrHeight = 0.5f; GameObject val = new GameObject("Panel", new Type[4] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image), typeof(CanvasGroup) }); val.transform.SetParent(_root.transform, false); _panel = val.GetComponent<RectTransform>(); _panel.anchorMin = new Vector2(0.5f, 1f); _panel.anchorMax = new Vector2(0.5f, 1f); _panel.pivot = new Vector2(0.5f, 1f); _panel.anchoredPosition = new Vector2(0f, -62f); _panel.sizeDelta = new Vector2(650f, 126f); _panelImage = val.GetComponent<Image>(); _panelImage.sprite = _panelSprite; _panelImage.type = (Type)1; ((Graphic)_panelImage).raycastTarget = false; _canvasGroup = val.GetComponent<CanvasGroup>(); _canvasGroup.blocksRaycasts = false; _canvasGroup.interactable = false; _accentImage = CreateImage("Accent", (Transform)(object)_panel, new Vector2(0f, 0f), new Vector2(7f, 110f)); RectTransform rectTransform = ((Graphic)_accentImage).rectTransform; rectTransform.anchorMin = new Vector2(0f, 0.5f); rectTransform.anchorMax = new Vector2(0f, 0.5f); rectTransform.pivot = new Vector2(0f, 0.5f); rectTransform.anchoredPosition = new Vector2(8f, 0f); _title = CreateText("Title", (Transform)(object)_panel, 18, (FontStyle)1, (TextAnchor)3); SetRect(((Graphic)_title).rectTransform, new Vector2(26f, -12f), new Vector2(598f, 24f), new Vector2(0f, 1f)); _name = CreateText("Name", (Transform)(object)_panel, 29, (FontStyle)1, (TextAnchor)3); SetRect(((Graphic)_name).rectTransform, new Vector2(26f, -39f), new Vector2(598f, 38f), new Vector2(0f, 1f)); _details = CreateText("Details", (Transform)(object)_panel, 17, (FontStyle)0, (TextAnchor)3); SetRect(((Graphic)_details).rectTransform, new Vector2(26f, -82f), new Vector2(598f, 28f), new Vector2(0f, 1f)); ApplyConfig(); _root.SetActive(false); } public void Show(string title, string name, string details) { if (_config.Enabled.Value && _config.ShowAnnouncement.Value) { _title.text = title; _name.text = name; _details.text = details; _elapsed = 0f; _duration = Mathf.Clamp(_config.AnnouncementDuration.Value, 1f, 20f); _visible = true; _root.SetActive(true); if (_config.SoundEnabled.Value) { _audioSource.PlayOneShot(_sound, Mathf.Clamp01(_config.SoundVolume.Value)); } } } public void Tick(float unscaledDeltaTime) { //IL_0093: Unknown result type (might be due to invalid IL or missing references) if (_visible) { _elapsed += Mathf.Max(0f, unscaledDeltaTime); float num = Mathf.Clamp01(_elapsed / 0.22f); float num2 = Mathf.Clamp01((_duration - _elapsed) / 0.55f); _canvasGroup.alpha = Mathf.Min(num, num2); float num3 = 1f - EaseOutBack(Mathf.Clamp01(_elapsed / 0.36f)); _panel.anchoredPosition = new Vector2(0f, -62f - num3 * 55f); if (_elapsed >= _duration) { Hide(); } } } public void Hide() { _visible = false; if ((Object)(object)_root != (Object)null) { _root.SetActive(false); } } public void ApplyConfig() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) Color accentColor = _config.GetAccentColor(); ((Graphic)_panelImage).color = new Color(0.006f, 0.012f, 0.016f, 0.94f); ((Graphic)_accentImage).color = accentColor; ((Graphic)_title).color = new Color(accentColor.r, accentColor.g, accentColor.b, 0.88f); ((Graphic)_name).color = new Color(0.96f, 1f, 0.97f, 1f); ((Graphic)_details).color = new Color(0.72f, 0.82f, 0.76f, 1f); if (!_config.Enabled.Value || !_config.ShowAnnouncement.Value) { Hide(); } } private Text CreateText(string name, Transform parent, int fontSize, FontStyle style, TextAnchor alignment) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Text) }); val.transform.SetParent(parent, false); Text component = val.GetComponent<Text>(); component.font = _font; component.fontSize = fontSize; component.fontStyle = style; component.alignment = alignment; component.horizontalOverflow = (HorizontalWrapMode)1; component.verticalOverflow = (VerticalWrapMode)0; component.supportRichText = true; ((Graphic)component).raycastTarget = false; return component; } private static Image CreateImage(string name, Transform parent, Vector2 position, Vector2 size) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name, new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val.transform.SetParent(parent, false); Image component = val.GetComponent<Image>(); ((Graphic)component).raycastTarget = false; ((Graphic)component).rectTransform.anchoredPosition = position; ((Graphic)component).rectTransform.sizeDelta = size; return component; } private static void SetRect(RectTransform rect, Vector2 position, Vector2 size, Vector2 pivot) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) rect.anchorMin = new Vector2(0f, 1f); rect.anchorMax = new Vector2(0f, 1f); rect.pivot = pivot; rect.anchoredPosition = position; rect.sizeDelta = size; } private static float EaseOutBack(float value) { float num = value - 1f; return 1f + 2.70158f * num * num * num + 1.70158f * num * num; } private static AudioClip CreateSound() { int num = Mathf.CeilToInt(19404f); float[] array = new float[num]; for (int i = 0; i < num; i++) { float num2 = (float)i / 44100f; float num3 = ((num2 < 0.14f) ? 392f : ((num2 < 0.28f) ? 523.25f : 783.99f)); float num4 = Mathf.Clamp01(num2 * 35f) * Mathf.Exp(-4.8f * num2); array[i] = (Mathf.Sin(MathF.PI * 2f * num3 * num2) + 0.32f * Mathf.Sin(MathF.PI * 2f * num3 * 2f * num2)) * num4 * 0.16f; } AudioClip obj = AudioClip.Create("HaulOfFame_Result", num, 1, 44100, false); ((Object)obj).hideFlags = (HideFlags)61; obj.SetData(array, 0); return obj; } public void Dispose() { if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } if ((Object)(object)_panelSprite != (Object)null) { Texture2D texture = _panelSprite.texture; Object.Destroy((Object)(object)_panelSprite); if ((Object)(object)texture != (Object)null) { Object.Destroy((Object)(object)texture); } } if ((Object)(object)_sound != (Object)null) { Object.Destroy((Object)(object)_sound); } if (_ownsFont && (Object)(object)_font != (Object)null) { Object.Destroy((Object)(object)_font); } } } public sealed class TrophyController : IDisposable { private readonly ModConfig _config; private readonly GameBindings _bindings; private readonly ManualLogSource _logger; private readonly GameObject _root; private readonly Transform _modelMount; private readonly GameObject _fallbackModel; private readonly RectTransform _plaqueCanvas; private readonly Image _plaquePanel; private readonly Image _plaqueAccent; private readonly Text _plaqueText; private readonly Light _light; private readonly Material _darkMaterial; private readonly Material _accentMaterial; private readonly Material _fallbackMaterial; private readonly Font _font; private readonly bool _ownsFont; private readonly List<GameObject> _trimObjects = new List<GameObject>(); private Transform? _anchor; private TrophyModelSnapshot? _attachedSnapshot; private ChampionData? _champion; private float _anchorSearchTimer; private float _animationTime; private int _lastAnchorSceneHandle = int.MinValue; public TrophyController(ModConfig config, GameBindings bindings, ManualLogSource logger) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0180: 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_01c5: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0224: Unknown result type (might be due to invalid IL or missing references) //IL_025f: Unknown result type (might be due to invalid IL or missing references) //IL_0273: Unknown result type (might be due to invalid IL or missing references) //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0292: Unknown result type (might be due to invalid IL or missing references) //IL_029b: Expected O, but got Unknown //IL_02c7: Unknown result type (might be due to invalid IL or missing references) //IL_02ea: Unknown result type (might be due to invalid IL or missing references) //IL_02fe: Unknown result type (might be due to invalid IL or missing references) //IL_0318: Unknown result type (might be due to invalid IL or missing references) //IL_031d: Unknown result type (might be due to invalid IL or missing references) //IL_0326: Expected O, but got Unknown //IL_0352: Unknown result type (might be due to invalid IL or missing references) _config = config; _bindings = bindings; _logger = logger; _font = Font.CreateDynamicFontFromOSFont(new string[4] { "Bahnschrift SemiCondensed", "Arial Narrow", "Segoe UI Semibold", "Arial" }, 18); if ((Object)(object)_font != (Object)null) { _ownsFont = true; } else { _font = Resources.GetBuiltinResource<Font>("Arial.ttf"); } _root = new GameObject("HaulOfFame_WorldTrophy") { hideFlags = (HideFlags)61 }; Object.DontDestroyOnLoad((Object)(object)_root); _darkMaterial = CreateMaterial("HaulOfFame_Dark", new Color(0.018f, 0.024f, 0.028f, 1f), Color.black); _accentMaterial = CreateMaterial("HaulOfFame_Accent", new Color(0.1f, 0.34f, 0.15f, 1f), new Color(0.2f, 2f, 0.36f, 1f)); _fallbackMaterial = CreateMaterial("HaulOfFame_Fallback", new Color(0.12f, 0.85f, 0.28f, 0.82f), new Color(0.25f, 2.6f, 0.5f, 1f)); CreatePrimitive("PedestalBase", (PrimitiveType)2, _root.transform, new Vector3(0f, 0.08f, 0f), new Vector3(0.72f, 0.08f, 0.72f), _darkMaterial); CreatePrimitive("PedestalTop", (PrimitiveType)2, _root.transform, new Vector3(0f, 0.19f, 0f), new Vector3(0.55f, 0.045f, 0.55f), _darkMaterial); _trimObjects.Add(CreatePrimitive("GlowRingLow", (PrimitiveType)2, _root.transform, new Vector3(0f, 0.145f, 0f), new Vector3(0.64f, 0.012f, 0.64f), _accentMaterial)); _trimObjects.Add(CreatePrimitive("GlowRingTop", (PrimitiveType)2, _root.transform, new Vector3(0f, 0.245f, 0f), new Vector3(0.48f, 0.012f, 0.48f), _accentMaterial)); GameObject val = new GameObject("ModelMount") { hideFlags = (HideFlags)61 }; val.transform.SetParent(_root.transform, false); val.transform.localPosition = new Vector3(0f, 0.72f, 0f); _modelMount = val.transform; _fallbackModel = CreatePrimitive("FallbackHologram", (PrimitiveType)0, _modelMount, Vector3.zero, new Vector3(0.52f, 0.72f, 0.52f), _fallbackMaterial); GameObject val2 = new GameObject("HologramLight") { hideFlags = (HideFlags)61 }; val2.transform.SetParent(_root.transform, false); val2.transform.localPosition = new Vector3(0f, 0.7f, 0.1f); _light = val2.AddComponent<Light>(); _light.type = (LightType)2; _light.range = 3.2f; _light.intensity = 1.35f; (_plaqueCanvas, _plaquePanel, _plaqueAccent, _plaqueText) = CreatePlaque(_root.transform); ApplyConfig(); SetChampionVisualsActive(active: false); _root.SetActive(false); } public void ShowChampion(ChampionData champion, TrophyModelSnapshot? snapshot, string plaqueText) { DetachSnapshot(); _champion = champion; _attachedSnapshot = ((snapshot != null && snapshot.Valuable.ViewId == champion.Valuable.ViewId) ? snapshot : null); if (_attachedSnapshot != null) { _attachedSnapshot.AttachTo(_modelMount); } _fallbackModel.SetActive(_attachedSnapshot == null); _plaqueText.text = plaqueText; SetChampionVisualsActive(active: true); _anchorSearchTimer = 0f; _animationTime = 0f; if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Visual] Trophy prepared: view={champion.Valuable.ViewId}, name='{champion.Valuable.Name}', modelCopy={_attachedSnapshot != null}."); } } public void Tick(float unscaledDeltaTime) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_0247: Unknown result type (might be due to invalid IL or missing references) //IL_0252: Unknown result type (might be due to invalid IL or missing references) //IL_0276: Unknown result type (might be due to invalid IL or missing references) //IL_027b: Unknown result type (might be due to invalid IL or missing references) //IL_0286: Unknown result type (might be due to invalid IL or missing references) //IL_02aa: Unknown result type (might be due to invalid IL or missing references) //IL_02af: Unknown result type (might be due to invalid IL or missing references) //IL_02ba: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02e8: Unknown result type (might be due to invalid IL or missing references) //IL_02f0: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0323: Unknown result type (might be due to invalid IL or missing references) //IL_0328: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023a: Unknown result type (might be due to invalid IL or missing references) //IL_010c: 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_0156: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_0337: Unknown result type (might be due to invalid IL or missing references) //IL_0349: Unknown result type (might be due to invalid IL or missing references) //IL_036d: Unknown result type (might be due to invalid IL or missing references) //IL_03d4: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_048e: Unknown result type (might be due to invalid IL or missing references) //IL_0499: Unknown result type (might be due to invalid IL or missing references) //IL_049e: Unknown result type (might be due to invalid IL or missing references) //IL_04a3: Unknown result type (might be due to invalid IL or missing references) //IL_04bb: Unknown result type (might be due to invalid IL or missing references) //IL_04c0: Unknown result type (might be due to invalid IL or missing references) //IL_04c5: Unknown result type (might be due to invalid IL or missing references) bool flag = _champion != null; if (!_config.Enabled.Value || !_config.ShowWorldTrophy.Value || (!flag && !_config.ShowEmptyBase.Value)) { _root.SetActive(false); return; } GamePhase phase = _bindings.GetPhase(); if ((uint)phase <= 1u) { _root.SetActive(false); return; } if ((Object)(object)_anchor == (Object)null) { _anchorSearchTimer -= Mathf.Max(0f, unscaledDeltaTime); if (_anchorSearchTimer <= 0f) { _anchorSearchTimer = 0.75f; _anchor = _bindings.FindTruckAnchor(); if ((Object)(object)_anchor != (Object)null) { Scene scene = ((Component)_anchor).gameObject.scene; if (((Scene)(ref scene)).handle != _lastAnchorSceneHandle) { scene = ((Component)_anchor).gameObject.scene; _lastAnchorSceneHandle = ((Scene)(ref scene)).handle; ManualLogSource logger = _logger; string[] obj = new string[5] { "[HaulOfFame/Visual] Truck display anchor found: ", ((Object)_anchor).name, " in scene ", null, null }; scene = ((Component)_anchor).gameObject.scene; obj[3] = ((Scene)(ref scene)).name; obj[4] = "."; logger.LogInfo((object)string.Concat(obj)); } } } } if ((Object)(object)_anchor == (Object)null) { _root.SetActive(false); return; } try { Vector3 val = default(Vector3); Quaternion val2; if (_config.PositionMode.Value == TrophyPositionMode.FixedWorld) { ((Vector3)(ref val))..ctor(Mathf.Clamp(_config.WorldX.Value, -1000f, 1000f), Mathf.Clamp(_config.WorldY.Value, -1000f, 1000f), Mathf.Clamp(_config.WorldZ.Value, -1000f, 1000f)); val2 = Quaternion.Euler(0f, Mathf.Clamp(_config.RotationY.Value, -360f, 360f), 0f); } else { val = _anchor.position + _anchor.right * Mathf.Clamp(_config.OffsetX.Value, -5f, 5f) + _anchor.up * Mathf.Clamp(_config.OffsetY.Value, -5f, 5f) + _anchor.forward * Mathf.Clamp(_config.OffsetZ.Value, -5f, 5f); val2 = _anchor.rotation * Quaternion.Euler(0f, Mathf.Clamp(_config.RotationY.Value, -360f, 360f), 0f); } _root.transform.SetPositionAndRotation(val, val2); _root.transform.localScale = Vector3.one * Mathf.Clamp(_config.TrophyScale.Value, 0.25f, 3f); if (!_root.activeSelf) { _root.SetActive(true); } SetChampionVisualsActive(flag); } catch (MissingReferenceException) { _anchor = null; _root.SetActive(false); return; } if (!flag) { return; } _animationTime += Mathf.Max(0f, unscaledDeltaTime); _modelMount.Rotate(Vector3.up, Mathf.Clamp(_config.SpinSpeed.Value, -180f, 180f) * unscaledDeltaTime, (Space)1); float num = Mathf.Sin(_animationTime * Mathf.Clamp(_config.BobSpeed.Value, 0f, 10f) * MathF.PI * 2f) * Mathf.Clamp(_config.BobHeight.Value, 0f, 0.3f); _modelMount.localPosition = new Vector3(0f, 0.72f + num, 0f); Camera main = Camera.main; if ((Object)(object)main != (Object)null) { Vector3 val3 = ((Transform)_plaqueCanvas).position - ((Component)main).transform.position; if (((Vector3)(ref val3)).sqrMagnitude > 0.001f) { ((Transform)_plaqueCanvas).rotation = Quaternion.LookRotation(((Vector3)(ref val3)).normalized, Vector3.up); } } } public void HandleSceneChanged() { _anchor = null; _anchorSearchTimer = 0.25f; _root.SetActive(false); } public void ApplyConfig() { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) Color accentColor = _config.GetAccentColor(); ApplyMaterialColor(_accentMaterial, new Color(accentColor.r * 0.32f, accentColor.g * 0.32f, accentColor.b * 0.32f, 1f), accentColor * 2f); ApplyMaterialColor(_fallbackMaterial, new Color(accentColor.r, accentColor.g, accentColor.b, 0.86f), accentColor * 2.7f); _light.color = accentColor; ((Graphic)_plaqueAccent).color = accentColor; ((Graphic)_plaquePanel).color = new Color(0.006f, 0.012f, 0.016f, 0.93f); if (!_config.Enabled.Value || !_config.ShowWorldTrophy.Value) { _root.SetActive(false); } } public void Clear() { DetachSnapshot(); _champion = null; _plaqueText.text = string.Empty; SetChampionVisualsActive(active: false); _anchor = null; _root.SetActive(false); } private void SetChampionVisualsActive(bool active) { if (((Component)_modelMount).gameObject.activeSelf != active) { ((Component)_modelMount).gameObject.SetActive(active); } if (((Component)_plaqueCanvas).gameObject.activeSelf != active) { ((Component)_plaqueCanvas).gameObject.SetActive(active); } if (((Component)_light).gameObject.activeSelf != active) { ((Component)_light).gameObject.SetActive(active); } } private void DetachSnapshot() { if (_attachedSnapshot == null || (Object)(object)_attachedSnapshot.Root == (Object)null) { _attachedSnapshot = null; return; } _attachedSnapshot.Root.transform.SetParent((Transform)null, false); _attachedSnapshot.Hide(); _attachedSnapshot = null; } private (RectTransform canvas, Image panel, Image accent, Text text) CreatePlaque(Transform parent) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Expected O, but got Unknown //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_016a: Unknown result type (might be due to invalid IL or missing references) //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_018d: Unknown result type (might be due to invalid IL or missing references) //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01b7: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_01e0: Unknown result type (might be due to invalid IL or missing references) //IL_022b: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0242: Unknown result type (might be due to invalid IL or missing references) //IL_0249: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_0269: Unknown result type (might be due to invalid IL or missing references) //IL_027d: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject("PlaqueCanvas", new Type[2] { typeof(RectTransform), typeof(Canvas) }); ((Object)val).hideFlags = (HideFlags)61; val.transform.SetParent(parent, false); RectTransform component = val.GetComponent<RectTransform>(); ((Transform)component).localPosition = new Vector3(0f, 1.58f, 0f); ((Transform)component).localRotation = Quaternion.identity; ((Transform)component).localScale = Vector3.one * 0.00145f; component.sizeDelta = new Vector2(620f, 180f); Canvas component2 = val.GetComponent<Canvas>(); component2.renderMode = (RenderMode)2; component2.sortingOrder = 100; GameObject val2 = new GameObject("Panel", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val2.transform.SetParent(val.transform, false); RectTransform component3 = val2.GetComponent<RectTransform>(); component3.anchorMin = Vector2.zero; component3.anchorMax = Vector2.one; component3.offsetMin = Vector2.zero; component3.offsetMax = Vector2.zero; Image component4 = val2.GetComponent<Image>(); ((Graphic)component4).raycastTarget = false; GameObject val3 = new GameObject("Accent", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Image) }); val3.transform.SetParent(val2.transform, false); RectTransform component5 = val3.GetComponent<RectTransform>(); component5.anchorMin = new Vector2(0f, 0f); component5.anchorMax = new Vector2(0f, 1f); component5.pivot = new Vector2(0f, 0.5f); component5.anchoredPosition = new Vector2(8f, 0f); component5.sizeDelta = new Vector2(7f, -18f); Image component6 = val3.GetComponent<Image>(); ((Graphic)component6).raycastTarget = false; GameObject val4 = new GameObject("Text", new Type[3] { typeof(RectTransform), typeof(CanvasRenderer), typeof(Text) }); val4.transform.SetParent(val2.transform, false); RectTransform component7 = val4.GetComponent<RectTransform>(); component7.anchorMin = Vector2.zero; component7.anchorMax = Vector2.one; component7.offsetMin = new Vector2(30f, 14f); component7.offsetMax = new Vector2(-18f, -12f); Text component8 = val4.GetComponent<Text>(); component8.font = _font; component8.fontSize = 24; component8.fontStyle = (FontStyle)1; component8.alignment = (TextAnchor)3; ((Graphic)component8).color = new Color(0.94f, 1f, 0.96f, 1f); component8.supportRichText = true; component8.horizontalOverflow = (HorizontalWrapMode)0; component8.verticalOverflow = (VerticalWrapMode)0; ((Graphic)component8).raycastTarget = false; return (canvas: component, panel: component4, accent: component6, text: component8); } private static GameObject CreatePrimitive(string name, PrimitiveType primitive, Transform parent, Vector3 localPosition, Vector3 localScale, Material material) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) GameObject obj = GameObject.CreatePrimitive(primitive); ((Object)obj).name = name; ((Object)obj).hideFlags = (HideFlags)61; obj.transform.SetParent(parent, false); obj.transform.localPosition = localPosition; obj.transform.localRotation = Quaternion.identity; obj.transform.localScale = localScale; Collider component = obj.GetComponent<Collider>(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } Renderer component2 = obj.GetComponent<Renderer>(); if ((Object)(object)component2 != (Object)null) { component2.sharedMaterial = material; } return obj; } private static Material CreateMaterial(string name, Color color, Color emission) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Expected O, but got Unknown //IL_007a: Expected O, but got Unknown Shader obj = Shader.Find("Standard") ?? Shader.Find("Universal Render Pipeline/Lit") ?? Shader.Find("Diffuse") ?? Shader.Find("Sprites/Default") ?? Shader.Find("UI/Default"); if ((Object)(object)obj == (Object)null) { throw new InvalidOperationException("No compatible built-in shader was found for the trophy display."); } Material val = new Material(obj) { name = name, color = color, hideFlags = (HideFlags)61 }; ApplyMaterialColor(val, color, emission); return val; } private static void ApplyMaterialColor(Material material, Color color, Color emission) { //IL_0001: 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) material.color = color; if (material.HasProperty("_EmissionColor")) { material.EnableKeyword("_EMISSION"); material.SetColor("_EmissionColor", emission); } } public void Dispose() { DetachSnapshot(); if ((Object)(object)_root != (Object)null) { Object.Destroy((Object)(object)_root); } Object.Destroy((Object)(object)_darkMaterial); Object.Destroy((Object)(object)_accentMaterial); Object.Destroy((Object)(object)_fallbackMaterial); if (_ownsFont && (Object)(object)_font != (Object)null) { Object.Destroy((Object)(object)_font); } _trimObjects.Clear(); } } public sealed class TrophyModelSnapshot : IDisposable { private readonly List<Mesh> _ownedMeshes = new List<Mesh>(); private bool _disposed; public CapturedValuable Valuable { get; } public GameObject Root { get; } private TrophyModelSnapshot(CapturedValuable valuable, GameObject root, List<Mesh> ownedMeshes) { Valuable = valuable; Root = root; _ownedMeshes.AddRange(ownedMeshes); } public static bool TryCreate(CapturedValuable valuable, PhysGrabObject source, ManualLogSource logger, out TrophyModelSnapshot snapshot) { //IL_01e8: Unknown result type (might be due to invalid IL or missing references) //IL_01ed: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Expected O, but got Unknown //IL_01fd: Unknown result type (might be due to invalid IL or missing references) //IL_0230: Unknown result type (might be due to invalid IL or missing references) //IL_0235: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Expected O, but got Unknown //IL_0248: Unknown result type (might be due to invalid IL or missing references) //IL_0295: Unknown result type (might be due to invalid IL or missing references) //IL_02a6: Unknown result type (might be due to invalid IL or missing references) //IL_02b2: Unknown result type (might be due to invalid IL or missing references) //IL_02be: Unknown result type (might be due to invalid IL or missing references) //IL_02ca: Unknown result type (might be due to invalid IL or missing references) //IL_02e7: Unknown result type (might be due to invalid IL or missing references) //IL_0304: Unknown result type (might be due to invalid IL or missing references) snapshot = null; if ((Object)(object)source == (Object)null) { return false; } List<GameObject> list = new List<GameObject>(); List<Renderer> list2 = new List<Renderer>(); List<Mesh> list3 = new List<Mesh>(); try { MeshFilter[] componentsInChildren = ((Component)source).GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.sharedMesh == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>(); if (!((Object)(object)component == (Object)null) && ((Renderer)component).enabled) { GameObject val2 = CreateMeshObject(((Component)val).transform, val.sharedMesh, ((Renderer)component).sharedMaterials); list.Add(val2); list2.Add((Renderer)(object)val2.GetComponent<MeshRenderer>()); } } } SkinnedMeshRenderer[] componentsInChildren2 = ((Component)source).GetComponentsInChildren<SkinnedMeshRenderer>(true); foreach (SkinnedMeshRenderer val3 in componentsInChildren2) { if (!((Object)(object)val3 == (Object)null) && ((Renderer)val3).enabled && ((Component)val3).gameObject.activeInHierarchy) { Mesh val4 = new Mesh { name = "HaulOfFame_BakedMesh", hideFlags = (HideFlags)61 }; val3.BakeMesh(val4); if (val4.vertexCount == 0) { Object.Destroy((Object)(object)val4); continue; } list3.Add(val4); GameObject val5 = CreateMeshObject(((Component)val3).transform, val4, ((Renderer)val3).sharedMaterials); list.Add(val5); list2.Add((Renderer)(object)val5.GetComponent<MeshRenderer>()); } } if (list2.Count == 0) { foreach (GameObject item in list) { Object.Destroy((Object)(object)item); } foreach (Mesh item2 in list3) { Object.Destroy((Object)(object)item2); } return false; } Bounds bounds = list2[0].bounds; for (int j = 1; j < list2.Count; j++) { ((Bounds)(ref bounds)).Encapsulate(list2[j].bounds); } GameObject val6 = new GameObject("HaulOfFame_Model_" + valuable.ViewId) { hideFlags = (HideFlags)61 }; val6.transform.position = ((Bounds)(ref bounds)).center; foreach (GameObject item3 in list) { item3.transform.SetParent(val6.transform, true); } val6.transform.position = Vector3.zero; val6.transform.rotation = Quaternion.identity; float num = Mathf.Max(((Bounds)(ref bounds)).size.x, Mathf.Max(((Bounds)(ref bounds)).size.y, ((Bounds)(ref bounds)).size.z)); val6.transform.localScale = Vector3.one * ((num > 0.001f) ? (1f / num) : 1f); Object.DontDestroyOnLoad((Object)(object)val6); val6.SetActive(false); snapshot = new TrophyModelSnapshot(valuable, val6, list3); return true; } catch (Exception ex) { foreach (GameObject item4 in list) { if ((Object)(object)item4 != (Object)null) { Object.Destroy((Object)(object)item4); } } foreach (Mesh item5 in list3) { if ((Object)(object)item5 != (Object)null) { Object.Destroy((Object)(object)item5); } } logger.LogWarning((object)("[HaulOfFame/Visual] Model snapshot failed for '" + valuable.Name + "': " + ex.GetType().Name + ": " + ex.Message)); return false; } } public void AttachTo(Transform parent) { //IL_0034: 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) if (!_disposed && !((Object)(object)Root == (Object)null)) { Root.transform.SetParent(parent, false); Root.transform.localPosition = Vector3.zero; Root.transform.localRotation = Quaternion.identity; Root.SetActive(true); } } public void Hide() { if (!_disposed && (Object)(object)Root != (Object)null) { Root.SetActive(false); } } private static GameObject CreateMeshObject(Transform sourceTransform, Mesh mesh, Material[] materials) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Expected O, but got Unknown GameObject val = new GameObject("HaulOfFame_RenderPart") { hideFlags = (HideFlags)61 }; val.transform.position = sourceTransform.position; val.transform.rotation = sourceTransform.rotation; val.transform.localScale = sourceTransform.lossyScale; val.AddComponent<MeshFilter>().sharedMesh = mesh; MeshRenderer obj = val.AddComponent<MeshRenderer>(); ((Renderer)obj).sharedMaterials = materials; ((Renderer)obj).shadowCastingMode = (ShadowCastingMode)1; ((Renderer)obj).receiveShadows = true; ((Renderer)obj).lightProbeUsage = (LightProbeUsage)1; return val; } public void Dispose() { if (_disposed) { return; } _disposed = true; if ((Object)(object)Root != (Object)null) { Object.Destroy((Object)(object)Root); } foreach (Mesh ownedMesh in _ownedMeshes) { if ((Object)(object)ownedMesh != (Object)null) { Object.Destroy((Object)(object)ownedMesh); } } _ownedMeshes.Clear(); } } } namespace HaulOfFame.Network { public sealed class HaulNetwork : IDisposable { private enum MessageType : byte { Hello, PrepareValuable, Contribution, Champion } private const byte EventCode = 182; private const string Signature = "com.juanma.hauloffame"; private const byte ProtocolVersion = 1; private const float MinimumContributionInterval = 0.02f; private readonly ModConfig _config; private readonly ManualLogSource _logger; private readonly HashSet<int> _moddedActors = new HashSet<int>(); private readonly Dictionary<long, float> _lastContributionTime = new Dictionary<long, float>(); private LoadBalancingClient? _subscribedClient; private Room? _trackedRoom; public event Action<int, int>? PrepareReceived; public event Action<int, int, float>? ContributionReceived; public event Action<ChampionData>? ChampionReceived; public HaulNetwork(ModConfig config, ManualLogSource logger) { _config = config; _logger = logger; RefreshSubscription(); } public void Tick() { RefreshSubscription(); Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == _trackedRoom) { return; } _trackedRoom = currentRoom; _moddedActors.Clear(); _lastContributionTime.Clear(); if (currentRoom != null && PhotonNetwork.LocalPlayer != null) { _moddedActors.Add(PhotonNetwork.LocalPlayer.ActorNumber); SendHello(); if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Network] Entered room '{currentRoom.Name}' as actor {PhotonNetwork.LocalPlayer.ActorNumber}; presence announced."); } } } public void BroadcastPrepare(int viewId, int extractionPointViewId) { if (CanSend() && viewId > 0) { object[] payload = new object[6] { "com.juanma.hauloffame", (byte)1, (byte)1, viewId, Mathf.Max(0, extractionPointViewId), PhotonNetwork.ServerTimestamp }; Raise(payload, (ReceiverGroup)0); } } public void SendContribution(int viewId, float score) { if (CanSend() && viewId > 0 && IsFinite(score)) { object[] payload = new object[6] { "com.juanma.hauloffame", (byte)1, (byte)2, viewId, Mathf.Clamp(score, 0f, 1000f), PhotonNetwork.ServerTimestamp }; Raise(payload, (ReceiverGroup)2); } } public void BroadcastChampion(ChampionData champion) { if (CanSend()) { object[] payload = new object[11] { "com.juanma.hauloffame", (byte)1, (byte)3, champion.Valuable.ViewId, CapturedValuable.SanitizeName(champion.Valuable.Name), champion.Valuable.CurrentValue, champion.Valuable.OriginalValue, champion.ContributorActors, champion.ContributorScores, champion.AttributionComplete, PhotonNetwork.ServerTimestamp }; Raise(payload, (ReceiverGroup)0); } } public bool AllPlayersHaveMod() { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom == null) { return true; } foreach (int key in currentRoom.Players.Keys) { if (!_moddedActors.Contains(key)) { return false; } } return true; } private void SendHello() { if (CanSend()) { object[] payload = new object[4] { "com.juanma.hauloffame", (byte)1, (byte)0, PhotonNetwork.ServerTimestamp }; Raise(payload, (ReceiverGroup)0); } } private bool Raise(object[] payload, ReceiverGroup receivers) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Expected O, but got Unknown //IL_001b: Unknown result type (might be due to invalid IL or missing references) RaiseEventOptions val = new RaiseEventOptions { Receivers = receivers, CachingOption = (EventCaching)0 }; bool flag = PhotonNetwork.RaiseEvent((byte)182, (object)payload, val, SendOptions.SendReliable); if (_config.DebugLogging.Value && !flag) { _logger.LogWarning((object)$"[HaulOfFame/Network] Photon rejected outgoing message type {payload[2]}."); } return flag; } private void RefreshSubscription() { LoadBalancingClient networkingClient = PhotonNetwork.NetworkingClient; if (networkingClient != _subscribedClient) { if (_subscribedClient != null) { _subscribedClient.EventReceived -= OnEventReceived; } _subscribedClient = networkingClient; if (_subscribedClient != null) { _subscribedClient.EventReceived += OnEventReceived; _logger.LogInfo((object)"[HaulOfFame/Network] Photon custom-event listener attached."); } } } private void OnEventReceived(EventData eventData) { if (eventData.Code != 182 || !(eventData.CustomData is object[] array) || array.Length < 4 || !(array[0] is string text) || text != "com.juanma.hauloffame" || !(array[1] is byte b) || b != 1 || !(array[2] is byte b2) || !Enum.IsDefined(typeof(MessageType), b2)) { return; } int sender = eventData.Sender; if (sender <= 0) { return; } switch ((MessageType)b2) { case MessageType.Hello: _moddedActors.Add(sender); if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Network] Actor {sender} reported compatible protocol {b}."); } break; case MessageType.PrepareValuable: ReceivePrepare(sender, array); break; case MessageType.Contribution: ReceiveContribution(sender, array); break; case MessageType.Champion: ReceiveChampion(sender, array); break; } } private void ReceivePrepare(int sender, object[] payload) { if (payload.Length == 6 && payload[3] is int num && payload[4] is int num2 && payload[5] is int timestamp && num > 0 && IsMasterActor(sender) && Fresh(timestamp, 15000)) { if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Network] Host prepared extracted valuable view={num}."); } this.PrepareReceived?.Invoke(num, Mathf.Max(0, num2)); } } private void ReceiveContribution(int sender, object[] payload) { if (payload.Length == 6 && payload[3] is int num && payload[4] is float num2 && payload[5] is int timestamp && PhotonNetwork.IsMasterClient && num > 0 && IsFinite(num2) && !(num2 < 0f) && !(num2 > 1000f) && Fresh(timestamp, 20000)) { float realtimeSinceStartup = Time.realtimeSinceStartup; long key = ((long)sender << 32) | (uint)num; if (!_lastContributionTime.TryGetValue(key, out var value) || !(realtimeSinceStartup - value < 0.02f)) { _lastContributionTime[key] = realtimeSinceStartup; this.ContributionReceived?.Invoke(sender, num, num2); } } } private void ReceiveChampion(int sender, object[] payload) { if (payload.Length != 11 || !IsMasterActor(sender) || !(payload[3] is int num) || !(payload[4] is string name) || !(payload[5] is int num2) || !(payload[6] is int num3) || !(payload[7] is int[] array) || !(payload[8] is float[] array2) || !(payload[9] is bool attributionComplete) || !(payload[10] is int timestamp) || num <= 0 || num2 < 0 || num3 < num2 || array.Length != array2.Length || array.Length > 32 || !Fresh(timestamp, 30000)) { return; } float[] array3 = array2; foreach (float num4 in array3) { if (!IsFinite(num4) || num4 < 0f || num4 > 1000f) { return; } } ChampionData obj = new ChampionData(new CapturedValuable(num, name, num2, num3), array, array2, attributionComplete); this.ChampionReceived?.Invoke(obj); } private static bool CanSend() { if (PhotonNetwork.InRoom) { return PhotonNetwork.IsConnectedAndReady; } return false; } private static bool IsMasterActor(int actorNumber) { Player masterClient = PhotonNetwork.MasterClient; if (masterClient != null) { return masterClient.ActorNumber == actorNumber; } return false; } private static bool Fresh(int timestamp, int maximumAgeMilliseconds) { int num = PhotonNetwork.ServerTimestamp - timestamp; if (num >= -2000) { return num <= maximumAgeMilliseconds; } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } public void Dispose() { if (_subscribedClient != null) { _subscribedClient.EventReceived -= OnEventReceived; } _subscribedClient = null; _trackedRoom = null; _moddedActors.Clear(); _lastContributionTime.Clear(); this.PrepareReceived = null; this.ContributionReceived = null; this.ChampionReceived = null; } } } namespace HaulOfFame.Core { public sealed class CapturedValuable { public int ViewId { get; } public string Name { get; } public int CurrentValue { get; } public int OriginalValue { get; } public float RetainedPercent { get { if (OriginalValue > 0) { return Mathf.Clamp((float)CurrentValue * 100f / (float)OriginalValue, 0f, 999f); } return 100f; } } public CapturedValuable(int viewId, string name, int currentValue, int originalValue) { ViewId = viewId; Name = SanitizeName(name); CurrentValue = Mathf.Max(0, currentValue); OriginalValue = Mathf.Max(CurrentValue, originalValue); } public bool Beats(CapturedValuable? other) { if (other == null) { return true; } if (CurrentValue != other.CurrentValue) { return CurrentValue > other.CurrentValue; } int num = RetainedPercent.CompareTo(other.RetainedPercent); if (num != 0) { return num > 0; } return ViewId < other.ViewId; } public static string SanitizeName(string? value) { if (string.IsNullOrWhiteSpace(value)) { return "VALUABLE"; } List<char> list = new List<char>(Mathf.Min(value.Length, 64)); string text = value.Trim(); foreach (char c in text) { if (list.Count >= 64) { break; } if (!char.IsControl(c) && c != '<' && c != '>') { list.Add(c); } } if (list.Count != 0) { return new string(list.ToArray()); } return "VALUABLE"; } } public sealed class ChampionData { public CapturedValuable Valuable { get; } public int[] ContributorActors { get; } public float[] ContributorScores { get; } public bool AttributionComplete { get; } public ChampionData(CapturedValuable valuable, int[]? contributorActors, float[]? contributorScores, bool attributionComplete) { Valuable = valuable; ContributorActors = contributorActors ?? Array.Empty<int>(); ContributorScores = contributorScores ?? Array.Empty<float>(); AttributionComplete = attributionComplete; } } public enum GamePhase { Unavailable, MainMenu, Mission, Shop, Lobby, Other } public sealed class GameBindings { private readonly ManualLogSource _logger; private FieldInfo? _valuableCurrentField; private FieldInfo? _valuableOriginalField; private FieldInfo? _valuableValueSetField; private FieldInfo? _runStartedField; private FieldInfo? _extractionPointsField; private FieldInfo? _extractionPointsCompletedField; private FieldInfo? _extractionPointCurrentField; private bool _readErrorLogged; public GameBindings(ManualLogSource logger) { _logger = logger; } public bool Resolve() { _valuableCurrentField = ResolveField(typeof(ValuableObject), "dollarValueCurrent", typeof(float)); _valuableOriginalField = ResolveField(typeof(ValuableObject), "dollarValueOriginal", typeof(float)); _valuableValueSetField = ResolveField(typeof(ValuableObject), "dollarValueSet", typeof(bool)); _runStartedField = ResolveField(typeof(RunManager), "runStarted", typeof(bool)); _extractionPointsField = ResolveField(typeof(RoundDirector), "extractionPoints", typeof(int)); _extractionPointsCompletedField = ResolveField(typeof(RoundDirector), "extractionPointsCompleted", typeof(int)); _extractionPointCurrentField = ResolveField(typeof(RoundDirector), "extractionPointCurrent", typeof(ExtractionPoint)); if (_valuableCurrentField != null && _valuableOriginalField != null && _runStartedField != null && _extractionPointsField != null) { return _extractionPointsCompletedField != null; } return false; } public bool TryCapture(ExtractionPoint extractionPoint, PhysGrabObject physObject, out CapturedValuable captured, out float localHaulScore, out string failure) { localHaulScore = 0f; if ((Object)(object)extractionPoint == (Object)null || (Object)(object)physObject == (Object)null) { captured = null; failure = "missing extraction point or physics object"; return false; } if (!TryCaptureMetadata(physObject, out captured, out ValuableObject valuable, out failure)) { return false; } try { localHaulScore = valuable.GetLocalPlayerHaulScore(((Component)extractionPoint).gameObject); if (!IsFinite(localHaulScore) || localHaulScore < 0f) { localHaulScore = 0f; } } catch (Exception ex) { localHaulScore = 0f; if (!_readErrorLogged) { _readErrorLogged = true; _logger.LogWarning((object)("[HaulOfFame/Bindings] Could not read vanilla haul score: " + ex.GetType().Name + ": " + ex.Message)); } } return true; } public bool TryCaptureStored(PhysGrabObject physObject, out CapturedValuable captured, out float localHaulScore, out string failure) { localHaulScore = 0f; if ((Object)(object)physObject == (Object)null) { captured = null; failure = "missing stored physics object"; return false; } if (!TryCaptureMetadata(physObject, out captured, out ValuableObject valuable, out failure)) { return false; } try { ExtractionPoint[] array = Object.FindObjectsOfType<ExtractionPoint>(); foreach (ExtractionPoint val in array) { if (!((Object)(object)val == (Object)null)) { float localPlayerHaulScore = valuable.GetLocalPlayerHaulScore(((Component)val).gameObject); if (IsFinite(localPlayerHaulScore) && localPlayerHaulScore > localHaulScore) { localHaulScore = localPlayerHaulScore; } } } } catch (Exception ex) { localHaulScore = 0f; if (!_readErrorLogged) { _readErrorLogged = true; _logger.LogWarning((object)("[HaulOfFame/Bindings] Could not read stored valuable haul score: " + ex.GetType().Name + ": " + ex.Message)); } } return true; } private bool TryCaptureMetadata(PhysGrabObject physObject, out CapturedValuable captured, out ValuableObject valuable, out string failure) { captured = null; valuable = null; failure = string.Empty; valuable = ((Component)physObject).GetComponent<ValuableObject>() ?? ((Component)physObject).GetComponentInChildren<ValuableObject>(); if ((Object)(object)valuable == (Object)null) { failure = "object is not a ValuableObject"; return false; } if (_valuableValueSetField != null && TryRead<bool>(_valuableValueSetField, valuable, out var value) && !value) { failure = "valuable value has not been initialized"; return false; } if (!TryRead<float>(_valuableCurrentField, valuable, out var value2) || !IsFinite(value2) || value2 < 0f) { failure = "invalid current value"; return false; } float num = value2; if (TryRead<float>(_valuableOriginalField, valuable, out var value3) && IsFinite(value3) && value3 > 0f) { num = Mathf.Max(value2, value3); } PhotonView val = ((Component)physObject).GetComponent<PhotonView>() ?? ((Component)physObject).GetComponentInParent<PhotonView>() ?? ((Component)valuable).GetComponent<PhotonView>(); int viewId = (((Object)(object)val != (Object)null && val.ViewID > 0) ? val.ViewID : Mathf.Abs(((Object)physObject).GetInstanceID())); captured = new CapturedValuable(viewId, CleanObjectName(((Object)((Component)valuable).gameObject).name, "VALUABLE"), Mathf.RoundToInt(value2), Mathf.RoundToInt(num)); return true; } public bool IsLastExtractionCompleted(RoundDirector? director, out int completed, out int total) { completed = 0; total = 0; if ((Object)(object)director == (Object)null || !TryRead<int>(_extractionPointsCompletedField, director, out completed) || !TryRead<int>(_extractionPointsField, director, out total)) { return false; } if (total > 0) { return completed >= total; } return false; } public GamePhase GetPhase() { try { if (SemiFunc.IsMainMenu()) { return GamePhase.MainMenu; } RunManager instance = RunManager.instance; if ((Object)(object)instance == (Object)null || !TryRead<bool>(_runStartedField, instance, out var value) || !value) { return GamePhase.Unavailable; } if (SemiFunc.RunIsLevel()) { return GamePhase.Mission; } if (SemiFunc.RunIsShop()) { return GamePhase.Shop; } if (SemiFunc.RunIsLobby()) { return GamePhase.Lobby; } return GamePhase.Other; } catch { return GamePhase.Unavailable; } } public Transform? FindTruckAnchor() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) try { TruckScreenText val = Object.FindObjectOfType<TruckScreenText>(); Scene scene; if ((Object)(object)val != (Object)null) { scene = ((Component)val).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return ((Component)val).transform; } } TruckScreenOpen val2 = Object.FindObjectOfType<TruckScreenOpen>(); if ((Object)(object)val2 != (Object)null) { scene = ((Component)val2).gameObject.scene; if (((Scene)(ref scene)).IsValid()) { return ((Component)val2).transform; } } } catch { } return null; } public ExtractionPoint? FindActiveExtractionPoint(int preferredViewId = 0) { if (preferredViewId > 0) { try { PhotonView val = PhotonView.Find(preferredViewId); ExtractionPoint val2 = (((Object)(object)val != (Object)null) ? (((Component)val).GetComponent<ExtractionPoint>() ?? ((Component)val).GetComponentInParent<ExtractionPoint>()) : null); if ((Object)(object)val2 != (Object)null) { return val2; } } catch { } } try { RoundDirector instance = RoundDirector.instance; if ((Object)(object)instance != (Object)null && TryRead<ExtractionPoint>(_extractionPointCurrentField, instance, out var value) && (Object)(object)value != (Object)null) { return value; } } catch { } try { ExtractionPoint[] array = Object.FindObjectsOfType<ExtractionPoint>(); foreach (ExtractionPoint val3 in array) { if ((Object)(object)val3 != (Object)null && !val3.isLocked) { return val3; } } } catch { } return null; } public string GetActorName(int actorNumber) { if (actorNumber > 0) { try { Room currentRoom = PhotonNetwork.CurrentRoom; if (currentRoom != null && currentRoom.Players.TryGetValue(actorNumber, out var value) && !string.IsNullOrWhiteSpace(value.NickName)) { return CapturedValuable.SanitizeName(value.NickName); } } catch { } } try { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); string value2 = (((Object)(object)val != (Object)null) ? SemiFunc.PlayerGetName(val) : null); if (!string.IsNullOrWhiteSpace(value2)) { return CapturedValuable.SanitizeName(value2); } } catch { } return "PLAYER"; } public static string CleanObjectName(string? rawName, string fallback) { if (string.IsNullOrWhiteSpace(rawName)) { return fallback; } string text = rawName.Replace("(Clone)", string.Empty).Trim(); string[] array = new string[5] { "Valuable ", "Valuable_", "Valuable-", "Prefab ", "Object " }; foreach (string text2 in array) { if (text.StartsWith(text2, StringComparison.OrdinalIgnoreCase)) { text = text.Substring(text2.Length); break; } } text = text.Replace('_', ' ').Replace('-', ' '); StringBuilder stringBuilder = new StringBuilder(text.Length + 8); for (int j = 0; j < text.Length; j++) { char c = text[j]; if (j > 0 && char.IsUpper(c) && char.IsLower(text[j - 1])) { stringBuilder.Append(' '); } stringBuilder.Append(c); } string value = stringBuilder.ToString().Trim(); if (!string.IsNullOrWhiteSpace(value)) { return CapturedValuable.SanitizeName(value); } return fallback; } private FieldInfo? ResolveField(Type type, string name, Type expectedType) { FieldInfo fieldInfo = AccessTools.Field(type, name); if (fieldInfo == null || fieldInfo.FieldType != expectedType) { _logger.LogWarning((object)("[HaulOfFame/Bindings] Missing field " + type.Name + "." + name + " (" + expectedType.Name + ").")); return null; } return fieldInfo; } private bool TryRead<T>(FieldInfo? field, object target, out T value) { value = default(T); if (field == null || target == null) { return false; } try { if (field.GetValue(target) is T val) { value = val; return true; } } catch (Exception ex) { if (!_readErrorLogged) { _readErrorLogged = true; _logger.LogWarning((object)("[HaulOfFame/Bindings] Reflection read failed: " + ex.GetType().Name + ": " + ex.Message)); } } return false; } private static bool IsFinite(float value) { if (!float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } public sealed class HaulController : IDisposable { private const float FinalizationDelay = 1.35f; private readonly ModConfig _config; private readonly GameBindings _bindings; private readonly ManualLogSource _logger; private readonly HaulNetwork _network; private readonly AnnouncementHud _announcement; private readonly TrophyController _trophy; private readonly Dictionary<int, CapturedValuable> _candidates = new Dictionary<int, CapturedValuable>(); private readonly Dictionary<int, Dictionary<int, float>> _contributions = new Dictionary<int, Dictionary<int, float>>(); private readonly Dictionary<int, Dictionary<int, CapturedValuable>> _storedCandidatesByBox = new Dictionary<int, Dictionary<int, CapturedValuable>>(); private readonly Dictionary<int, TrophyModelSnapshot> _storedBestSnapshotsByBox = new Dictionary<int, TrophyModelSnapshot>(); private readonly HashSet<int> _capturedViewIds = new HashSet<int>(); private readonly HashSet<int> _storedViewIds = new HashSet<int>(); private TrophyModelSnapshot? _bestSnapshot; private ChampionData? _champion; private GamePhase _phase; private float _finalizationTime = -1f; private int _missionSceneHandle = int.MinValue; private int _lastTickFrame = -1; private bool _disposed; public HaulController(ModConfig config, GameBindings bindings, ManualLogSource logger) { _config = config; _bindings = bindings; _logger = logger; _network = new HaulNetwork(config, logger); _announcement = new AnnouncementHud(config); _trophy = new TrophyController(config, bindings, logger); _network.PrepareReceived += OnPrepareReceived; _network.ContributionReceived += OnContributionReceived; _network.ChampionReceived += OnChampionReceived; _config.Changed += OnConfigChanged; } public void Tick(float unscaledDeltaTime) { //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) if (_disposed || _lastTickFrame == Time.frameCount) { return; } _lastTickFrame = Time.frameCount; _config.PollForExternalChanges(unscaledDeltaTime); _network.Tick(); _announcement.Tick(unscaledDeltaTime); _trophy.Tick(unscaledDeltaTime); GamePhase phase = _bindings.GetPhase(); Scene activeScene = SceneManager.GetActiveScene(); if (phase != _phase) { if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Lifecycle] Phase changed: {_phase} -> {phase}, scene={((Scene)(ref activeScene)).name}[{((Scene)(ref activeScene)).buildIndex}]."); } _phase = phase; } switch (phase) { case GamePhase.MainMenu: if (_missionSceneHandle != int.MinValue || _champion != null || _candidates.Count > 0) { ResetAll("returned to main menu"); } return; case GamePhase.Mission: if (((Scene)(ref activeScene)).handle != _missionSceneHandle) { BeginMission(activeScene); } break; } if (_finalizationTime > 0f && Time.realtimeSinceStartup >= _finalizationTime && IsAuthority()) { _finalizationTime = -1f; FinalizeChampion(); } } public void OnValuableExtracting(ExtractionPoint extractionPoint, PhysGrabObject physObject) { if (!_disposed && _config.Enabled.Value && !((Object)(object)extractionPoint == (Object)null) && !((Object)(object)physObject == (Object)null) && _bindings.GetPhase() == GamePhase.Mission && IsAuthority()) { PhotonView val = ((Component)physObject).GetComponent<PhotonView>() ?? ((Component)physObject).GetComponentInParent<PhotonView>(); int num = (((Object)(object)val != (Object)null) ? val.ViewID : 0); PhotonView val2 = ((Component)extractionPoint).GetComponent<PhotonView>() ?? ((Component)extractionPoint).GetComponentInParent<PhotonView>(); int extractionPointViewId = (((Object)(object)val2 != (Object)null) ? val2.ViewID : 0); CaptureLocal(extractionPoint, physObject, "host extraction hook"); if (PhotonNetwork.InRoom && num > 0) { _network.BroadcastPrepare(num, extractionPointViewId); } } } public void OnExtractionCompleted(RoundDirector director) { if (_disposed || !_config.Enabled.Value || !IsAuthority()) { return; } int completed; int total; bool flag = _bindings.IsLastExtractionCompleted(director, out completed, out total); _logger.LogInfo((object)$"[HaulOfFame/Extraction] Extraction completed: {completed}/{total}, captured={_candidates.Count}, final={flag}."); if (flag) { _finalizationTime = Time.realtimeSinceStartup + 1.35f; if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Extraction] Final result scheduled in {1.35f:0.00}s to receive remaining contribution reports."); } } } public void OnValuableStored(ItemValuableBox box, PhysGrabObject physObject) { if (_disposed || !_config.Enabled.Value || (Object)(object)box == (Object)null || (Object)(object)physObject == (Object)null || _bindings.GetPhase() != GamePhase.Mission) { return; } if (!_bindings.TryCaptureStored(physObject, out CapturedValuable captured, out float localHaulScore, out string failure)) { if (_config.DebugLogging.Value) { _logger.LogWarning((object)("[HaulOfFame/Hauler] Ignored absorbed target: " + failure + ".")); } } else if (_storedViewIds.Add(captured.ViewId)) { PhotonView val = ((Component)box).GetComponent<PhotonView>() ?? ((Component)box).GetComponentInParent<PhotonView>(); int num = (((Object)(object)val != (Object)null && val.ViewID > 0) ? val.ViewID : Mathf.Abs(((Object)box).GetInstanceID())); if (!_storedCandidatesByBox.TryGetValue(num, out Dictionary<int, CapturedValuable> value)) { value = new Dictionary<int, CapturedValuable>(); _storedCandidatesByBox[num] = value; } value[captured.ViewId] = captured; if ((!_storedBestSnapshotsByBox.TryGetValue(num, out TrophyModelSnapshot value2) || captured.Beats(value2.Valuable)) && TrophyModelSnapshot.TryCreate(captured, physObject, _logger, out TrophyModelSnapshot snapshot)) { value2?.Dispose(); _storedBestSnapshotsByBox[num] = snapshot; } int actorNumber = ((PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0); RecordContribution(actorNumber, captured.ViewId, localHaulScore); if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { _network.SendContribution(captured.ViewId, localHaulScore); } if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Hauler] Stored '{captured.Name}', view={captured.ViewId}, box={num}, value=${captured.CurrentValue:N0}, localScore={localHaulScore:0.###}."); } } } public void OnValuableBoxExtracted(ItemValuableBox box) { if (_disposed || !_config.Enabled.Value || (Object)(object)box == (Object)null || !IsAuthority()) { return; } PhotonView val = ((Component)box).GetComponent<PhotonView>() ?? ((Component)box).GetComponentInParent<PhotonView>(); int num = (((Object)(object)val != (Object)null && val.ViewID > 0) ? val.ViewID : Mathf.Abs(((Object)box).GetInstanceID())); if (!_storedCandidatesByBox.TryGetValue(num, out Dictionary<int, CapturedValuable> value) || value.Count == 0) { if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Hauler] Extracted box={num} had no individually tracked valuables."); } return; } foreach (KeyValuePair<int, CapturedValuable> item in value) { _candidates[item.Key] = item.Value; _capturedViewIds.Add(item.Key); } _logger.LogInfo((object)$"[HaulOfFame/Hauler] Extracted box={num}; promoted {value.Count} stored valuables into the final selection."); } public void HandleSceneChanged(Scene scene) { _announcement.Hide(); _trophy.HandleSceneChanged(); if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Scene] Loaded {((Scene)(ref scene)).name}[{((Scene)(ref scene)).buildIndex}]; championPreserved={_champion != null}."); } } private void OnPrepareReceived(int viewId, int extractionPointViewId) { if (!_config.Enabled.Value || _capturedViewIds.Contains(viewId)) { return; } try { PhotonView val = PhotonView.Find(viewId); PhysGrabObject val2 = (((Object)(object)val != (Object)null) ? (((Component)val).GetComponent<PhysGrabObject>() ?? ((Component)val).GetComponentInParent<PhysGrabObject>() ?? ((Component)val).GetComponentInChildren<PhysGrabObject>()) : null); ExtractionPoint val3 = _bindings.FindActiveExtractionPoint(extractionPointViewId); if ((Object)(object)val2 == (Object)null || (Object)(object)val3 == (Object)null) { _logger.LogWarning((object)$"[HaulOfFame/Capture] Could not resolve prepared valuable view={viewId}, extractionView={extractionPointViewId}."); } else { CaptureLocal(val3, val2, "host prepare event"); } } catch (Exception ex) { _logger.LogWarning((object)$"[HaulOfFame/Capture] Prepared valuable view={viewId} failed: {ex.GetType().Name}: {ex.Message}"); } } private void CaptureLocal(ExtractionPoint extractionPoint, PhysGrabObject physObject, string source) { if (!_bindings.TryCapture(extractionPoint, physObject, out CapturedValuable captured, out float localHaulScore, out string failure)) { if (_config.DebugLogging.Value) { _logger.LogWarning((object)("[HaulOfFame/Capture] Ignored extraction target from " + source + ": " + failure + ".")); } } else if (_capturedViewIds.Add(captured.ViewId)) { _candidates[captured.ViewId] = captured; if (captured.Beats(_bestSnapshot?.Valuable) && TrophyModelSnapshot.TryCreate(captured, physObject, _logger, out TrophyModelSnapshot snapshot)) { _bestSnapshot?.Dispose(); _bestSnapshot = snapshot; } int actorNumber = ((PhotonNetwork.InRoom && PhotonNetwork.LocalPlayer != null) ? PhotonNetwork.LocalPlayer.ActorNumber : 0); RecordContribution(actorNumber, captured.ViewId, localHaulScore); if (PhotonNetwork.InRoom && !PhotonNetwork.IsMasterClient) { _network.SendContribution(captured.ViewId, localHaulScore); } _logger.LogInfo((object)$"[HaulOfFame/Capture] Extracted '{captured.Name}', view={captured.ViewId}, value=${captured.CurrentValue:N0}/${captured.OriginalValue:N0}, localScore={localHaulScore:0.###}, source={source}, modelCopy={_bestSnapshot?.Valuable.ViewId == captured.ViewId}."); } } private void OnContributionReceived(int actorNumber, int viewId, float score) { if (!_candidates.ContainsKey(viewId) && !IsStoredCandidate(viewId)) { if (_config.DebugLogging.Value) { _logger.LogWarning((object)$"[HaulOfFame/Network] Contribution arrived for unknown view={viewId} from actor={actorNumber}."); } return; } RecordContribution(actorNumber, viewId, score); if (_config.DebugLogging.Value) { _logger.LogInfo((object)$"[HaulOfFame/Network] Contribution accepted: actor={actorNumber}, view={viewId}, score={score:0.###}."); } } private void RecordContribution(int actorNumber, int viewId, float score) { score = Mathf.Clamp(score, 0f, 1000f); if (!_contributions.TryGetValue(viewId, out Dictionary<int, float> value)) { value = new Dictionary<int, float>(); _contributions[viewId] = value; } if (!value.TryGetValue(actorNumber, out var value2) || score > value2) { value[actorNumber] = score; } } private void FinalizeChampion() { CapturedValuable capturedValuable = null; foreach (CapturedValuable value2 in _candidates.Values) { if (value2.Beats(capturedValuable)) { capturedValuable = value2; } } if (capturedValuable == null) { _logger.LogWarning((object)"[HaulOfFame/Result] Final extraction completed, but no valid valuable was captured."); return; } int[] array = Array.Empty<int>(); float[] array2 = Array.Empty<float>(); if (_contributions.TryGetValue(capturedValuable.ViewId, out Dictionary<int, float> value)) { array = new int[value.Count]; array2 = new float[value.Count]; int num = 0; foreach (KeyValuePair<int, float> item in value) { array[num] = item.Key; array2[num] = item.Value; num++; } } bool flag = !PhotonNetwork.InRoom || _network.AllPlayersHaveMod(); ChampionData champion = new ChampionData(capturedValuable, array, array2, flag); HandleChampion(champion); if (PhotonNetwork.InRoom) { _network.BroadcastChampion(champion); } _logger.LogInfo((object)$"[HaulOfFame/Result] Champion selected: '{capturedValuable.Name}', view={capturedValuable.ViewId}, value=${capturedValuable.CurrentValue:N0}, retained={capturedValuable.RetainedPercent:0.#}%, contributors={array.Length}, completeAttribution={flag}."); } private void OnChampionReceived(ChampionData champion) { if (_config.Enabled.Value) { HandleChampion(champion); _logger.LogInfo((object)$"[HaulOfFame/Network] Host champion received: '{champion.Valuable.Name}', view={champion.Valuable.ViewId}, value=${champion.Valuable.CurrentValue:N0}."); } } private void HandleChampion(ChampionData champion) { _champion = champion; (string, string, string, string) tuple = FormatChampion(champion); _announcement.Show(tuple.Item1, tuple.Item2, tuple.Item3); TrophyModelSnapshot snapshot = FindSnapshot(champion.Valuable.ViewId); _trophy.ShowChampion(champion, snapshot, tuple.Item4); } private (string Title, string Name, string Details, string Plaque) FormatChampion(ChampionData champion) { //IL_0012: Unknown result type (might be due to invalid IL or missing references) bool isSpanish = _config.IsSpanish; string text = ColorUtility.ToHtmlStringRGB(_config.GetAccentColor()); string item = (isSpanish ? "HAUL OF FAME — CAMPEÓN DE CARGA" : "HAUL OF FAME — HAUL CHAMPION"); string text2 = "$" + champion.Valuable.CurrentValue.ToString("N0", CultureInfo.InvariantCulture); string text3 = champion.Valuable.RetainedPercent.ToString("0.#", CultureInfo.InvariantCulture) + "%"; string item2 = (isSpanish ? (text2 + " • " + text3 + " CONSERVADO") : (text2 + " • " + text3 + " PRESERVED")); string text4 = FormatContributors(champion, isSpanish); string item3 = "<color=#" + text + ">HAUL OF FAME</color>\n" + champion.Valuable.Name.ToUpperInvariant() + "\n" + text2 + " • " + text3 + " " + (isSpanish ? "CONSERVADO" : "PRESERVED") + "\n" + text4; return (Title: item, Name: champion.Valuable.Name.ToUpperInvariant(), Details: item2, Plaque: item3); } private string FormatContributors(ChampionData champion, bool spanish) { List<(int, float)> list = new List<(int, float)>(); float num = 0f; for (int i = 0; i < champion.ContributorActors.Length && i < champion.ContributorScores.Length; i++) { float num2 = Mathf.Max(0f, champion.ContributorScores[i]); if (!(num2 <= 0f)) { list.Add((champion.ContributorActors[i], num2)); num += num2; } } if (num <= 0f || list.Count == 0) { if (!spanish) { return "TRANSPORTED BY THE CREW"; } return "TRANSPORTADO POR LA TRIPULACIÓN"; } list.Sort(((int Actor, float Score) left, (int Actor, float Score) right) => right.Score.CompareTo(left.Score)); int num3 = Mathf.Clamp(_config.MaxContributors.Value, 1, 8); float num4 = Mathf.Clamp(_config.MinimumContributionPercent.Value, 0f, 100f); List<string> list2 = new List<string>(); foreach (var item in list) { if (list2.Count >= num3) { break; } float num5 = item.Item2 * 100f / num; if (!(num5 < num4)) { list2.Add($"{_bindings.GetActorName(item.Item1).ToUpperInvariant()} {num5:0}%"); } } string text = (spanish ? "MVP: " : "MVP: ") + ((list2.Count > 0) ? string.Join(" • ", list2) : (spanish ? "TRIPULACIÓN" : "CREW")); if (!champion.AttributionComplete) { text += (spanish ? " • DATOS PARCIALES" : " • PARTIAL DATA"); } return text; } private void BeginMission(Scene scene) { ResetAll("new mission scene"); _missionSceneHandle = ((Scene)(ref scene)).handle; _logger.LogInfo((object)$"[HaulOfFame/Lifecycle] Mission tracking started in {((Scene)(ref scene)).name}[{((Scene)(ref scene)).buildIndex}]."); } private void ResetAll(string reason) { _trophy.Clear(); _announcement.Hide(); _bestSnapshot?.Dispose(); _bestSnapshot = null; foreach (TrophyModelSnapshot value in _storedBestSnapshotsByBox.Values) { value.Dispose(); } _storedBestSnapshotsByBox.Clear(); _champion = null; _candidates.Clear(); _contributions.Clear(); _storedCandidatesByBox.Clear(); _capturedViewIds.Clear(); _storedViewIds.Clear(); _finalizationTime = -1f; _missionSceneHandle = int.MinValue; if (_config.DebugLogging.Value) { _logger.LogInfo((object)("[HaulOfFame/Lifecycle] Runtime state cleared: " + reason + ".")); } } private void OnConfigChanged() { _announcement.ApplyConfig(); _trophy.ApplyConfig(); if (_champion != null) { (string, string, string, string) tuple = FormatChampion(_champion); TrophyModelSnapshot snapshot = FindSnapshot(_champion.Valuable.ViewId); _trophy.ShowChampion(_champion, snapshot, tuple.Item4); } _logger.LogInfo((object)"[HaulOfFame/Config] Configuration applied without restarting the game."); } private static bool IsAuthority() { if (PhotonNetwork.InRoom) { return PhotonNetwork.IsMasterClient; } return true; } private bool IsStoredCandidate(int viewId) { foreach (Dictionary<int, CapturedValuable> value in _storedCandidatesByBox.Values) { if (value.ContainsKey(viewId)) { return true; } } return false; } private TrophyModelSnapshot? FindSnapshot(int viewId) { if (_bestSnapshot != null && _bestSnapshot.Valuable.ViewId == viewId) { return _bestSnapshot; } foreach (TrophyModelSnapshot value in _storedBestSnapshotsByBox.Values) { if (value.Valuable.ViewId == viewId) { return value; } } return null; } public void Dispose() { if (_disposed) { return; } _disposed = true; _config.Changed -= OnConfigChanged; _network.PrepareReceived -= OnPrepareReceived; _network.ContributionReceived -= OnContributionReceived; _network.ChampionReceived -= OnChampionReceived; _trophy.Clear(); _bestSnapshot?.Dispose(); _bestSnapshot = null; foreach (TrophyModelSnapshot value in _storedBestSnapshotsByBox.Values) { value.Dispose(); } _storedBestSnapshotsByBox.Clear(); _network.Dispose(); _announcement.Dispose(); _trophy.Dispose(); } } } namespace HaulOfFame.Config { public enum DisplayLanguage { Auto, English, Spanish } public enum TrophyPositionMode { FixedWorld, ScreenRelative } public sealed class ModConfig : IDisposable { private const float ExternalReloadInterval = 0.5f; private readonly ConfigFile _configFile; private readonly List<Action> _unsubscribeActions = new List<Action>(); private DateTime _lastWriteTimeUtc; private long _lastFileLength; private float _reloadTimer; private bool _reloading; public ConfigEntry<bool> Enabled { get; } public ConfigEntry<bool> ShowAnnouncement { get; } public ConfigEntry<bool> ShowWorldTrophy { get; } public ConfigEntry<bool> ShowEmptyBase { get; } public ConfigEntry<float> AnnouncementDuration { get; } public ConfigEntry<int> MaxContributors { get; } public ConfigEntry<float> MinimumContributionPercent { get; } public ConfigEntry<DisplayLanguage> Language { get; } public ConfigEntry<float> TrophyScale { get; } public ConfigEntry<float> SpinSpeed { get; } public ConfigEntry<float> BobHeight { get; } public ConfigEntry<float> BobSpeed { get; } public ConfigEntry<TrophyPositionMode> PositionMode { get; } public ConfigEntry<float> WorldX { get; } public ConfigEntry<float> WorldY { get; } public ConfigEntry<float> WorldZ { get; } public ConfigEntry<float> OffsetX { get; } public ConfigEntry<float> OffsetY { get; } public ConfigEntry<float> OffsetZ { get; } public ConfigEntry<float> RotationY { get; } public ConfigEntry<string> AccentColor { get; } public ConfigEntry<bool> SoundEnabled { get; } public ConfigEntry<float> SoundVolume { get; } public ConfigEntry<bool> DebugLogging { get; } public bool IsSpanish { get { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Invalid comparison between Unknown and I4 if (Language.Value != DisplayLanguage.Spanish) { if (Language.Value == DisplayLanguage.Auto) { return (int)Application.systemLanguage == 34; } return false; } return true; } } public event Action? Changed; public ModConfig(ConfigFile config) { _configFile = config; Enabled = Bind(config, "General", "Enabled", defaultValue: true, "Enable Haul of Fame."); ShowAnnouncement = Bind(config, "General", "ShowAnnouncement", defaultValue: true, "Show the post-extraction champion banner."); ShowWorldTrophy = Bind(config, "General", "ShowWorldTrophy", defaultValue: true, "Display the winning valuable as a harmless trophy near the truck screen."); ShowEmptyBase = Bind(config, "General", "ShowEmptyBase", defaultValue: true, "Keep the empty trophy pedestal visible in the truck before a champion is selected."); AnnouncementDuration = Bind(config, "General", "AnnouncementDuration", 5f, "Seconds the champion banner remains visible."); MaxContributors = Bind(config, "General", "MaxContributors", 4, "Maximum contributor names displayed on the trophy plaque."); MinimumContributionPercent = Bind(config, "General", "MinimumContributionPercent", 2f, "Hide contributors below this percentage."); Language = Bind(config, "General", "