using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using ExitGames.Client.Photon; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using Photon.Realtime; using REPOLib.Modules; using TMPro; using TokControlREPOBridge.Commands; using TokControlREPOBridge.Logging; using TokControlREPOBridge.Network; using TokControlREPOBridge.Ui; using TokControlREPOBridge.Util; using UnityEngine; using UnityEngine.AI; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Utilities; 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("TokControl_REPO_Tiktoklive")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("TokControl WebSocket bridge for R.E.P.O. TikTok Live — spawn items and enemies from stream gifts")] [assembly: AssemblyFileVersion("1.3.91.0")] [assembly: AssemblyInformationalVersion("1.3.91")] [assembly: AssemblyProduct("TokControl_REPO_Tiktoklive")] [assembly: AssemblyTitle("TokControl_REPO_Tiktoklive")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.3.91.0")] [module: UnverifiableCode] 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; } } internal static class IsExternalInit { } } namespace TokControlREPOBridge { [BepInPlugin("com.tokcontrol.repobridge", "TokControl_REPO_Tiktoklive", "1.3.91")] [BepInDependency(/*Could not decode attribute arguments.*/)] public class Plugin : BaseUnityPlugin { private ConfigEntry _portConfig; private ConfigEntry _logToUnityConfig; private ConfigEntry _defaultGhostEnemyConfig; private WebSocketServer? _server; private CommandProcessor? _processor; private Harmony? _harmony; private static readonly ConcurrentQueue MainThreadQueue = new ConcurrentQueue(); private static readonly List<(float due, Action action)> DelayedActions = new List<(float, Action)>(); private static readonly object DelayedLock = new object(); private const int MinActionsPerFrame = 16; private const int MaxBurstActionsPerFrame = 256; internal static Plugin Instance { get; private set; } = null; internal static ManualLogSource Log { get; private set; } = null; internal static void EnqueueMainThread(Action action) { if (action != null) { MainThreadQueue.Enqueue(action); } } internal static void EnqueueMainThreadDelayed(Action action, float delaySeconds) { if (action == null) { return; } if (delaySeconds <= 0.001f) { EnqueueMainThread(action); return; } lock (DelayedLock) { DelayedActions.Add((Time.realtimeSinceStartup + delaySeconds, action)); } } private void Awake() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); ModLog.Info("=== TokControl_REPO_Tiktoklive v1.3.91 ==="); ModLog.Info("REPOLib dependency OK — initializing WebSocket bridge"); try { _harmony = new Harmony("com.tokcontrol.repobridge"); _harmony.PatchAll(typeof(Plugin).Assembly); ModLog.Info("Enemy spawn patches applied"); } catch (Exception ex) { ModLog.Warn("Harmony patch failed: " + ex.Message); } _processor = new CommandProcessor(_defaultGhostEnemyConfig.Value); SpawnRelay.Initialize(_processor.Actions); EffectRelay.Initialize(_processor.Actions); SpeakBroadcast.Initialize(); try { _server = new WebSocketServer(_portConfig.Value, _processor); _server.Start(); ModLog.Info($"WebSocket listening on ws://127.0.0.1:{_server.Port}/"); if (_server.Port != _portConfig.Value) { ModLog.Warn($"Configured port {_portConfig.Value} was busy. Update TokControl URL → ws://127.0.0.1:{_server.Port}/"); } } catch (Exception ex2) { ModLog.Error("Failed to start WebSocket bridge: " + ex2.Message); ModLog.Error("Disable other TikTok/stream mods using port 8080, or change Server.Port in the config file."); _server = null; } MainThreadDispatcher.Enqueue(delegate { ItemRegistry.EnsureLoaded(); _ = EffectTimerHost.Instance; TokControlStatusHud.Ensure(); }); ModLog.Info("Waiting for TokControl / Pandy App commands..."); } private void Update() { float deltaTime = Time.deltaTime; try { RunGate.Tick(deltaTime); } catch { } float realtimeSinceStartup = Time.realtimeSinceStartup; lock (DelayedLock) { for (int num = DelayedActions.Count - 1; num >= 0; num--) { if (!(DelayedActions[num].due > realtimeSinceStartup)) { Action item = DelayedActions[num].action; DelayedActions.RemoveAt(num); if (item != null) { MainThreadQueue.Enqueue(item); } } } } int count = MainThreadQueue.Count; int num2 = ((count > 2) ? Math.Min(count, 256) : 16); int num3 = 0; Action result; while (num3 < num2 && MainThreadQueue.TryDequeue(out result)) { num3++; try { result(); } catch (Exception ex) { ModLog.Error("Main thread action failed: " + ex.Message); } } } private void BindConfig() { _portConfig = ((BaseUnityPlugin)this).Config.Bind("Server", "Port", 8080, "Local WebSocket port for TokControl commands (ws://127.0.0.1:PORT/)"); _logToUnityConfig = ((BaseUnityPlugin)this).Config.Bind("Debug", "LogToUnityConsole", true, "Mirror TokControl bridge logs to Unity debug console"); _defaultGhostEnemyConfig = ((BaseUnityPlugin)this).Config.Bind("Gameplay", "DefaultGhostEnemy", "Hidden", "Enemy name used for spawn_ghost when no name is provided (e.g. Hidden, Robe, Hunter)"); } internal static bool ShouldLogToUnity() { return Instance?._logToUnityConfig?.Value ?? true; } private void OnDestroy() { try { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch { } _server?.Dispose(); ModLog.Info("TokControl_REPO_Tiktoklive shut down"); } } public static class PluginInfo { public const string PLUGIN_GUID = "com.tokcontrol.repobridge"; public const string PLUGIN_NAME = "TokControl_REPO_Tiktoklive"; public const string PLUGIN_VERSION = "1.3.91"; } } namespace TokControlREPOBridge.Util { internal static class BurstCoalescer { private const float QuietSeconds = 0.45f; private static readonly Dictionary FlushActions = new Dictionary(); internal static void Debounce(string key, Action onFlush, Action? onTouch = null) { onTouch?.Invoke(); FlushActions[key] = onFlush; EffectTimerHost.Instance.Stop(key); EffectTimerHost.Instance.RunForSeconds(key, 0.45f, delegate { }, delegate { if (!FlushActions.TryGetValue(key, out Action value)) { return; } FlushActions.Remove(key); try { value(); } catch (Exception ex) { ModLog.Warn("Burst flush '" + key + "' failed: " + ex.Message); } }); } } public static class GameNotifier { public static void AnnounceSpawn(string user, string target, int count, string kind) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string text2 = (string.IsNullOrWhiteSpace(target) ? "item" : target.Trim()); string text3 = ((count > 1) ? $" x{count}" : ""); PostAnnouncement(text + " activates '" + text2 + text3 + "'", 4.5f); } public static void AnnounceEvent(string user, string eventId) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string label = EventLangCatalog.GetLabel(eventId); PostAnnouncement(text + " activates '" + label + "'", 3.5f); } public static void AnnounceCustom(string user, string message, float seconds = 4.5f) { string text = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); string text2 = (string.IsNullOrWhiteSpace(message) ? "event" : message.Trim()); if (text2.IndexOf(text, StringComparison.OrdinalIgnoreCase) >= 0) { PostAnnouncement(text2, seconds); } else { PostAnnouncement(text + " → " + text2, seconds); } } private static void PostAnnouncement(string line, float seconds = 3f) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrWhiteSpace(line)) { PostTruck(line); PostMission(line, new Color(1f, 0.45f, 0.15f), Color.white, Math.Max(2f, seconds)); } } private static void PostTruck(string message) { try { if ((Object)(object)TruckScreenText.instance == (Object)null) { ModLog.Debug("TruckScreenText not ready — skip monitor message"); } else { TruckScreenText.instance.MessageSendCustom("", "{arrowright}" + message + "{arrowleft}", 0); } } catch (Exception ex) { ModLog.Debug("Truck notify failed: " + ex.Message); } } private static void PostMission(string text, Color colorA, Color colorB, float seconds) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)MissionUI.instance == (Object)null)) { MissionUI.instance.MissionText(text, colorA, colorB, seconds); } } catch (Exception ex) { ModLog.Debug("Mission notify failed: " + ex.Message); } } } public static class MainThreadDispatcher { public static bool IsReady => (Object)(object)Plugin.Instance != (Object)null; public static void Enqueue(Action action) { Plugin.EnqueueMainThread(action); } public static void EnqueueDelayed(Action action, float delaySeconds) { Plugin.EnqueueMainThreadDelayed(action, delaySeconds); } } public static class SimpleJson { public static string? GetString(string json, string key) { if (string.IsNullOrEmpty(json) || string.IsNullOrEmpty(key)) { return null; } string value = "\"" + key + "\""; int num = json.IndexOf(value, StringComparison.OrdinalIgnoreCase); if (num < 0) { return null; } num = json.IndexOf(':', num); if (num < 0) { return null; } for (num++; num < json.Length && char.IsWhiteSpace(json[num]); num++) { } if (num >= json.Length) { return null; } if (json[num] == '"') { num++; int num2 = num; while (num < json.Length) { if (json[num] == '\\') { num += 2; continue; } if (json[num] == '"') { break; } num++; } return json.Substring(num2, num - num2); } int num3 = num; for (; num < json.Length && json[num] != ',' && json[num] != '}'; num++) { } return json.Substring(num3, num - num3).Trim().Trim('"'); } public static int? GetInt(string json, string key) { string text = GetString(json, key); if (text != null && int.TryParse(text, out var result)) { return result; } return null; } public static string Escape(string value) { return (value ?? "").Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n") .Replace("\r", "\\r"); } public static string CommandResult(bool success, string message, string? detail = null) { if (!string.IsNullOrEmpty(detail)) { return "{\"success\":" + (success ? "true" : "false") + ",\"message\":\"" + Escape(message) + "\",\"detail\":\"" + Escape(detail) + "\"}"; } return "{\"success\":" + (success ? "true" : "false") + ",\"message\":\"" + Escape(message) + "\"}"; } public static string EffectPayload(string eventId, string user, int playerViewId = 0, int count = 1, string? namedPlayer = null) { int num = Math.Max(1, Math.Min(count, 100)); string text = Escape(namedPlayer ?? ""); return $"{{\"count\":{num},\"eventId\":\"{Escape(eventId)}\",\"user\":\"{Escape(user)}\",\"playerViewId\":{playerViewId},\"namedPlayer\":\"{text}\"}}"; } public static bool TryParseEffectPayload(string json, out string eventId, out string user) { int playerViewId; int count; string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId) { int count; string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId, out int count) { string namedPlayer; return TryParseEffectPayload(json, out eventId, out user, out playerViewId, out count, out namedPlayer); } public static bool TryParseEffectPayload(string json, out string eventId, out string user, out int playerViewId, out int count, out string namedPlayer) { eventId = GetString(json, "eventId") ?? GetString(json, "cmd") ?? ""; user = GetString(json, "user") ?? "viewer"; playerViewId = GetInt(json, "playerViewId").GetValueOrDefault(); count = Math.Max(1, Math.Min(GetInt(json, "count") ?? 1, 100)); namedPlayer = GetString(json, "namedPlayer") ?? GetString(json, "targetPlayer") ?? ""; return !string.IsNullOrWhiteSpace(eventId); } public static string SpawnPayload(string cmd, string name, int count, string user, int playerViewId = 0) { return $"{{\"count\":{count},\"cmd\":\"{Escape(cmd)}\",\"name\":\"{Escape(name)}\",\"user\":\"{Escape(user)}\",\"playerViewId\":{playerViewId}}}"; } public static bool TryParseSpawnPayload(string json, out string cmd, out string name, out int count, out string user) { int playerViewId; return TryParseSpawnPayload(json, out cmd, out name, out count, out user, out playerViewId); } public static bool TryParseSpawnPayload(string json, out string cmd, out string name, out int count, out string user, out int playerViewId) { cmd = GetString(json, "cmd") ?? ""; name = GetString(json, "name") ?? ""; count = GetInt(json, "count") ?? 1; user = GetString(json, "user") ?? "viewer"; playerViewId = GetInt(json, "playerViewId").GetValueOrDefault(); return !string.IsNullOrWhiteSpace(cmd); } } } namespace TokControlREPOBridge.Ui { internal static class EnemyRoomCounter { private const float RoomRadius = 22f; internal static int CountInCurrentRooms() { return HudStatsProvider.GetEnemyCount(); } internal static int ScanLiveCountInCurrentRooms() { //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (!IsInGameplayLevel()) { return 0; } List playerRoomAnchors = HudRoomHelper.GetPlayerRoomAnchors(); if (playerRoomAnchors.Count == 0) { return 0; } int num = 0; EnemyParent[] array = Object.FindObjectsOfType(); foreach (EnemyParent val in array) { if (IsLiveEnemy(val) && IsNearAnyAnchor(((Component)val).transform.position, playerRoomAnchors, 22f)) { num++; } } return num; } private static bool IsInGameplayLevel() { try { if (SemiFunc.MenuLevel()) { return false; } return SemiFunc.RunIsLevel(); } catch { return (Object)(object)RunManager.instance != (Object)null; } } private static bool IsNearAnyAnchor(Vector3 position, List anchors, float radius) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) float num = radius * radius; foreach (Vector3 anchor in anchors) { if (HorizontalDistanceSqr(position, anchor) <= num) { return true; } } return false; } private static bool IsLiveEnemy(EnemyParent parent) { if ((Object)(object)parent == (Object)null || !((Component)parent).gameObject.activeInHierarchy) { return false; } Enemy componentInChildren = ((Component)parent).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null || !((Component)componentInChildren).gameObject.activeInHierarchy) { return false; } if (ReadBool(parent, "despawned")) { return false; } if (ReadBool(parent, "disabled")) { return false; } if (ReadBool(componentInChildren, "disabled")) { return false; } if (ReadBool(componentInChildren, "dead")) { return false; } if (ReadBool(componentInChildren, "isDead")) { return false; } if (ReadBool(componentInChildren, "despawned")) { return false; } return true; } private static bool ReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } } catch { } return false; } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) a.y = 0f; b.y = 0f; Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; } } internal static class HudRoomHelper { private const float RoomRadius = 22f; internal static bool IsInCurrentRoom(Vector3 position) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) List playerRoomAnchors = GetPlayerRoomAnchors(); if (playerRoomAnchors.Count == 0) { return false; } float num = 484f; foreach (Vector3 item in playerRoomAnchors) { if (HorizontalDistanceSqr(position, item) <= num) { return true; } } return false; } internal static List GetPlayerRoomAnchors() { //IL_007c: 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) List list = new List(); try { List list2 = SemiFunc.LevelPointsGetInPlayerRooms(); if (list2 != null) { foreach (LevelPoint item in list2) { if ((Object)(object)item != (Object)null) { list.Add(((Component)item).transform.position); } } } } catch { } if (list.Count > 0) { return list; } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null) { list.Add(((Component)val).transform.position); } return list; } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) a.y = 0f; b.y = 0f; Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; } } internal static class HudStatsProvider { private const float MapInterval = 0.5f; private const float CartInterval = 0.55f; private const float CosmeticInterval = 1.35f; private const float EnemyInterval = 0.6f; private static readonly Dictionary RarityColors = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["common"] = "#55FF55", ["uncommon"] = "#5599FF", ["rare"] = "#BB55FF", ["ultrarare"] = "#FF8800", ["ultra"] = "#FF8800", ["ultra rare"] = "#FF8800" }; private static readonly string[] RarityOrder = new string[4] { "common", "uncommon", "rare", "ultrarare" }; private static float _cachedMap; private static float _cachedCart; private static int _cachedEnemies; private static string _cachedCosmetics = string.Empty; private static bool _hasCosmetics; private static float _mapNext; private static float _cartNext; private static float _cosmeticNext; private static float _enemyNext; internal static void InvalidateCache() { _mapNext = 0f; _cartNext = 0f; _cosmeticNext = 0f; _enemyNext = 0f; } internal static void TickCache() { float unscaledTime = Time.unscaledTime; if (unscaledTime >= _mapNext) { _cachedMap = ScanMapValue(); _mapNext = unscaledTime + 0.5f; } if (unscaledTime >= _cartNext) { _cachedCart = ScanCartValue(); _cartNext = unscaledTime + 0.55f; } if (unscaledTime >= _cosmeticNext) { _hasCosmetics = ScanCosmeticIconLine(out _cachedCosmetics); _cosmeticNext = unscaledTime + 1.35f; } if (unscaledTime >= _enemyNext) { _cachedEnemies = EnemyRoomCounter.ScanLiveCountInCurrentRooms(); _enemyNext = unscaledTime + 0.6f; } } internal static float GetMapValue() { return _cachedMap; } internal static float GetCartValue() { return _cachedCart; } internal static int GetEnemyCount() { return _cachedEnemies; } internal static bool TryBuildCosmeticIconLine(out string line) { line = _cachedCosmetics; return _hasCosmetics; } private static float ScanMapValue() { float num = 0f; HashSet cartPhysObjects = GetCartPhysObjects(); ValuableObject[] array = Object.FindObjectsOfType(); foreach (ValuableObject val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled) { PhysGrabObject component = ((Component)val).GetComponent(); if (!((Object)(object)component != (Object)null) || !cartPhysObjects.Contains(component)) { num += Mathf.Max(0f, val.dollarValueCurrent); } } } return num; } private static float ScanCartValue() { float num = 0f; PhysGrabCart[] allCarts = CartHelper.GetAllCarts(); foreach (PhysGrabCart cart in allCarts) { foreach (PhysGrabObject cartItemObject in CartHelper.GetCartItemObjects(cart)) { if (!((Object)(object)cartItemObject == (Object)null)) { ValuableObject component = ((Component)cartItemObject).GetComponent(); if ((Object)(object)component != (Object)null) { num += Mathf.Max(0f, component.dollarValueCurrent); } } } } return num; } private static bool ScanCosmeticIconLine(out string line) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); CosmeticWorldObject[] array = Object.FindObjectsOfType(); foreach (CosmeticWorldObject val in array) { if (!((Object)(object)val == (Object)null) && ((Behaviour)val).isActiveAndEnabled && !IsCosmeticBoxExtracted(val) && HudRoomHelper.IsInCurrentRoom(((Component)val).transform.position)) { string text = NormalizeRarity(ReadCosmeticRarity(val)); if (!string.IsNullOrWhiteSpace(text)) { hashSet.Add(text); } } } if (hashSet.Count == 0) { line = string.Empty; return false; } StringBuilder stringBuilder = new StringBuilder(); string[] rarityOrder = RarityOrder; foreach (string text2 in rarityOrder) { if (hashSet.Contains(text2)) { string value; string text3 = (RarityColors.TryGetValue(text2, out value) ? value : "#DDDDDD"); if (stringBuilder.Length > 0) { stringBuilder.Append(' '); } stringBuilder.Append("■"); } } line = stringBuilder.ToString(); return line.Length > 0; } private static bool IsCosmeticBoxExtracted(CosmeticWorldObject box) { try { CosmeticWorldObjectHealth component = ((Component)box).GetComponent(); if ((Object)(object)component != (Object)null) { FieldInfo field = typeof(CosmeticWorldObjectHealth).GetField("health", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(component); if (value is float num && num <= 0f) { return true; } if (value is int num2 && num2 <= 0) { return true; } } } } catch { } string text = ((Object)((Component)box).gameObject).name.ToLowerInvariant(); if (!text.Contains("extract") && !text.Contains("broken")) { return text.Contains("opened"); } return true; } private static string ReadCosmeticRarity(CosmeticWorldObject box) { try { FieldInfo field = typeof(CosmeticWorldObject).GetField("cosmeticRarity", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null) { object value = field.GetValue(box); if (value != null) { return value.ToString() ?? string.Empty; } } } catch { } return GuessRarityFromName(((Object)((Component)box).gameObject).name); } private static string NormalizeRarity(string rarity) { string text = rarity.Replace("_", " ").Trim().ToLowerInvariant(); if (text.Contains("ultra")) { return "ultrarare"; } if (text.Contains("uncommon")) { return "uncommon"; } if (text.Contains("common")) { return "common"; } if (text.Contains("rare")) { return "rare"; } return text; } private static string GuessRarityFromName(string name) { string text = name.ToLowerInvariant(); if (text.Contains("ultra")) { return "ultrarare"; } if (text.Contains("uncommon")) { return "uncommon"; } if (text.Contains("rare")) { return "rare"; } if (text.Contains("common")) { return "common"; } return string.Empty; } private static HashSet GetCartPhysObjects() { HashSet hashSet = new HashSet(); PhysGrabCart[] allCarts = CartHelper.GetAllCarts(); foreach (PhysGrabCart cart in allCarts) { foreach (PhysGrabObject cartItemObject in CartHelper.GetCartItemObjects(cart)) { if ((Object)(object)cartItemObject != (Object)null) { hashSet.Add(cartItemObject); } } } return hashSet; } } internal sealed class MapValueAnimator { private const float ScanDuration = 0.85f; private const float LossFadeDuration = 1.75f; private float _mapValue; private float _lossAmount; private float _lossFadeTimer; private float _scanTimer; private float _scanMax; private bool _scanReady; internal bool IsScanReady => _scanReady; internal bool IsAnimating => _lossFadeTimer > 0f; internal void BeginLevel() { _mapValue = 0f; _lossAmount = 0f; _lossFadeTimer = 0f; _scanTimer = 0.85f; _scanMax = 0f; _scanReady = false; } internal void EndLevel() { _scanReady = false; _scanTimer = 0f; _lossAmount = 0f; _lossFadeTimer = 0f; } internal void Tick(float actualValue, float deltaTime) { if (!_scanReady) { _scanMax = Mathf.Max(_scanMax, actualValue); _scanTimer -= deltaTime; if (_scanTimer <= 0f) { _mapValue = _scanMax; _scanReady = true; } return; } if (actualValue > _mapValue + 0.5f) { _mapValue = actualValue; return; } if (actualValue < _mapValue - 0.5f) { _lossAmount = _mapValue - actualValue; _mapValue = actualValue; _lossFadeTimer = 1.75f; } else { _mapValue = actualValue; } if (_lossFadeTimer > 0f) { _lossFadeTimer -= deltaTime; if (_lossFadeTimer <= 0f) { _lossAmount = 0f; _lossFadeTimer = 0f; } } } internal string? BuildMapLine() { if (!_scanReady) { return null; } if (_lossAmount > 0.5f && _lossFadeTimer > 0f) { float num = Mathf.Clamp01(_lossFadeTimer / 1.75f); string arg = Color32ToHex(byte.MaxValue, (byte)Mathf.RoundToInt(77f * num), (byte)Mathf.RoundToInt(77f * num)); return $"-${_lossAmount:N0} MAP: ${_mapValue:N0}"; } return $"MAP: ${_mapValue:N0}"; } private static string Color32ToHex(byte r, byte g, byte b) { return $"{r:X2}{g:X2}{b:X2}"; } } internal sealed class TokControlStatusHud : MonoBehaviour { private const float RefreshInterval = 0.4f; private const float LossRefreshInterval = 0.08f; private const float RepositionInterval = 1.5f; private const float LineHeight = 14f; private const float FontSize = 13f; private static TokControlStatusHud? _instance; private readonly MapValueAnimator _mapAnimator = new MapValueAnimator(); private GameObject? _panelRoot; private TextMeshProUGUI? _label; private RectTransform? _panelRt; private RectTransform? _gameHudRt; private RectTransform? _taxHaulRt; private float _refreshTimer; private float _repositionTimer; private string _lastText = string.Empty; private int _trackedLevel = -1; private bool _wasInLevel; internal static void Ensure() { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown if (!((Object)(object)_instance != (Object)null)) { GameObject val = new GameObject("TokControlStatusHud"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent(); } } private void Update() { bool flag = IsInPlayableLevel(); if (flag && !_wasInLevel) { _trackedLevel = GetLevelId(); _mapAnimator.BeginLevel(); HudStatsProvider.InvalidateCache(); } else if (flag) { int levelId = GetLevelId(); if (levelId != _trackedLevel) { _trackedLevel = levelId; _mapAnimator.BeginLevel(); HudStatsProvider.InvalidateCache(); } } else if (_wasInLevel) { _trackedLevel = -1; _mapAnimator.EndLevel(); HudStatsProvider.InvalidateCache(); } _wasInLevel = flag; if (!ShouldShowHud()) { HidePanel(); return; } if (!EnsurePanel()) { HidePanel(); return; } _repositionTimer -= Time.unscaledDeltaTime; if (_repositionTimer <= 0f) { _repositionTimer = 1.5f; RepositionBelowHudStack(); } HudStatsProvider.TickCache(); _mapAnimator.Tick(HudStatsProvider.GetMapValue(), Time.unscaledDeltaTime); float refreshTimer = (_mapAnimator.IsAnimating ? 0.08f : 0.4f); _refreshTimer -= Time.unscaledDeltaTime; if (!(_refreshTimer > 0f) || !((Object)(object)_panelRoot != (Object)null) || !_panelRoot.activeSelf) { _refreshTimer = refreshTimer; string text = BuildStatusText(); if (!(text == _lastText) || !((Object)(object)_panelRoot != (Object)null) || !_panelRoot.activeSelf) { _lastText = text; ((TMP_Text)_label).SetText(text, true); _panelRoot.SetActive(true); } } } private string BuildStatusText() { //IL_005b: Unknown result type (might be due to invalid IL or missing references) float cartValue = HudStatsProvider.GetCartValue(); int enemyCount = HudStatsProvider.GetEnemyCount(); string line; bool flag = HudStatsProvider.TryBuildCosmeticIconLine(out line); int num = 2; if (_mapAnimator.IsScanReady) { num++; } num++; if (flag) { num++; } if ((Object)(object)_panelRt != (Object)null) { _panelRt.sizeDelta = new Vector2(168f, 14f * (float)num); } StringBuilder stringBuilder = new StringBuilder(); string value = _mapAnimator.BuildMapLine(); if (!string.IsNullOrEmpty(value)) { stringBuilder.AppendLine(value); } stringBuilder.AppendLine($"C.A.R.T.: ${cartValue:N0}"); stringBuilder.AppendLine($"MON: {enemyCount}"); if (flag) { stringBuilder.Append(line); } return stringBuilder.ToString().TrimEnd(); } private static bool IsInPlayableLevel() { try { return !SemiFunc.MenuLevel() && SemiFunc.RunIsLevel(); } catch { return (Object)(object)RunManager.instance != (Object)null; } } private static int GetLevelId() { try { Level val = RunManager.instance?.levelCurrent; return ((Object)(object)val == (Object)null) ? (-1) : ((object)val).GetHashCode(); } catch { return -1; } } private static bool ShouldShowHud() { if (!IsInPlayableLevel()) { return false; } if (IsMapOpen()) { return false; } return true; } private static bool IsMapOpen() { try { if (SemiFunc.InputHold((InputKey)8)) { return true; } } catch { } if (Input.GetKey((KeyCode)9)) { return true; } try { if ((Object)(object)MapToolController.instance == (Object)null) { return false; } FieldInfo field = typeof(MapToolController).GetField("mapToggled", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(MapToolController.instance); } } catch { } return false; } private bool EnsurePanel() { //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Expected O, but got Unknown //IL_014e: Unknown result type (might be due to invalid IL or missing references) //IL_017e: Unknown result type (might be due to invalid IL or missing references) //IL_01c0: Unknown result type (might be due to invalid IL or missing references) //IL_01da: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_020e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelRoot != (Object)null && (Object)(object)_label != (Object)null && (Object)(object)_panelRt != (Object)null) { return true; } GameObject val = GameObject.Find("Game Hud"); GameObject val2 = GameObject.Find("Tax Haul"); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return false; } TMP_Text component = val2.GetComponent(); if ((Object)(object)component == (Object)null || (Object)(object)component.font == (Object)null) { return false; } _gameHudRt = val.GetComponent(); _taxHaulRt = val2.GetComponent(); _panelRoot = new GameObject("TokControl Status HUD"); _panelRoot.SetActive(false); _label = _panelRoot.AddComponent(); ((TMP_Text)_label).font = component.font; ((TMP_Text)_label).fontSize = 13f; ((TMP_Text)_label).lineSpacing = 0f; ((TMP_Text)_label).paragraphSpacing = 0f; ((TMP_Text)_label).enableWordWrapping = false; ((TMP_Text)_label).alignment = (TextAlignmentOptions)260; ((TMP_Text)_label).horizontalAlignment = (HorizontalAlignmentOptions)4; ((TMP_Text)_label).verticalAlignment = (VerticalAlignmentOptions)256; ((Graphic)_label).color = new Color(0.79f, 0.91f, 0.9f, 1f); ((TMP_Text)_label).richText = true; ((TMP_Text)_label).margin = new Vector4(0f, 0f, 0f, 0f); _panelRoot.transform.SetParent(val.transform, false); _panelRt = _panelRoot.GetComponent(); _panelRt.anchorMin = new Vector2(1f, 1f); _panelRt.anchorMax = new Vector2(1f, 1f); _panelRt.pivot = new Vector2(1f, 1f); _panelRt.sizeDelta = new Vector2(168f, 56f); return true; } private void RepositionBelowHudStack() { //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0161: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: 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_0118: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_panelRt == (Object)null) { return; } if ((Object)(object)_gameHudRt == (Object)null || (Object)(object)_taxHaulRt == (Object)null) { GameObject val = GameObject.Find("Game Hud"); GameObject obj = GameObject.Find("Tax Haul"); RectTransform val2 = ((obj != null) ? obj.GetComponent() : null); if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null) { return; } _gameHudRt = val.GetComponent(); _taxHaulRt = val2; } float num = _taxHaulRt.anchoredPosition.y; TMP_Text[] componentsInChildren = ((Component)_gameHudRt).GetComponentsInChildren(true); foreach (TMP_Text val3 in componentsInChildren) { if ((Object)(object)val3 == (Object)null || (Object)(object)val3 == (Object)(object)_label || ((Object)((Component)val3).gameObject).name.StartsWith("TokControl") || !((Component)val3).gameObject.activeInHierarchy) { continue; } RectTransform component = ((Component)val3).GetComponent(); if (!((Object)(object)component == (Object)null) && !(component.anchorMax.x < 0.55f)) { float num2 = component.anchoredPosition.y - Mathf.Max(component.sizeDelta.y, val3.fontSize * 0.85f); if (num2 < num) { num = num2; } } } _panelRt.anchoredPosition = new Vector2(-12f, num - 4f); } private void HidePanel() { if ((Object)(object)_panelRoot != (Object)null) { _panelRoot.SetActive(false); } _lastText = string.Empty; } } } namespace TokControlREPOBridge.Network { public static class EffectRelay { private const string EventName = "TokControl_EffectRelay_v1"; private static NetworkedEvent? _relayEvent; public static void Initialize(GameActions actions) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown _relayEvent = new NetworkedEvent("TokControl_EffectRelay_v1", (Action)OnRelayReceived); ModLog.Info("Effect relay initialized (client → host)"); } public static CommandResult ExecuteEffect(string eventId, string user, int count = 1) { return StreamEventRunner.Execute(eventId, user, count); } public static CommandResult RelayKnownEvent(string eventId, string user, int count = 1, int playerViewId = 0, string? namedPlayer = null) { return RelayToHost(eventId, user, playerViewId, count, namedPlayer); } private static CommandResult RelayToHost(string eventId, string user, int playerViewId, int count, string? namedPlayer = null) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) if (_relayEvent == null) { return CommandResult.Fail("relay_not_ready"); } count = Math.Max(1, Math.Min(count, 100)); try { string text = SimpleJson.EffectPayload(eventId, user, playerViewId, count, namedPlayer); _relayEvent.RaiseEvent((object)text, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); ModLog.Info($"Effect relayed to host: {eventId} x{count} for @{user} (view={playerViewId} name={namedPlayer})"); return CommandResult.Ok("relayed_to_host", $"Effect {eventId} x{count} sent to lobby host"); } catch (Exception ex) { ModLog.Error("Effect relay failed: " + ex.Message); return CommandResult.Fail("relay_failed:" + ex.Message); } } private static void OnRelayReceived(EventData eventData) { if (!SemiFunc.IsMasterClientOrSingleplayer()) { ModLog.Debug("Effect relay received on non-host — ignored"); return; } try { string text = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(text)) { ModLog.Warn("Effect relay payload empty"); return; } if (!SimpleJson.TryParseEffectPayload(text, out string eventId, out string user, out int playerViewId, out int count, out string namedPlayer)) { ModLog.Warn("Effect relay payload invalid"); return; } ModLog.Info($"Host executing effect relay: {eventId} x{count} for @{user} view={playerViewId} name={namedPlayer}"); MainThreadDispatcher.Enqueue(delegate { string commandLine; if (!string.IsNullOrWhiteSpace(namedPlayer)) { StreamEventRunner.Execute(eventId, user ?? "viewer", count, null, namedPlayer); } else if (!EventCommandCatalog.TryGetCommandLine(eventId, out commandLine)) { ModLog.Warn("Host relay unknown event: " + eventId); } else { PlayerAvatar targetPlayer = null; if (playerViewId > 0) { try { targetPlayer = SemiFunc.PlayerAvatarGetFromPhotonID(playerViewId); } catch { } } StreamEventRunner.ExecuteLocal(eventId, commandLine, user ?? "viewer", count, targetPlayer); } }); } catch (Exception ex) { ModLog.Error("Effect relay handler error: " + ex.Message); } } } public static class SpawnRelay { private const string EventName = "TokControl_SpawnRelay_v1"; private static NetworkedEvent? _relayEvent; private static GameActions? _actions; public static void Initialize(GameActions actions) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected O, but got Unknown _actions = actions; _relayEvent = new NetworkedEvent("TokControl_SpawnRelay_v1", (Action)OnRelayReceived); ModLog.Info("Spawn relay initialized (client → host)"); } public static CommandResult ExecuteSpawn(string cmd, string name, int count, string user) { if (_actions == null) { return CommandResult.Fail("relay_not_ready"); } if (!MainThreadDispatcher.IsReady) { return CommandResult.Fail("game_not_ready"); } if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); int playerViewId = 0; try { playerViewId = (((Object)(object)val?.photonView != (Object)null) ? val.photonView.ViewID : 0); } catch { } if (SemiFunc.IsMasterClientOrSingleplayer() || !SemiFunc.IsMultiplayer()) { return ExecuteLocally(cmd, name, count, user, val); } return RelayToHost(cmd, name, count, user, playerViewId); } private static CommandResult RelayToHost(string cmd, string name, int count, string user, int playerViewId) { //IL_002a: Unknown result type (might be due to invalid IL or missing references) if (_relayEvent == null) { return CommandResult.Fail("relay_not_ready"); } try { string text = SimpleJson.SpawnPayload(cmd, name, count, user, playerViewId); _relayEvent.RaiseEvent((object)text, NetworkingEvents.RaiseMasterClient, SendOptions.SendReliable); ModLog.Info($"Relayed to host: {cmd} {name} x{count} for @{user} (view={playerViewId})"); return CommandResult.Ok("relayed_to_host", "Spawn sent to lobby host — host must have this mod installed"); } catch (Exception ex) { ModLog.Error("Relay failed: " + ex.Message); return CommandResult.Fail("relay_failed:" + ex.Message); } } private static void OnRelayReceived(EventData eventData) { if (_actions == null) { return; } if (!SemiFunc.IsMasterClientOrSingleplayer()) { ModLog.Debug("Relay received on non-host — ignored"); return; } try { string text = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(text)) { ModLog.Warn("Relay payload empty"); return; } if (!SimpleJson.TryParseSpawnPayload(text, out string cmd, out string name, out int count, out string user, out int playerViewId)) { ModLog.Warn("Relay payload invalid"); return; } ModLog.Info($"Host executing relay: {cmd} {name} x{count} for @{user} view={playerViewId}"); MainThreadDispatcher.Enqueue(delegate { PlayerAvatar targetPlayer = null; if (playerViewId > 0) { try { targetPlayer = SemiFunc.PlayerAvatarGetFromPhotonID(playerViewId); } catch { } } ExecuteLocally(cmd, name, count, user ?? "viewer", targetPlayer); }); } catch (Exception ex) { ModLog.Error("Relay handler error: " + ex.Message); } } private static CommandResult ExecuteLocally(string cmd, string name, int count, string user, PlayerAvatar? targetPlayer) { if (_actions == null) { return CommandResult.Fail("actions_not_ready"); } count = Math.Max(1, Math.Min(count, 100)); cmd = cmd.Trim().ToLowerInvariant(); EventContext.SetTarget(targetPlayer ?? SemiFunc.PlayerAvatarLocal()); try { switch (cmd) { case "spawn_item": case "spawnitem": case "item": return _actions.SpawnItemLocal(name, count, user); case "spawnghost": case "spawn_ghost": case "ghost": return _actions.SpawnEnemyLocal(name, count, user); case "spawnenemy": case "spawn_enemy": case "enemy": return _actions.SpawnEnemyLocal(name, count, user); case "spawn_valuable": case "spawnvaluable": case "valuable": return _actions.SpawnValuableLocal(name, count, user); case "spawnbatch": case "spawn_batch": case "batch": return _actions.SpawnBatchLocal(name, user); default: return CommandResult.Fail("unknown_spawn_cmd:" + cmd); } } finally { EventContext.Clear(); } } } internal static class SpeakBroadcast { private const string EventName = "TokControl_SpeakBroadcast_v1"; private static NetworkedEvent? _event; private static bool _handling; public static void Initialize() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown _event = new NetworkedEvent("TokControl_SpeakBroadcast_v1", (Action)OnReceived); ModLog.Info("Speak broadcast initialized"); } public static void Broadcast(string message) { if (!string.IsNullOrWhiteSpace(message)) { SpeakHelper.ForceSpeakNow(message); RaiseOthers(message); } } public static void RaiseOthers(string message) { //IL_0023: Unknown result type (might be due to invalid IL or missing references) if (string.IsNullOrWhiteSpace(message) || _event == null) { return; } try { if (SemiFunc.IsMultiplayer()) { _event.RaiseEvent((object)message, NetworkingEvents.RaiseOthers, SendOptions.SendReliable); } } catch (Exception ex) { ModLog.Debug("Speak broadcast failed: " + ex.Message); } } private static void OnReceived(EventData eventData) { if (_handling) { return; } string raw = eventData.CustomData as string; if (string.IsNullOrWhiteSpace(raw)) { return; } MainThreadDispatcher.Enqueue(delegate { _handling = true; try { SpeakHelper.ForceSpeakNow(raw); } finally { _handling = false; } }); } } public sealed class WebSocketServer : IDisposable { private readonly int _preferredPort; private readonly CommandProcessor _processor; private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private HttpListener? _listener; private Task? _acceptTask; public int Port { get; private set; } public WebSocketServer(int port, CommandProcessor processor) { _preferredPort = ((port > 0) ? port : 8080); Port = _preferredPort; _processor = processor; } public void Start() { int[] array = BuildPortCandidates(_preferredPort); Exception ex = null; int[] array2 = array; foreach (int num in array2) { HttpListener httpListener = null; try { httpListener = new HttpListener(); httpListener.Prefixes.Add($"http://127.0.0.1:{num}/"); httpListener.Start(); _listener = httpListener; Port = num; _acceptTask = Task.Run(() => AcceptLoopAsync(_cts.Token)); if (num != _preferredPort) { ModLog.Warn($"Port {_preferredPort} was busy — TokControl bridge moved to ws://127.0.0.1:{num}/"); ModLog.Warn($"Set TokControl Connection URL to: ws://127.0.0.1:{num}/"); } else { ModLog.Info($"HTTP/WebSocket listener started on port {num} (127.0.0.1 only)"); } return; } catch (Exception ex2) { ex = ex2; try { httpListener?.Close(); } catch { } ModLog.Warn($"Could not bind 127.0.0.1:{num} — {ex2.Message}"); } } throw new InvalidOperationException("TokControl bridge failed to bind any port (tried " + string.Join(", ", array) + "). Last error: " + ex?.Message); } private static int[] BuildPortCandidates(int preferred) { List list = new List { preferred }; int[] array = new int[5] { 8080, 8082, 8090, 18080, 28080 }; foreach (int item in array) { if (!list.Contains(item)) { list.Add(item); } } return list.ToArray(); } private async Task AcceptLoopAsync(CancellationToken ct) { while (!ct.IsCancellationRequested && _listener != null && _listener.IsListening) { HttpListenerContext context = null; try { context = await _listener.GetContextAsync().ConfigureAwait(continueOnCapturedContext: false); } catch (HttpListenerException) when (ct.IsCancellationRequested) { break; } catch (ObjectDisposedException) { break; } catch (Exception ex3) { ModLog.Warn("Accept error: " + ex3.Message); continue; } Task.Run(() => HandleContextAsync(context, ct), ct); } } private async Task HandleContextAsync(HttpListenerContext context, CancellationToken ct) { _ = 3; try { if (context.Request.IsWebSocketRequest) { await HandleWebSocketAsync((await context.AcceptWebSocketAsync(null).ConfigureAwait(continueOnCapturedContext: false)).WebSocket, ct).ConfigureAwait(continueOnCapturedContext: false); return; } string text = context.Request.Url?.AbsolutePath ?? "/"; string s; if (text.Equals("/health", StringComparison.OrdinalIgnoreCase)) { s = "{\"ok\":true,\"mod\":\"TokControl_REPO_Tiktoklive\",\"version\":\"1.3.91\",\"port\":" + Port + "}"; } else if (context.Request.HttpMethod == "POST") { using StreamReader reader = new StreamReader(context.Request.InputStream, context.Request.ContentEncoding); string raw = await reader.ReadToEndAsync().ConfigureAwait(continueOnCapturedContext: false); CommandResult commandResult = _processor.Process(raw); s = commandResult.ToJson(); } else { s = "{\"ok\":true,\"mod\":\"TokControl_REPO_Tiktoklive\",\"hint\":\"Connect via WebSocket ws://127.0.0.1:" + Port + "/\"}"; } byte[] bytes = Encoding.UTF8.GetBytes(s); context.Response.StatusCode = 200; context.Response.ContentType = "application/json"; context.Response.ContentLength64 = bytes.Length; await context.Response.OutputStream.WriteAsync(bytes, 0, bytes.Length, ct).ConfigureAwait(continueOnCapturedContext: false); context.Response.Close(); } catch (Exception ex) { ModLog.Warn("Request handler error: " + ex.Message); try { context.Response.StatusCode = 500; context.Response.Close(); } catch { } } } private async Task HandleWebSocketAsync(WebSocket socket, CancellationToken ct) { byte[] buffer = new byte[8192]; ModLog.Info("WebSocket client connected"); try { while (socket.State == WebSocketState.Open && !ct.IsCancellationRequested) { WebSocketReceiveResult webSocketReceiveResult = await socket.ReceiveAsync(new ArraySegment(buffer), ct).ConfigureAwait(continueOnCapturedContext: false); if (webSocketReceiveResult.MessageType == WebSocketMessageType.Close) { break; } if (webSocketReceiveResult.MessageType != WebSocketMessageType.Text) { continue; } string message = Encoding.UTF8.GetString(buffer, 0, webSocketReceiveResult.Count); Task.Run(delegate { try { CommandResult commandResult = _processor.Process(message); byte[] bytes = Encoding.UTF8.GetBytes(commandResult.ToJson()); socket.SendAsync(new ArraySegment(bytes), WebSocketMessageType.Text, endOfMessage: true, ct); } catch (Exception ex3) { ModLog.Warn("WS message error: " + ex3.Message); } }, ct); } } catch (WebSocketException ex) { ModLog.Debug("WebSocket closed: " + ex.Message); } catch (Exception ex2) { ModLog.Warn("WebSocket error: " + ex2.Message); } finally { ModLog.Info("WebSocket client disconnected"); try { if (socket.State == WebSocketState.Open || socket.State == WebSocketState.CloseReceived) { await socket.CloseAsync(WebSocketCloseStatus.NormalClosure, "bye", CancellationToken.None).ConfigureAwait(continueOnCapturedContext: false); } } catch { } socket.Dispose(); } } public void Dispose() { _cts.Cancel(); try { _listener?.Stop(); } catch { } try { _listener?.Close(); } catch { } _listener = null; _cts.Dispose(); } } } namespace TokControlREPOBridge.Logging { public static class ModLog { public static void Info(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogInfo((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.Log((object)Format(message)); } } public static void Warn(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogWarning((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.LogWarning((object)Format(message)); } } public static void Error(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogError((object)Format(message)); } if (Plugin.ShouldLogToUnity()) { Debug.LogError((object)Format(message)); } } public static void Debug(string message) { ManualLogSource log = Plugin.Log; if (log != null) { log.LogDebug((object)Format(message)); } } private static string Format(string message) { return "[TokControl] " + message; } } } namespace TokControlREPOBridge.Commands { internal static class ArenaHelper { public static bool IsPlayerInCrownArenaBeforeStart(PlayerAvatar player) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) Arena instance = Arena.instance; if ((Object)(object)instance == (Object)null || (Object)(object)player == (Object)null) { return false; } if (!IsBeforeCrownContestStart(instance)) { return false; } Vector3 arenaCenter = GetArenaCenter(instance); float num = Vector2.Distance(new Vector2(((Component)player).transform.position.x, ((Component)player).transform.position.z), new Vector2(arenaCenter.x, arenaCenter.z)); if (num < 18f) { return Mathf.Abs(((Component)player).transform.position.y - arenaCenter.y) < 10f; } return false; } public static bool IsContestMap() { if ((Object)(object)Arena.instance != (Object)null) { return true; } if ((Object)(object)ArenaRace.instance != (Object)null) { return true; } try { List list = FindSpawnPoints(); if (list.Count < 2) { return false; } List list2 = null; try { list2 = SemiFunc.LevelPointsGetAll(); } catch { } return list2 == null || list2.Count <= 8; } catch { return false; } } public static Vector3? GetContestTeleportPosition(Vector3 avoidNear, Vector3 playerForward) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_00b9: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ArenaRace.instance != (Object)null) { Vector3? farthestSpawnPosition = GetFarthestSpawnPosition(avoidNear, 64f); if (farthestSpawnPosition.HasValue) { return farthestSpawnPosition; } Vector3? raceStartPosition = GetRaceStartPosition(avoidNear); if (raceStartPosition.HasValue && FarEnough(raceStartPosition.Value, avoidNear, 64f)) { return raceStartPosition; } Vector3? farthestRaceTrackPosition = GetFarthestRaceTrackPosition(avoidNear, 64f); if (farthestRaceTrackPosition.HasValue) { return farthestRaceTrackPosition; } Vector3? backwardOnTrack = GetBackwardOnTrack(avoidNear, playerForward, 64f); if (backwardOnTrack.HasValue && FarEnough(backwardOnTrack.Value, avoidNear, 64f)) { return backwardOnTrack; } return OffsetFarBehind(avoidNear, playerForward); } if ((Object)(object)Arena.instance != (Object)null && (Object)(object)ArenaRace.instance == (Object)null) { Vector3? result = GetFarthestSpawnPosition(avoidNear, 64f) ?? GetRandomSpawnPosition(avoidNear); if (result.HasValue) { return result; } } return (GetFarthestRaceTrackPosition(avoidNear, 64f) ?? GetRandomRaceTrackPosition(avoidNear)) ?? GetFarthestSpawnPosition(avoidNear, 64f) ?? GetRandomSpawnPosition(avoidNear); } public static Vector3? GetContestTeleportPosition(Vector3 avoidNear) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetContestTeleportPosition(avoidNear, Vector3.back); } public static Vector3? GetRandomSpawnPosition(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) List list = (from p in FindSpawnPoints() select ((Component)p).transform.position).ToList(); if (list.Count == 0) { return CartHelper.GetRandomPlayerSpawnPoint(avoidNear); } List list2 = list.Where(delegate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val = pos - avoidNear; return ((Vector3)(ref val)).sqrMagnitude > 2.25f; }).ToList(); List list3 = ((list2.Count > 0) ? list2 : list); Vector3 position = list3[Random.Range(0, list3.Count)]; return KeepOnSurface(position, avoidNear); } private static Vector3? GetFarthestSpawnPosition(Vector3 avoidNear, float minSepSqr) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0143: Unknown result type (might be due to invalid IL or missing references) List list = (from p in FindSpawnPoints() select ((Component)p).transform.position).ToList(); if (list.Count == 0) { Vector3? randomPlayerSpawnPoint = CartHelper.GetRandomPlayerSpawnPoint(avoidNear); if (randomPlayerSpawnPoint.HasValue && FarEnough(randomPlayerSpawnPoint.Value, avoidNear, minSepSqr)) { return KeepOnSurface(randomPlayerSpawnPoint.Value, avoidNear); } return null; } List list2 = list.OrderByDescending((Vector3 pos) => HorizontalSqr(pos, avoidNear)).ToList(); foreach (Vector3 item in list2) { if (FarEnough(item, avoidNear, minSepSqr)) { ModLog.Info("Contest teleport: farthest spawn / race start"); return KeepOnSurface(item, avoidNear); } } if (list2.Count > 0 && FarEnough(list2[0], avoidNear, 4f)) { return KeepOnSurface(list2[0], avoidNear); } return null; } public static Vector3 GetCrownArenaDropPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Vector3? randomSpawnPosition = GetRandomSpawnPosition(Vector3.zero); if (randomSpawnPosition.HasValue) { return randomSpawnPosition.Value; } Arena instance = Arena.instance; if ((Object)(object)instance == (Object)null) { return Vector3.zero; } Vector3 val = (((Object)(object)instance.crownTransform != (Object)null) ? instance.crownTransform.position : (((Object)(object)instance.crownPlatform != (Object)null) ? instance.crownPlatform.transform.position : ((Component)instance).transform.position)); return KeepOnSurface(val + Vector3.up * 1.2f); } public static Vector3 KeepOnSurface(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) return KeepOnSurface(position, null); } public static Vector3 KeepOnSurface(Vector3 position, Vector3? ignoreNear) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position + Vector3.up * 8f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, 24f, -1, (QueryTriggerInteraction)1); if (array != null && array.Length != 0) { Array.Sort(array, (RaycastHit a, RaycastHit b) => ((RaycastHit)(ref a)).distance.CompareTo(((RaycastHit)(ref b)).distance)); RaycastHit[] array2 = array; for (int num = 0; num < array2.Length; num++) { RaycastHit val2 = array2[num]; if (!((Object)(object)((RaycastHit)(ref val2)).collider == (Object)null) && !(((RaycastHit)(ref val2)).normal.y < 0.35f) && (!ignoreNear.HasValue || !(HorizontalSqr(((RaycastHit)(ref val2)).point, ignoreNear.Value) < 16f)) && !LooksLikeVehicle(((RaycastHit)(ref val2)).collider)) { return ((RaycastHit)(ref val2)).point + Vector3.up * 0.35f; } } } return position + Vector3.up * 0.4f; } private static bool LooksLikeVehicle(Collider col) { Transform val = ((Component)col).transform; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("vehicle") || text.Contains("scooter") || text.Contains("cart") || text.Contains("car") || text.Contains("buggy") || text.Contains("truck")) { return true; } val = val.parent; } return false; } private static bool FarEnough(Vector3 a, Vector3 b, float minSepSqr) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return HorizontalSqr(a, b) >= minSepSqr; } private static float HorizontalSqr(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return num * num + num2 * num2; } private static Vector3? GetRaceStartPosition(Vector3 avoidNear) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) List list = FindSpawnPoints(); if (list.Count > 0) { return KeepOnSurface(((Component)list[0]).transform.position, avoidNear); } try { ArenaRace instance = ArenaRace.instance; if ((Object)(object)instance != (Object)null) { return KeepOnSurface(((Component)instance).transform.position + Vector3.up * 1.2f, avoidNear); } } catch { } return null; } private static Vector3? GetRaceStartPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetRaceStartPosition(Vector3.zero); } private static Vector3 OffsetFarBehind(Vector3 from, Vector3 forward) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_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_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_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.back; } ((Vector3)(ref forward)).Normalize(); Vector3 position = from - forward * Random.Range(28f, 42f) + Vector3.up * 1.2f; ModLog.Info("Contest teleport: far reverse offset"); return KeepOnSurface(position, from); } private static Vector3? GetBackwardOnTrack(Vector3 from, Vector3 forward, float minSepSqr) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0187: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_0189: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_009b: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_0117: Unknown result type (might be due to invalid IL or missing references) //IL_011c: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.back; } ((Vector3)(ref forward)).Normalize(); try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType(); if (array != null && array.Length != 0) { ArenaRaceTrackPiece val = null; float num = 1f; float num2 = 0f; ArenaRaceTrackPiece[] array2 = array; foreach (ArenaRaceTrackPiece val2 in array2) { if ((Object)(object)val2 == (Object)null || !((Behaviour)val2).isActiveAndEnabled) { continue; } Vector3 val3 = ((Component)val2).transform.position - from; val3.y = 0f; float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude; if (!(sqrMagnitude < minSepSqr)) { float num3 = Vector3.Dot(((Vector3)(ref val3)).normalized, forward); if (!(num3 >= num)) { num = num3; num2 = sqrMagnitude; val = val2; } } } if ((Object)(object)val != (Object)null && num < -0.05f && num2 >= minSepSqr) { Collider componentInChildren = ((Component)val).GetComponentInChildren(); Vector3 val4; if (!((Object)(object)componentInChildren != (Object)null)) { val4 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val4 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val4; ModLog.Info("Contest teleport: reverse track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, from); } } } catch (Exception ex) { ModLog.Debug("GetBackwardOnTrack failed: " + ex.Message); } return OffsetFarBehind(from, forward); } private static Vector3? GetFarthestRaceTrackPosition(Vector3 avoidNear, float minSepSqr) { //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return null; } ArenaRaceTrackPiece val = null; float num = -1f; ArenaRaceTrackPiece[] array2 = array; foreach (ArenaRaceTrackPiece val2 in array2) { if (!((Object)(object)val2 == (Object)null) && ((Behaviour)val2).isActiveAndEnabled) { float num2 = HorizontalSqr(((Component)val2).transform.position, avoidNear); if (!(num2 <= num)) { num = num2; val = val2; } } } if ((Object)(object)val == (Object)null || num < minSepSqr) { return null; } Collider componentInChildren = ((Component)val).GetComponentInChildren(); Vector3 val3; if (!((Object)(object)componentInChildren != (Object)null)) { val3 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val3 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val3; ModLog.Info("Contest teleport: farthest track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, avoidNear); } catch (Exception ex) { ModLog.Debug("GetFarthestRaceTrackPosition failed: " + ex.Message); return null; } } private static Vector3? GetRandomRaceTrackPosition(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00fb: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_012f: Unknown result type (might be due to invalid IL or missing references) try { ArenaRaceTrackPiece[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return null; } List list = array.Where((ArenaRaceTrackPiece p) => (Object)(object)p != (Object)null && ((Behaviour)p).isActiveAndEnabled).ToList(); if (list.Count == 0) { return null; } List list2 = list.Where((ArenaRaceTrackPiece p) => HorizontalSqr(((Component)p).transform.position, avoidNear) > 64f).ToList(); List list3 = ((list2.Count > 0) ? list2 : list); ArenaRaceTrackPiece val = list3[Random.Range(0, list3.Count)]; Collider componentInChildren = ((Component)val).GetComponentInChildren(); Vector3 val2; if (!((Object)(object)componentInChildren != (Object)null)) { val2 = ((Component)val).transform.position + Vector3.up * 1.5f; } else { Bounds bounds = componentInChildren.bounds; val2 = ((Bounds)(ref bounds)).center + Vector3.up * 1.15f; } Vector3 position = val2; ModLog.Info("Contest teleport: driving track piece '" + ((Object)val).name + "'"); return KeepOnSurface(position, avoidNear); } catch (Exception ex) { ModLog.Debug("GetRandomRaceTrackPosition failed: " + ex.Message); return null; } } private static List FindSpawnPoints() { SpawnPoint[] array = null; try { array = Object.FindObjectsOfType(true); } catch { array = Object.FindObjectsOfType(); } if (array != null) { return array.Where((SpawnPoint p) => (Object)(object)p != (Object)null).ToList(); } return new List(); } private static Vector3 GetArenaCenter(Arena arena) { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)arena.crownTransform != (Object)null) { return arena.crownTransform.position; } if ((Object)(object)arena.floorDoorTransform != (Object)null) { return arena.floorDoorTransform.position; } return ((Component)arena).transform.position; } private static bool IsBeforeCrownContestStart(Arena arena) { //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_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Invalid comparison between Unknown and I4 try { if (typeof(Arena).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(arena) is States val) { if ((int)val == 0 || (int)val == 5) { return true; } return false; } } catch { } return true; } } internal static class CartHelper { public static PhysGrabCart[] GetAllCarts() { return (from c in Object.FindObjectsOfType() where (Object)(object)c != (Object)null && ((Behaviour)c).isActiveAndEnabled select c).ToArray(); } public static List GetCartItemObjects(PhysGrabCart cart) { if (cart?.itemsInCart == null || cart.itemsInCart.Count == 0) { return new List(); } return cart.itemsInCart.Where((PhysGrabObject o) => (Object)(object)o != (Object)null).ToList(); } public static bool TeleportCart(PhysGrabCart cart, Vector3 targetPosition) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0050: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)cart == (Object)null) { return false; } Rigidbody rb = cart.rb; if ((Object)(object)rb == (Object)null) { return false; } float cartHeight = GetCartHeight(cart); Vector3 val = targetPosition + Vector3.up * cartHeight; Vector3 position = rb.position; rb.position = val; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; TeleportItemsInCart(cart, val, position); return true; } public static void TeleportItemsInCart(PhysGrabCart cart, Vector3 newPos, Vector3 oldPos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Vector3 val = newPos - oldPos; foreach (PhysGrabObject cartItemObject in GetCartItemObjects(cart)) { try { cartItemObject.Teleport(((Component)cartItemObject).transform.position + val, ((Component)cartItemObject).transform.rotation); } catch (Exception ex) { ModLog.Debug("Cart item teleport failed: " + ex.Message); } } } public static void ShakeItemsInAllCarts(float minForce, float maxForce, float minDelay, float maxDelay) { PhysGrabCart[] allCarts = GetAllCarts(); if (allCarts.Length != 0) { EffectTimerHost.Instance.RunRoutine(ShakeAllCartsRoutine(allCarts, minForce, maxForce, minDelay, maxDelay)); } } public static bool TeleportAllCarts(bool toStart) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) PhysGrabCart[] allCarts = GetAllCarts(); if (allCarts.Length == 0) { return false; } LevelPoint lastPoint = null; bool result = false; PhysGrabCart[] array = allCarts; foreach (PhysGrabCart cart in array) { Vector3? val = (toStart ? GetNextStartRoomPoint(ref lastPoint) : GetNextRandomMapPoint(ref lastPoint, excludePlayerRooms: true)); if (val.HasValue && TeleportCart(cart, val.Value)) { result = true; } } return result; } private static IEnumerator ShakeAllCartsRoutine(PhysGrabCart[] carts, float minForce, float maxForce, float minDelay, float maxDelay) { float num = Mathf.Max(0f, Mathf.Min(minDelay, maxDelay)); float num2 = Mathf.Max(num, Mathf.Max(minDelay, maxDelay)); if (num2 > 0.001f) { yield return (object)new WaitForSeconds(Random.Range(num, num2)); } else { yield return null; } foreach (PhysGrabCart val in carts) { if ((Object)(object)val == (Object)null) { continue; } foreach (PhysGrabObject cartItemObject in GetCartItemObjects(val)) { Rigidbody rb = cartItemObject.rb; if (!((Object)(object)rb == (Object)null)) { rb.isKinematic = false; rb.WakeUp(); float num3 = Random.Range(minForce, maxForce); rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; rb.AddForce(Vector3.up * num3, (ForceMode)1); CartItemScatterBehavior cartItemScatterBehavior = ((Component)cartItemObject).gameObject.GetComponent() ?? ((Component)cartItemObject).gameObject.AddComponent(); cartItemScatterBehavior.Begin(); } } } } private static float GetCartHeight(PhysGrabCart cart) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) Collider componentInParent = ((Component)cart).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return 1f; } Bounds bounds = componentInParent.bounds; return ((Bounds)(ref bounds)).size.y; } private static Vector3? GetNextStartRoomPoint(ref LevelPoint? lastPoint) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetInStartRoom(); if (list == null || list.Count == 0) { return GetPlayerSpawnPoint(); } lastPoint = PickNextPoint(list, lastPoint); LevelPoint? obj = lastPoint; return (obj != null) ? new Vector3?(((Component)obj).transform.position) : ((Vector3?)null); } catch (Exception ex) { ModLog.Debug("GetNextStartRoomPoint failed: " + ex.Message); return GetPlayerSpawnPoint(); } } private static Vector3? GetNextRandomMapPoint(ref LevelPoint? lastPoint, bool excludePlayerRooms) { //IL_0089: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { return null; } if (excludePlayerRooms) { List playerRooms = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List(); list = list.Where((LevelPoint p) => (Object)(object)p != (Object)null && !playerRooms.Contains(p)).ToList(); } if (list.Count == 0) { return null; } lastPoint = PickNextPoint(list, lastPoint); LevelPoint? obj = lastPoint; return (obj != null) ? new Vector3?(((Component)obj).transform.position) : ((Vector3?)null); } catch (Exception ex) { ModLog.Debug("GetNextRandomMapPoint failed: " + ex.Message); return null; } } private static LevelPoint PickNextPoint(IReadOnlyList points, LevelPoint? lastPoint) { if (points.Count == 1) { return points[0]; } int num = 0; LevelPoint val; do { val = points[Random.Range(0, points.Count)]; num++; } while ((Object)(object)val == (Object)(object)lastPoint && num < 8); return val; } private static Vector3? GetPlayerSpawnPoint() { //IL_0027: Unknown result type (might be due to invalid IL or missing references) SpawnPoint[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return null; } return ((Component)array[Random.Range(0, array.Length)]).transform.position; } public static Vector3? GetRandomPlayerSpawnPoint(Vector3 avoidNear) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) List list = (from p in Object.FindObjectsOfType() where (Object)(object)p != (Object)null select ((Component)p).transform.position).ToList(); if (list.Count == 0) { return SpawnHelper.TryGetStartRoomLevelPoint(0); } List list2 = list.OrderByDescending(delegate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_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) Vector3 val = pos - avoidNear; return ((Vector3)(ref val)).sqrMagnitude; }).ToList(); return list2[Random.Range(0, list2.Count)]; } } internal sealed class CartItemScatterBehavior : MonoBehaviour { private Rigidbody? _rb; private bool _airborne; private float _airTime; private bool _ceilingHitThisArc; private float _cooldown; public void Begin() { _rb = ((Component)this).GetComponentInChildren(); } private void FixedUpdate() { if ((Object)(object)_rb == (Object)null || ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } _cooldown -= Time.fixedDeltaTime; CheckCeilingHit(); if (!IsGrounded()) { _airborne = true; _airTime += Time.fixedDeltaTime; return; } if (_airborne && _airTime > 0.12f) { ApplyImpact(heavy: false); if (ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } } _airborne = false; _airTime = 0f; _ceilingHitThisArc = false; } private void CheckCeilingHit() { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rb == (Object)null) && !_ceilingHitThisArc && !(_rb.velocity.y < 0.8f)) { Vector3 val = ((Component)this).transform.position + Vector3.up * 0.15f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.up, ref val2, 1.4f, -5, (QueryTriggerInteraction)1) && !(((RaycastHit)(ref val2)).normal.y > -0.2f) && !(_cooldown > 0f)) { ApplyImpact(heavy: true); _ceilingHitThisArc = true; } } } private void ApplyImpact(bool heavy) { if (!(_cooldown > 0f)) { _cooldown = 0.18f; ValuableDamageHelper.ApplyImpactDamage(((Component)this).gameObject, 0.22f, heavy); } } private bool IsGrounded() { //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_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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)this).transform.position + Vector3.up * 0.1f; return Physics.Raycast(val, Vector3.down, 0.35f, -5, (QueryTriggerInteraction)1); } } internal sealed class ChompBookHuntBehavior : MonoBehaviour { private ChompBookTrap? _trap; private Transform? _player; private float _duration = 45f; private float _elapsed; private float _attackTimer = 0.15f; public void Configure(ChompBookTrap trap, float durationSeconds = 45f) { _trap = trap; _duration = Mathf.Max(12f, durationSeconds); PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _player = ((localPlayer != null) ? ((Component)localPlayer).transform : null); ForceTrapOn(); RefreshTarget(); TryAttack(); } private void FixedUpdate() { if ((Object)(object)_trap == (Object)null || ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { try { _trap.TrapStop(); } catch { } Object.Destroy((Object)(object)this); return; } ForceTrapOn(); RefreshTarget(); _attackTimer -= Time.fixedDeltaTime; if (_attackTimer <= 0f) { _attackTimer = 1.05f; TryAttack(); } } private void ForceTrapOn() { if (!((Object)(object)_trap == (Object)null)) { ((Trap)_trap).isLocal = true; ((Trap)_trap).trapStart = true; if (_trap.biteAmount < 8) { _trap.biteAmount = 12; } try { _trap.TrapActivate(); } catch { TryInvoke(_trap, "TrapActivate"); } Animator component = ((Component)_trap).GetComponent(); if ((Object)(object)component != (Object)null) { ((Behaviour)component).enabled = true; } } } private void RefreshTarget() { if ((Object)(object)_trap == (Object)null) { return; } if ((Object)(object)_player == (Object)null) { PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _player = ((localPlayer != null) ? ((Component)localPlayer).transform : null); } if ((Object)(object)_player == (Object)null) { return; } try { typeof(ChompBookTrap).GetField("targetTransform", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(_trap, _player); } catch { } } private void TryAttack() { if ((Object)(object)_trap == (Object)null) { return; } try { _trap.Attack(); } catch (Exception ex) { ModLog.Debug("Chomp Book Attack: " + ex.Message); } } private static void TryInvoke(object target, string methodName) { try { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 0) { method.Invoke(target, null); } } catch { } } } public sealed class CommandProcessor { private readonly string _defaultGhostEnemy; private readonly GameActions _actions = new GameActions(); internal GameActions Actions => _actions; public CommandProcessor(string defaultGhostEnemy) { _defaultGhostEnemy = (string.IsNullOrWhiteSpace(defaultGhostEnemy) ? "Hidden" : defaultGhostEnemy.Trim()); } public CommandResult Process(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return CommandResult.Fail("empty_message"); } raw = raw.Trim(); if (!raw.StartsWith("{", StringComparison.Ordinal)) { return ProcessPlainText(raw); } try { return ProcessJson(raw); } catch (Exception ex) { ModLog.Error("Command parse error: " + ex.Message); return CommandResult.Fail(ex.Message); } } private CommandResult ProcessJson(string json) { string text = SimpleJson.GetString(json, "cmd") ?? SimpleJson.GetString(json, "command") ?? SimpleJson.GetString(json, "action") ?? ""; text = text.Trim().ToLowerInvariant(); string text2 = SimpleJson.GetString(json, "eventId") ?? SimpleJson.GetString(json, "event"); string name = SimpleJson.GetString(json, "name") ?? SimpleJson.GetString(json, "item") ?? SimpleJson.GetString(json, "enemy") ?? SimpleJson.GetString(json, "gift") ?? ""; int count = SimpleJson.GetInt(json, "count") ?? SimpleJson.GetInt(json, "amount") ?? 1; string user = SimpleJson.GetString(json, "user") ?? SimpleJson.GetString(json, "uniqueId") ?? "viewer"; string speakText = SimpleJson.GetString(json, "text") ?? SimpleJson.GetString(json, "message") ?? ""; string namedPlayer = SimpleJson.GetString(json, "targetPlayer") ?? SimpleJson.GetString(json, "namedPlayer") ?? SimpleJson.GetString(json, "player"); if (string.IsNullOrEmpty(text)) { string text3 = SimpleJson.GetString(json, "command"); if (!string.IsNullOrEmpty(text3)) { return ProcessPlainText(text3); } } if (!string.IsNullOrEmpty(text2) && (string.IsNullOrEmpty(text) || text == "event")) { return Dispatch(text2.Trim().ToLowerInvariant(), "", count, user, speakText, namedPlayer); } return Dispatch(text, name, count, user, speakText, namedPlayer); } private CommandResult ProcessPlainText(string text) { string[] array = text.Split('|'); if (array.Length >= 2) { string text2 = array[0].Trim().ToLowerInvariant(); string text3 = ((array.Length > 1) ? array[1].Trim() : ""); int result; int count = ((array.Length <= 2 || !int.TryParse(array[2], out result)) ? 1 : result); bool flag; switch (text2) { case "speak": case "say": case "tts": case "chat": flag = true; break; default: flag = false; break; } string speakText = (flag ? text3 : ""); return Dispatch(text2, text3, count, "viewer", speakText); } string[] array2 = text.Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array2.Length == 0) { return CommandResult.Fail("empty_command"); } string cmd = array2[0].ToLowerInvariant(); string name = ((array2.Length > 1) ? array2[1] : ""); int result2; int count2 = ((array2.Length <= 2 || !int.TryParse(array2[2], out result2)) ? 1 : result2); return Dispatch(cmd, name, count2, "viewer"); } private CommandResult Dispatch(string cmd, string name, int count, string user, string speakText = "", string? namedPlayer = null) { count = Math.Max(1, Math.Min(count, 100)); switch (cmd) { case "ping": case "health": return CommandResult.Ok("pong", "Server alive"); case "chat": case "speak": case "say": case "tts": { string message2 = ((!string.IsNullOrWhiteSpace(speakText)) ? speakText : name); return EnqueueFireAndForget(() => SpeakHelper.TrySpeak(message2, user), "speak"); } case "roll": case "hud": case "announce": case "mission": { string message = ((!string.IsNullOrWhiteSpace(speakText)) ? speakText : name); if (string.IsNullOrWhiteSpace(message)) { return CommandResult.Fail("announce requires text"); } return EnqueueFireAndForget(delegate { GameNotifier.AnnounceCustom(user, message); return CommandResult.Ok("announced", message); }, "announce"); } case "item": case "spawn_item": case "spawnitem": if (string.IsNullOrWhiteSpace(name)) { return CommandResult.Fail("spawn_item requires a name"); } return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn(cmd, name, count, user), "spawn_item:" + name); case "ghost": case "spawnghost": case "spawn_ghost": { string enemy = (string.IsNullOrWhiteSpace(name) ? _defaultGhostEnemy : name); if (SpawnBlocklist.IsBlockedEnemy(enemy)) { ModLog.Warn("Enemy spawn temporarily disabled: " + enemy); return CommandResult.Fail("spawn_disabled_temp"); } return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn(cmd, enemy, count, user), "spawn_ghost:" + enemy); } case "enemy": case "spawnenemy": case "spawn_enemy": if (string.IsNullOrWhiteSpace(name)) { return CommandResult.Fail("spawn_enemy requires a name"); } if (SpawnBlocklist.IsBlockedEnemy(name)) { ModLog.Warn("Enemy spawn temporarily disabled: " + name); return CommandResult.Fail("spawn_disabled_temp"); } return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn(cmd, name, count, user), "spawn_enemy:" + name); case "spawn_batch": return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn("spawn_batch", name, 1, user), "spawn_batch"); case "valuable": case "spawn_valuable": case "spawnvaluable": if (string.IsNullOrWhiteSpace(name)) { return CommandResult.Fail("spawn_valuable requires a name"); } return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn(cmd, name, count, user), "spawn_valuable:" + name); case "list_items": return RunOnMainThreadWait(() => _actions.ListItems()); case "list_enemies": return RunOnMainThreadWait(() => _actions.ListEnemies()); case "roster": case "list_player": case "list_players": return RunOnMainThreadWait(delegate { List source = PlayerTargeting.AliveRosterNames(); string detail = "[" + string.Join(",", source.Select((string n) => "\"" + SimpleJson.Escape(n) + "\"")) + "]"; return CommandResult.Ok("list_players", detail); }); case "kill_named": case "explode_named_player": case "destruct_player": case "all_debuff_kill_named": case "solo_debuff_kill_named": { string who = ((!string.IsNullOrWhiteSpace(namedPlayer)) ? namedPlayer : name); return EnqueueFireAndForget(() => StreamEventRunner.Execute("all_debuff_kill_named", user, count, null, who), "explode_named_player"); } default: { if (SpawnBlocklist.IsBlockedEventId(cmd)) { ModLog.Warn("Event temporarily disabled: " + cmd); return CommandResult.Fail("spawn_disabled_temp"); } if (EventCommandCatalog.HasEvent(cmd)) { return EnqueueFireAndForget(() => StreamEventRunner.Execute(cmd, user, count, null, namedPlayer), cmd); } if (RepoEventResolver.TryResolve(cmd, out string eventCmd, out string eventTarget)) { if (SpawnBlocklist.IsBlockedEnemy(eventTarget)) { ModLog.Warn("Enemy spawn temporarily disabled: " + eventTarget + " (" + cmd + ")"); return CommandResult.Fail("spawn_disabled_temp"); } return EnqueueFireAndForget(() => SpawnRelay.ExecuteSpawn(eventCmd, eventTarget, count, user), cmd); } ModLog.Warn("Unknown command: " + cmd); return CommandResult.Fail("unknown_command:" + cmd); } } } private static CommandResult EnqueueFireAndForget(Func action, string label) { if (!MainThreadDispatcher.IsReady) { return CommandResult.Fail("game_not_ready"); } MainThreadDispatcher.Enqueue(delegate { try { CommandResult commandResult = action(); if (!commandResult.Success) { ModLog.Warn("Queued cmd failed (" + label + "): " + commandResult.Message); } } catch (Exception ex) { ModLog.Error("Queued cmd error (" + label + "): " + ex.Message); } }); return CommandResult.Ok("queued", label); } private static CommandResult RunOnMainThreadWait(Func action) { if (!MainThreadDispatcher.IsReady) { return CommandResult.Fail("game_not_ready"); } CommandResult result = null; ManualResetEventSlim wait = new ManualResetEventSlim(initialState: false); MainThreadDispatcher.Enqueue(delegate { try { result = action(); } catch (Exception ex) { result = CommandResult.Fail(ex.Message); } finally { wait.Set(); } }); if (!wait.Wait(TimeSpan.FromSeconds(10.0))) { return CommandResult.Fail("main_thread_timeout"); } return result ?? CommandResult.Fail("no_result"); } private static bool IsEffectEvent(string cmd) { if (string.IsNullOrWhiteSpace(cmd)) { return false; } cmd = cmd.Trim().ToLowerInvariant(); while (cmd.StartsWith("repo_", StringComparison.Ordinal)) { cmd = cmd.Substring(5); } if (!cmd.StartsWith("all_debuff_", StringComparison.Ordinal) && !cmd.StartsWith("solo_debuff_", StringComparison.Ordinal) && !cmd.StartsWith("all_buff_", StringComparison.Ordinal)) { return cmd.StartsWith("solo_buff_", StringComparison.Ordinal); } return true; } } public sealed class CommandResult { public bool Success { get; init; } public string Message { get; init; } = ""; public string? Detail { get; init; } public static CommandResult Ok(string message, string? detail = null) { return new CommandResult { Success = true, Message = message, Detail = detail }; } public static CommandResult Fail(string message) { return new CommandResult { Success = false, Message = message }; } public string ToJson() { return SimpleJson.CommandResult(Success, Message, Detail); } } [HarmonyPatch] internal static class InputManagerCrouchHoldBoolPatch { private static List _methods = new List(); private static bool Prepare() { _methods = Collect("bool"); return _methods.Count > 0; } private static IEnumerable TargetMethods() { return _methods; } private static void Postfix(InputKey __0, ref bool __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if (PlayerEffectHelper.ForceCrouchHeld && (int)__0 == 12) { __result = true; } } internal static List Collect(string kind) { List list = new List(); MethodInfo[] methods = typeof(InputManager).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if ((!(kind == "bool") || !(methodInfo.ReturnType != typeof(bool))) && (!(kind == "float") || !(methodInfo.ReturnType != typeof(float))) && HasLeadingInputKey(methodInfo) && LooksLikeRead(methodInfo.Name)) { list.Add(methodInfo); } } return list; } internal static bool HasLeadingInputKey(MethodBase method) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length >= 1) { return parameters[0].ParameterType == typeof(InputKey); } return false; } internal static bool LooksLikeRead(string name) { if (string.IsNullOrEmpty(name)) { return false; } if (name.IndexOf("Disable", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (name.IndexOf("Except", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (name.IndexOf("Set", StringComparison.OrdinalIgnoreCase) >= 0) { return false; } if (name.IndexOf("Get", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Input", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Press", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Hold", StringComparison.OrdinalIgnoreCase) < 0 && name.IndexOf("Key", StringComparison.OrdinalIgnoreCase) < 0) { return name.IndexOf("Button", StringComparison.OrdinalIgnoreCase) >= 0; } return true; } } [HarmonyPatch] internal static class InputManagerCrouchHoldFloatPatch { private static List _methods = new List(); private static bool Prepare() { _methods = InputManagerCrouchHoldBoolPatch.Collect("float"); return _methods.Count > 0; } private static IEnumerable TargetMethods() { return _methods; } private static void Postfix(InputKey __0, ref float __result) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Invalid comparison between Unknown and I4 if (PlayerEffectHelper.ForceCrouchHeld && (int)__0 == 12) { __result = 1f; } } } internal sealed class DirectorEnemyDeathGuard : MonoBehaviour { private const float SpawnGraceSeconds = 2.5f; private EnemyParent? _parent; private Enemy? _enemy; private float _graceTimer; private float _checkTimer; private bool _wasAlive; private bool _handled; private bool _logged; private static readonly HashSet BlockSpawnIds = new HashSet(); public void Configure(EnemyParent parent, Enemy enemy) { _parent = parent; _enemy = enemy; _graceTimer = 2.5f; _wasAlive = false; _handled = false; _logged = false; } private void Update() { if ((Object)(object)_parent == (Object)null) { return; } if (_graceTimer > 0f) { _graceTimer -= Time.deltaTime; if (IsEnemyPresent(_enemy, _parent) && !IsHealthDead(_enemy)) { _wasAlive = true; } return; } if (IsEnemyPresent(_enemy, _parent) && !IsHealthDead(_enemy)) { _wasAlive = true; } if (IsHealthDead(_enemy) && _wasAlive) { PreventRespawn(_parent); if (!_logged) { _logged = true; ModLog.Info("TokControl enemy death confirmed — blocking auto-respawn"); } _checkTimer += Time.deltaTime; if (!_handled && !(_checkTimer < 2f)) { _handled = true; } } } internal static void PreventRespawn(EnemyParent? parent) { if ((Object)(object)parent == (Object)null) { return; } BlockSpawnIds.Add(((Object)parent).GetInstanceID()); try { parent.DespawnedTimerSet(999999f, false); } catch { } try { parent.DespawnedTimerSet(999999f, true); } catch { } } internal static bool ShouldBlockSpawn(EnemyParent? parent) { if ((Object)(object)parent == (Object)null) { return false; } if (BlockSpawnIds.Contains(((Object)parent).GetInstanceID())) { return true; } return IsHealthDead(parent.Enemy); } internal static void Clear() { BlockSpawnIds.Clear(); } private static bool IsHealthDead(Enemy? enemy) { try { return (Object)(object)enemy != (Object)null && enemy.HasHealth && (Object)(object)enemy.Health != (Object)null && enemy.Health.dead; } catch { return false; } } private static bool IsEnemyPresent(Enemy? enemy, EnemyParent? parent) { if ((Object)(object)enemy == (Object)null || (Object)(object)parent == (Object)null) { return false; } if (!((Component)parent).gameObject.activeInHierarchy) { return false; } if (!((Component)enemy).gameObject.activeInHierarchy) { return false; } if (ReadBool(enemy, "isDead") || ReadBool(enemy, "dead")) { return false; } return true; } private static bool ReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } } catch { } return false; } } internal static class DropGroupCatalog { private static Dictionary? _simpleGroups; private static Dictionary>? _variantGroups; private static bool _loaded; public static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; _simpleGroups = new Dictionary(StringComparer.OrdinalIgnoreCase); _variantGroups = new Dictionary>(StringComparer.OrdinalIgnoreCase); try { string text = ResolveDataPath("drop_simple_groups.data"); if (text != null && File.Exists(text)) { ParseSimpleGroups(File.ReadAllText(text)); ModLog.Info($"Loaded {_simpleGroups.Count} simple drop groups from {text}"); } else { ModLog.Warn("drop_simple_groups.data not found — seeding fallbacks"); SeedFallbackGroups(); } } catch (Exception ex) { ModLog.Warn("Simple drop load failed: " + ex.Message); SeedFallbackGroups(); } try { string text2 = ResolveDataPath("drop_groups.data"); if (text2 != null && File.Exists(text2)) { ParseVariantGroups(File.ReadAllText(text2)); ModLog.Info($"Loaded {_variantGroups.Count} variant drop groups from {text2}"); } } catch (Exception ex2) { ModLog.Warn("Variant drop load failed: " + ex2.Message); } } public static bool IsSimpleGroup(string name) { EnsureLoaded(); if (!string.IsNullOrWhiteSpace(name)) { return _simpleGroups.ContainsKey(name.Trim()); } return false; } public static string? PickRandom(string groupName) { EnsureLoaded(); if (string.IsNullOrWhiteSpace(groupName)) { return null; } if (!_simpleGroups.TryGetValue(groupName.Trim(), out string[] value) || value == null || value.Length == 0) { return null; } return ParseItemPath(value[Random.Range(0, value.Length)]); } public static string[] PickRandomVariantItems(string groupName) { EnsureLoaded(); if (string.IsNullOrWhiteSpace(groupName)) { return Array.Empty(); } if (!_variantGroups.TryGetValue(groupName.Trim(), out List value) || value == null || value.Count == 0) { return Array.Empty(); } string[] array = value[Random.Range(0, value.Count)]; List list = new List(); string[] array2 = array; foreach (string raw in array2) { string text = ParseItemPath(raw); if (!string.IsNullOrEmpty(text)) { list.Add(text); } } return list.ToArray(); } public static string GroupForLootEvent(string eventId) { string text = (eventId ?? "").Trim().ToLowerInvariant(); if (text.Contains("huge")) { return "group_loot_rand_huge"; } if (text.Contains("enemy")) { return "group_loot_rand_enemy"; } if (text.Contains("big")) { return "group_loot_rand_big"; } if (text.Contains("med") || text.Contains("medium")) { return "group_loot_rand_med"; } return "group_loot_rand_small"; } public static string ParseItemPath(string raw) { if (string.IsNullOrWhiteSpace(raw)) { return ""; } string text = raw.Trim().Replace('\\', '/'); int num = text.LastIndexOf('/'); if (num >= 0 && num < text.Length - 1) { text = text.Substring(num + 1); } return text.Trim(); } private static string? ResolveDataPath(string fileName) { try { string location = Assembly.GetExecutingAssembly().Location; if (!string.IsNullOrEmpty(location)) { string directoryName = Path.GetDirectoryName(location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, fileName); if (File.Exists(text)) { return text; } string text2 = Path.Combine(directoryName, "Data", fileName); if (File.Exists(text2)) { return text2; } } } } catch { } try { string text3 = Path.Combine(PathsSafe(), "TokControlREPOBridge", "Data", fileName); if (File.Exists(text3)) { return text3; } } catch { } return null; } private static string PathsSafe() { try { return Paths.PluginPath; } catch { return "."; } } private static void ParseSimpleGroups(string json) { int num = 0; while (num < json.Length) { int num2 = json.IndexOf('"', num); if (num2 < 0) { break; } int num3 = json.IndexOf('"', num2 + 1); if (num3 < 0) { break; } string text = json.Substring(num2 + 1, num3 - num2 - 1); int num4 = json.IndexOf('[', num3); if (num4 < 0) { break; } int num5 = json.IndexOf(']', num4); if (num5 < 0) { break; } if (text.StartsWith("group_", StringComparison.OrdinalIgnoreCase) && !json.Substring(num3, Math.Min(40, num4 - num3)).Contains("drop_variants")) { string text2 = json.Substring(num3 + 1, num4 - num3 - 1).Trim(); if (text2.StartsWith(":")) { string body = json.Substring(num4 + 1, num5 - num4 - 1); List list = ExtractQuotedStrings(body); if (list.Count > 0) { _simpleGroups[text] = list.ToArray(); } } } num = num5 + 1; } } private static void ParseVariantGroups(string json) { foreach (Match item in Regex.Matches(json, "\"(group_[^\"]+)\"\\s*:\\s*\\{\\s*\"drop_variants\"\\s*:\\s*\\[(.*?)\\]\\s*\\}", RegexOptions.IgnoreCase | RegexOptions.Singleline)) { string value = item.Groups[1].Value; string value2 = item.Groups[2].Value; List list = new List(); foreach (Match item2 in Regex.Matches(value2, "\"items\"\\s*:\\s*\\[(.*?)\\]", RegexOptions.IgnoreCase | RegexOptions.Singleline)) { List list2 = ExtractQuotedStrings(item2.Groups[1].Value); if (list2.Count > 0) { list.Add(list2.ToArray()); } } if (list.Count > 0) { _variantGroups[value] = list; } } } private static List ExtractQuotedStrings(string body) { List list = new List(); int num = 0; while (num < body.Length) { int num2 = body.IndexOf('"', num); if (num2 < 0) { break; } int num3 = body.IndexOf('"', num2 + 1); if (num3 < 0) { break; } string text = body.Substring(num2 + 1, num3 - num2 - 1).Trim(); if (text.Length > 0 && !text.Equals("items", StringComparison.OrdinalIgnoreCase) && !text.Equals("drop_variants", StringComparison.OrdinalIgnoreCase)) { list.Add(text); } num = num3 + 1; } return list; } private static void SeedFallbackGroups() { _simpleGroups["group_loot_rand_small"] = new string[3] { "Valuable_Wizard_Diamond", "Valuable_Manor_Goblet", "Valuable_Arctic_Eraser" }; _simpleGroups["group_loot_rand_med"] = new string[3] { "Valuable_Manor_Radio", "Valuable_Manor_Trophy", "Valuable_Wizard_Crystal" }; _simpleGroups["group_loot_rand_big"] = new string[2] { "Valuable_Manor_Vase_Big", "Valuable_Wizard_Master_Potion" }; _simpleGroups["group_loot_rand_huge"] = new string[2] { "Valuable_Arctic_Cryo_Pod", "Valuable_Wizard_Alchemy_Station" }; _simpleGroups["group_loot_rand_enemy"] = new string[3] { "Enemy_Valuable_-_Small", "Enemy_Valuable_-_Medium", "Enemy_Valuable_-_Big" }; _simpleGroups["group_item_rand_nades"] = new string[3] { "Item_Grenade_Stun", "Item_Grenade_Shockwave", "Item_Grenade_Explosive" }; } } public sealed class GameActions { private const int GrenadeWaveSize = 5; private static int _grenadeScatterSeq; private static readonly Dictionary> UpgradeHandlers = new Dictionary>(StringComparer.OrdinalIgnoreCase) { ["solo_upgrade_energy"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerEnergy(id, d); }, ["solo_upgrade_health"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerHealth(id, d); }, ["solo_upgrade_speed"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerSprintSpeed(id, d); }, ["solo_upgrade_range"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerGrabRange(id, d); }, ["solo_upgrade_strength"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerGrabStrength(id, d); }, ["solo_upgrade_jump"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerExtraJump(id, d); }, ["solo_upgrade_roll"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerTumbleLaunch(id, d); }, ["solo_upgrade_wings"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerTumbleWings(id, d); }, ["solo_upgrade_rest"] = delegate(string id, int d) { PunManager.instance.UpgradePlayerCrouchRest(id, d); } }; internal CommandResult SpawnActiveGrenade(string kind, int count, string user) { if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } kind = (kind ?? "").Trim().ToLowerInvariant(); count = Math.Max(1, Math.Min(count, 100)); EffectTimerHost.Instance.RunRoutine(SpawnActiveGrenadeRoutine(kind, count, user ?? "viewer", EventContext.SoloTarget())); return CommandResult.Ok("active_nade_queued", kind); } private IEnumerator SpawnActiveGrenadeRoutine(string kind, int count, string user, PlayerAvatar? subject) { int spawned = 0; string itemLabel = null; int remaining = count; while (remaining > 0) { EventContext.SetTarget(subject); int batch = Math.Min(5, remaining); for (int i = 0; i < batch; i++) { int scatterIndex = Interlocked.Increment(ref _grenadeScatterSeq) - 1; if (TrySpawnOneActiveGrenade(kind, scatterIndex, out string itemLabel2)) { itemLabel = itemLabel2; spawned++; } yield return null; } remaining -= batch; if (remaining > 0) { yield return (object)new WaitForSeconds(0.08f); } } if (spawned == 0) { ModLog.Warn("active_nade_" + kind + ": item spawn failed"); yield break; } ModLog.Info($"active_nade '{kind}' x{spawned} for @{user} (item={itemLabel})"); GameNotifier.AnnounceEvent(user, "active_nade_" + kind); } private bool TrySpawnOneActiveGrenade(string kind, int scatterIndex, out string? itemLabel) { //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_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) itemLabel = kind; Vector3 grenadeSpreadPosition = SpawnHelper.GetGrenadeSpreadPosition(scatterIndex); GameObject val = null; switch (kind) { case "duck": val = TrySpawnActiveItem(grenadeSpreadPosition, GetDuckSearchTerms(), out itemLabel, scatterIndex); if ((Object)(object)val != (Object)null) { val.transform.position = grenadeSpreadPosition; ThrowableHelper.ApplyStrongBounce(val, 30f); } break; case "stun": case "shock": case "expl": val = TrySpawnActiveItem(grenadeSpreadPosition, GetGrenadeSearchTerms(kind), out itemLabel, scatterIndex, armGrenade: true); if ((Object)(object)val != (Object)null) { val.transform.position = grenadeSpreadPosition; ThrowableHelper.ArmWithFuse(val, 3f, immediate: true); } break; default: return false; } return (Object)(object)val != (Object)null; } private static string[] GetDuckSearchTerms() { return ExpandActiveItemTerms("active_nade_duck", "Item_Rubber_Duck"); } private static string[] GetGrenadeSearchTerms(string kind) { return ExpandActiveItemTerms(kind switch { "stun" => "active_nade_stun", "shock" => "active_nade_shock", "expl" => "active_nade_expl", _ => "", }, kind switch { "stun" => "Item_Grenade_Stun", "shock" => "Item_Grenade_Shockwave", "expl" => "Item_Grenade_Explosive", _ => kind, }); } private static string[] ExpandActiveItemTerms(string eventId, string fallback) { if (RepoEventMap.TryGetActiveItem(eventId, out string itemId)) { return RepoEventMap.ExpandItemSearchIds(itemId).Distinct().ToArray(); } return RepoEventMap.ExpandItemSearchIds(fallback).Distinct().ToArray(); } private GameObject? TrySpawnActiveItem(Vector3 pos, string[] searchTerms, out string itemLabel, int scatterIndex, bool armGrenade = false) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) itemLabel = searchTerms[0]; foreach (string text in searchTerms) { string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn(text, pos, Quaternion.identity, out spawnedLabel, scatterIndex, holdInPlace: true, armGrenade); if (!((Object)(object)val == (Object)null)) { itemLabel = spawnedLabel ?? text; return val; } } return null; } internal CommandResult SpawnItemLocal(string itemName, int count, string user) { //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0046: 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_0068: Unknown result type (might be due to invalid IL or missing references) if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (RepoEventMap.TryGetItemInternalName(itemName, out string itemId)) { itemName = itemId; } SpawnHelper.GetItemOffsetForName(itemName, out var length, out var height); int num = 0; string text = null; for (int i = 0; i < count; i++) { Vector3 itemSpawnPosition = SpawnHelper.GetItemSpawnPosition(length, height, i); Quaternion identity = Quaternion.identity; string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn(itemName, itemSpawnPosition, identity, out spawnedLabel, i, holdInPlace: true); if (!((Object)(object)val == (Object)null)) { val.transform.position = itemSpawnPosition; text = spawnedLabel ?? itemName; num++; } } if (num == 0) { ModLog.Warn("Item not found: " + itemName); return CommandResult.Fail("item_not_found:" + itemName); } ModLog.Info($"spawn_item '{text}' x{count} for @{user} (spawned {num})"); GameNotifier.AnnounceSpawn(user, text ?? itemName, num, "item"); return CommandResult.Ok("spawned_item:" + text, $"count={num}"); } internal CommandResult SpawnEnemyLocal(string enemyName, int count, string user) { //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (SpawnBlocklist.IsBlockedEnemy(enemyName)) { ModLog.Warn("Enemy spawn temporarily disabled: " + enemyName); return CommandResult.Fail("spawn_disabled_temp"); } enemyName = EnemyRegistry.ResolveInternalName(enemyName); if (SpawnBlocklist.IsBlockedEnemy(enemyName)) { ModLog.Warn("Enemy spawn temporarily disabled: " + enemyName); return CommandResult.Fail("spawn_disabled_temp"); } int num = 0; string text = null; for (int i = 0; i < count; i++) { Vector3 enemySpawnPosition = SpawnHelper.GetEnemySpawnPosition(i); if (EnemySpawnHelper.TrySpawn(enemyName, enemySpawnPosition, out string spawnedName)) { text = spawnedName ?? enemyName; num++; } } if (num == 0) { bool flag = false; try { flag = SemiFunc.MenuLevel(); } catch { } if (flag && (Object)(object)RunManager.instance == (Object)null) { ModLog.Warn("Enemy spawn blocked in menu: " + enemyName); return CommandResult.Fail("game_not_ready"); } ModLog.Warn("Enemy not found: " + enemyName); return CommandResult.Fail("enemy_not_found:" + enemyName); } ModLog.Info($"spawn_enemy '{text}' x{num} for @{user}"); GameNotifier.AnnounceSpawn(user, text ?? enemyName, num, "enemy"); return CommandResult.Ok("spawned_enemy:" + text, $"count={num}"); } internal CommandResult SpawnBatchLocal(string batchSpec, string user) { if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (string.IsNullOrWhiteSpace(batchSpec)) { return CommandResult.Fail("spawn_batch_empty"); } int num = 0; int num2 = 0; string[] array = batchSpec.Split(new char[1] { ';' }, StringSplitOptions.RemoveEmptyEntries); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length == 0) { continue; } int num3 = text2.LastIndexOf(':'); string eventId = ((num3 > 0) ? text2.Substring(0, num3).Trim() : text2); int num4 = 1; if (num3 > 0 && int.TryParse(text2.Substring(num3 + 1), out var result)) { num4 = Math.Max(1, result); } if (!RepoEventResolver.TryResolve(eventId, out string spawnCmd, out string targetName)) { num2++; continue; } bool flag = SpawnBlocklist.IsBlockedEventId(eventId); bool flag2 = flag; if (!flag2) { bool flag3 = ((spawnCmd == "spawn_ghost" || spawnCmd == "spawn_enemy") ? true : false); flag2 = flag3 && SpawnBlocklist.IsBlockedEnemy(targetName); } if (flag2) { num2++; continue; } CommandResult commandResult; if ((spawnCmd == "spawn_ghost" || spawnCmd == "spawn_enemy") ? true : false) { commandResult = SpawnEnemyLocal(targetName, num4, user); } else if (spawnCmd == "spawn_item") { commandResult = SpawnItemLocal(targetName, num4, user); } else { if (!(spawnCmd == "spawn_valuable")) { num2++; continue; } commandResult = SpawnValuableLocal(targetName, num4, user); } if (commandResult.Success) { num += num4; } else { num2++; } } if (num == 0) { return CommandResult.Fail("spawn_batch_failed"); } ModLog.Info($"spawn_batch for @{user}: spawned={num}, failed={num2}"); return CommandResult.Ok("spawn_batch", $"spawned={num},failed={num2}"); } internal CommandResult SpawnValuableLocal(string valuableName, int count, string user) { //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (DropGroupCatalog.IsSimpleGroup(valuableName) || valuableName.StartsWith("group_", StringComparison.OrdinalIgnoreCase)) { string text = DropGroupCatalog.PickRandom(valuableName); if (string.IsNullOrEmpty(text)) { return CommandResult.Fail("drop_group_empty:" + valuableName); } valuableName = text; } int num = 0; string text2 = null; for (int i = 0; i < count; i++) { Vector3 valuableSpawnPosition = SpawnHelper.GetValuableSpawnPosition(i); if (ValuableSpawnHelper.TrySpawn(valuableName, valuableSpawnPosition, Quaternion.identity, out string spawnedLabel)) { text2 = spawnedLabel ?? valuableName; num++; } } if (num == 0) { ModLog.Warn("Valuable not found: " + valuableName); return CommandResult.Fail("valuable_not_found:" + valuableName); } ModLog.Info($"spawn_valuable '{text2}' x{num} for @{user}"); GameNotifier.AnnounceSpawn(user, text2 ?? valuableName, num, "loot"); return CommandResult.Ok("spawned_valuable:" + text2, $"count={num}"); } public CommandResult ListItems() { string text = ItemRegistry.FormatList(); ModLog.Info("list_items\n" + text); return CommandResult.Ok("list_items", text); } public CommandResult ListEnemies() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.AppendLine("=== REPOLib AllEnemies ==="); stringBuilder.Append(EnemyRegistry.FormatRepolibList()); stringBuilder.AppendLine(); stringBuilder.AppendLine("=== Resources paths (spawn-time load) ==="); stringBuilder.AppendLine("Format: Enemies/Enemy - {name}"); string text = stringBuilder.ToString(); ModLog.Info("list_enemies\n" + text); return CommandResult.Ok("list_enemies", text); } private static Item? FindItem(string name) { return ItemRegistry.Resolve(name); } private static IEnumerable ExpandItemSearchTerms(string name) { yield return name; string lower = name.ToLowerInvariant(); bool flag; switch (lower) { case "gun": case "handgun": case "pistol": flag = true; break; default: flag = false; break; } if (flag) { yield return "gun"; yield return "handgun"; yield return "pistol"; } if (lower.Contains("health") || lower.Contains("medkit") || lower.Contains("med")) { yield return "medkit"; yield return "health"; } if (lower.Contains("shotgun")) { yield return "shotgun"; } if (lower.Contains("grenade") || lower == "expl") { yield return "Item Grenade Explosive"; yield return "Grenade Explosive"; yield return "grenade"; } if (lower.Contains("stun")) { yield return "Item Grenade Stun"; yield return "Grenade Stun"; yield return "stun"; } if (lower.Contains("shock")) { yield return "Item Grenade Shockwave"; yield return "Grenade Shockwave"; yield return "shock"; } if (lower.Contains("rubber") && lower.Contains("duck")) { yield return "Item Rubber Duck"; yield return "Rubber Duck"; } if (lower.Contains("flashlight")) { yield return "flashlight"; } if (lower.Contains("bat")) { yield return "bat"; } } internal CommandResult ApplyEffect(string eventId, string user) { return StreamEventRunner.Execute(eventId, user); } internal CommandResult ApplyUpgrade(string eventId, string user) { if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (!UpgradeHandlers.TryGetValue(eventId.Trim().ToLowerInvariant(), out Action value)) { return CommandResult.Fail("unknown_upgrade:" + eventId); } try { if ((Object)(object)PunManager.instance == (Object)null) { return CommandResult.Fail("pun_manager_not_ready"); } PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return CommandResult.Fail("player_not_found"); } string arg = SemiFunc.PlayerGetSteamID(val); value(arg, 1); ModLog.Info("upgrade '" + eventId + "' +1 for @" + user); GameNotifier.AnnounceEvent(user, eventId); return CommandResult.Ok("upgrade_applied", eventId); } catch (Exception ex) { ModLog.Error("upgrade error: " + ex.Message); return CommandResult.Fail(ex.Message); } } } internal static class EffectCommandExecutor { public static bool TryExecuteLine(string commandLine) { if (string.IsNullOrWhiteSpace(commandLine)) { return false; } bool flag = true; string[] array = commandLine.Split(';'); foreach (string text in array) { string text2 = text.Trim(); if (text2.Length != 0) { flag &= TryExecuteSingle(text2); } } return flag; } public static bool TryExecuteEvent(string eventId) { if (EventCommandCatalog.TryGetCommandLine(eventId, out string commandLine)) { return TryExecuteLine(commandLine); } if (!RepoEventMap.TryGetEffectCommand(eventId, out commandLine)) { return false; } return TryExecuteLine(commandLine); } private static bool TryExecuteSingle(string commandLine) { //IL_0930: Unknown result type (might be due to invalid IL or missing references) //IL_0935: Unknown result type (might be due to invalid IL or missing references) //IL_0939: Unknown result type (might be due to invalid IL or missing references) //IL_0967: Unknown result type (might be due to invalid IL or missing references) //IL_0945: Unknown result type (might be due to invalid IL or missing references) //IL_094a: Unknown result type (might be due to invalid IL or missing references) //IL_094e: Unknown result type (might be due to invalid IL or missing references) //IL_08d1: Unknown result type (might be due to invalid IL or missing references) //IL_08d6: Unknown result type (might be due to invalid IL or missing references) //IL_08da: Unknown result type (might be due to invalid IL or missing references) //IL_08dc: Unknown result type (might be due to invalid IL or missing references) //IL_08f5: Unknown result type (might be due to invalid IL or missing references) //IL_08f7: Unknown result type (might be due to invalid IL or missing references) //IL_0a83: Unknown result type (might be due to invalid IL or missing references) //IL_0a88: Unknown result type (might be due to invalid IL or missing references) //IL_0a8c: Unknown result type (might be due to invalid IL or missing references) //IL_0a8e: Unknown result type (might be due to invalid IL or missing references) //IL_0b15: Unknown result type (might be due to invalid IL or missing references) //IL_0b1a: Unknown result type (might be due to invalid IL or missing references) //IL_0b21: Unknown result type (might be due to invalid IL or missing references) //IL_0b23: Unknown result type (might be due to invalid IL or missing references) //IL_0a00: Unknown result type (might be due to invalid IL or missing references) //IL_0a05: Unknown result type (might be due to invalid IL or missing references) //IL_0a09: Unknown result type (might be due to invalid IL or missing references) //IL_0a0b: Unknown result type (might be due to invalid IL or missing references) //IL_0a9e: Unknown result type (might be due to invalid IL or missing references) //IL_0aa0: Unknown result type (might be due to invalid IL or missing references) //IL_0b36: Unknown result type (might be due to invalid IL or missing references) //IL_0b38: Unknown result type (might be due to invalid IL or missing references) try { List list = SplitArgs(commandLine); if (list.Count == 0) { return false; } string text = list[0].ToLowerInvariant(); List args = ((list.Count > 1) ? list.GetRange(1, list.Count - 1) : new List()); string spawnedLabel; switch (text) { case "spawn_item": { List rest3; string text5 = ReadNameThenFloats(args, out rest3); if (string.IsNullOrEmpty(text5)) { return false; } float length2 = ReadFloat(rest3, 0, 0f); float height3 = ReadFloat(rest3, 1, 1f); Vector3 itemSpawnPosition3 = SpawnHelper.GetItemSpawnPosition(length2, height3); return (Object)(object)ItemSpawnHelper.TrySpawn(text5, itemSpawnPosition3, Quaternion.identity, out spawnedLabel, 0, holdInPlace: true) != (Object)null || ValuableSpawnHelper.TrySpawn(text5, itemSpawnPosition3, Quaternion.identity, out spawnedLabel); } case "spawn_enemy": { string text4 = ReadNameThenFloats(args, out List _); if (string.IsNullOrEmpty(text4)) { return false; } text4 = EnemyRegistry.ResolveInternalName(text4); Vector3 val2 = SpawnHelper.GetEnemySpawnPosition(); if (!EnemySpawnHelper.TrySpawn(text4, val2, out string spawnedName)) { val2 = SpawnHelper.GetEnemyFallbackSpawnNearPlayer(0); if (!EnemySpawnHelper.TrySpawn(text4, val2, out spawnedName)) { return false; } } ModLog.Info($"spawn_enemy ok '{spawnedName}' at {val2}"); return true; } case "tok_active_nade": { string kind = ReadString(args, 0, "stun"); int count = Math.Max(1, EventContext.StackCount); return SpecialEffectHelper.SpawnPrimedActiveNades(kind, count); } case "spawn_active_item": { List rest; string text2 = ReadNameThenFloats(args, out rest); if (string.IsNullOrEmpty(text2)) { return false; } string text3 = MapActiveItemToNadeKind(text2); if (text3 != null) { return SpecialEffectHelper.SpawnPrimedActiveNade(text3); } float length = ReadFloat(rest, 0, 1f); float height2 = ReadFloat(rest, 1, 1f); Vector3 itemSpawnPosition2 = SpawnHelper.GetItemSpawnPosition(length, height2); GameObject val = ItemSpawnHelper.TrySpawn(text2, itemSpawnPosition2, Quaternion.identity, out spawnedLabel, 0, holdInPlace: true, skipGrenadeDormant: true); if ((Object)(object)val == (Object)null) { return false; } SpecialEffectHelper.ActivateSpawnedActiveItem(val); return true; } case "spawn_simple_item_group": { string groupName2 = ReadString(args, 0, "group_loot_rand_small"); float length3 = ReadFloat(args, 1, 0f); float height4 = ReadFloat(args, 2, 1f); string text6 = DropGroupCatalog.PickRandom(groupName2); if (string.IsNullOrEmpty(text6)) { return false; } Vector3 itemSpawnPosition4 = SpawnHelper.GetItemSpawnPosition(length3, height4); return ValuableSpawnHelper.TrySpawn(text6, itemSpawnPosition4, Quaternion.identity, out spawnedLabel) || (Object)(object)ItemSpawnHelper.TrySpawn(text6, itemSpawnPosition4, Quaternion.identity, out spawnedLabel, 0, holdInPlace: true) != (Object)null; } case "spawn_item_group": { string groupName = ReadString(args, 0, "group_single_item"); float num = ReadFloat(args, 1, 0f); float height = ReadFloat(args, 2, 1f); string[] array = DropGroupCatalog.PickRandomVariantItems(groupName); if (array.Length == 0) { return false; } bool result = false; for (int i = 0; i < array.Length; i++) { Vector3 itemSpawnPosition = SpawnHelper.GetItemSpawnPosition(num + (float)i * 0.1f, height, i); if (ValuableSpawnHelper.TrySpawn(array[i], itemSpawnPosition, Quaternion.identity, out spawnedLabel) || (Object)(object)ItemSpawnHelper.TrySpawn(array[i], itemSpawnPosition, Quaternion.identity, out spawnedLabel, i, holdInPlace: true) != (Object)null) { result = true; } } return result; } case "upgrade_player_tumble_launch": return ApplyUpgradeEvent("solo_upgrade_roll"); case "upgrade_player_sprint_speed": return ApplyUpgradeEvent("solo_upgrade_speed"); case "upgrade_player_stamina": return ApplyUpgradeEvent("solo_upgrade_energy"); case "upgrade_player_health": return ApplyUpgradeEvent("solo_upgrade_health"); case "upgrade_player_grab_range": return ApplyUpgradeEvent("solo_upgrade_range"); case "upgrade_player_grab_strength": return ApplyUpgradeEvent("solo_upgrade_strength"); case "upgrade_player_extra_jump": return ApplyUpgradeEvent("solo_upgrade_jump"); case "upgrade_player_wings": return ApplyUpgradeEvent("solo_upgrade_wings"); case "upgrade_player_crouch_rest": return ApplyUpgradeEvent("solo_upgrade_rest"); case "disable_player_aiming": return PlayerEffectHelper.DisableAiming(ReadDuration(args, 0, 30f)); case "disable_player_movement": return PlayerEffectHelper.DisableMovement(ReadDuration(args, 0, 10f)); case "disable_input": return PlayerEffectHelper.DisableInputKey(ReadString(args, 1, "Grab"), ReadDuration(args, 0, 10f)); case "hold_input": return PlayerEffectHelper.HoldInputKey(ReadString(args, 1, "Crouch"), ReadDuration(args, 0, 60f)); case "shuffle_player_movement": return PlayerEffectHelper.ShuffleMovement(ReadDuration(args, 0, 45f)); case "hurt_player_amount": return PlayerEffectHelper.HurtPlayerAmount(ReadBool(args, 0, fallback: false), ReadInt(args, 1, 10), ReadBool(args, 2, fallback: true)); case "slap_all_room": return PlayerEffectHelper.SlapAllRoom(ReadInt(args, 0, 10)); case "heal_player_amount": return PlayerEffectHelper.HealPlayerAmount(ReadBool(args, 0, fallback: false), ReadInt(args, 1, 25)); case "explode_player": return PlayerEffectHelper.ExplodeTargetPlayer(EventContext.SoloTarget()); case "explode_random_player": return SpecialEffectHelper.ExplodeRandomPlayer(); case "explode_closest_item": return SpecialEffectHelper.ExplodeClosestItem(ReadFloat(args, 0, 13f), ReadFloat(args, 1, 13f), ReadFloat(args, 2, 5f)); case "avg_players_hp": return SpecialEffectHelper.AveragePlayersHp(); case "drop_inventory": return PlayerEffectHelper.DropInventory(); case "resurrect_player": return SpecialEffectHelper.ResurrectPlayers(allPlayers: false, randomOnly: false); case "resurrect_all_players": return SpecialEffectHelper.ResurrectPlayers(allPlayers: true, randomOnly: false); case "resurrect_random_player": return SpecialEffectHelper.ResurrectPlayers(allPlayers: true, randomOnly: true); case "resurrect_closest_player": return SpecialEffectHelper.ResurrectClosestDeadPlayer(); case "teleport_player_rnd_point_start_room": return SpecialEffectHelper.TeleportPlayerRandomPoint(startRoom: true, ReadBool(args, 0, fallback: false)); case "teleport_player_rnd_point_rnd_room": return SpecialEffectHelper.TeleportPlayerRandomPoint(startRoom: false, ReadBool(args, 0, fallback: false)); case "teleport_shuffle_players": return SpecialEffectHelper.TeleportShufflePlayers(); case "shuffle_players_hp": return SpecialEffectHelper.ShufflePlayersHp(); case "change_extract_goal_percents": return SpecialEffectHelper.ChangeExtractGoalPercent(ReadFloat(args, 0, 1f)); case "shake_cart_items_delayed": return SpecialEffectHelper.ShakeCartItems(ReadFloat(args, 0, 0.5f), ReadFloat(args, 1, 1.5f), ReadFloat(args, 2, 35f), ReadFloat(args, 3, 55f)); case "teleport_carts_to_start": return SpecialEffectHelper.TeleportCarts(toStart: true); case "teleport_carts_to_random_room": return SpecialEffectHelper.TeleportCarts(toStart: false); case "stun_enemies": return SpecialEffectHelper.StunEnemies(ReadFloat(args, 0, 7f)); case "spawn_items_around_player": return SpecialEffectHelper.SpawnItemsAroundPlayer(ReadString(args, 0, "Valuable_Manor_Frog"), ReadFloat(args, 1, 1f), ReadFloat(args, 2, 1f), ReadInt(args, 3, 6)); case "spawn_toycars_around": return SpecialEffectHelper.SpawnToyCarsAroundPlayer(ReadInt(args, 0, 5)); case "spawn_toyplanes_around": return SpecialEffectHelper.SpawnToyPlanesAroundPlayer(ReadInt(args, 0, 5)); case "spawn_chomp_book": return SpecialEffectHelper.SpawnChompBookNearPlayer(); case "spawn_items_from_player": return SpecialEffectHelper.SpawnItemsFromPlayer(ReadString(args, 0, ""), ReadFloat(args, 1, 15f), ReadFloat(args, 2, 0.5f), ReadFloat(args, 3, 0.3f), ReadFloat(args, 4, 0.5f), ReadFloat(args, 5, 90f)); case "all_players_speak": case "random_player_speak": return SpecialEffectHelper.AllPlayersSpeak(); case "nade_from_all_players": return SpecialEffectHelper.SpawnNadesFromAllPlayers(ReadString(args, 0, "expl"), ReadInt(args, 1, 1)); case "restore_stamina": return PlayerEffectHelper.RestoreStamina(); case "infinite_player_stamina": return PlayerEffectHelper.InfiniteStamina(ReadDuration(args, 0, 60f)); case "drain_player_stamina": return PlayerEffectHelper.DrainStamina(ReadDuration(args, 0, 30f), ReadFloat(args, 1, 20f)); case "invincible_player": return PlayerEffectHelper.Invincible(ReadDuration(args, 0, 60f)); case "set_player_speed_mult": return PlayerEffectHelper.SetSpeedMultiplier(ReadDuration(args, 0, 45f), ReadFloat(args, 1, 0.33f)); case "set_player_jump_power": return PlayerEffectHelper.SetJumpPower(ReadDuration(args, 0, 60f), ReadFloat(args, 1, 40f)); case "enable_anti_gravity": return PlayerEffectHelper.EnableAntiGravity(ReadDuration(args, 0, 60f)); case "set_player_gravity": return PlayerEffectHelper.SetHeavyGravity(ReadDuration(args, 0, 45f), ReadFloat(args, 1, 120f)); case "knockdown_player": return PlayerEffectHelper.Knockdown(ReadDuration(args, 0, 10f), ReadFloat(args, 1, 10f)); case "rel_force_move": return PlayerEffectHelper.RelativeForceMove(ReadFloat(args, 0, 0f), ReadFloat(args, 1, 0f), 20f); case "force_rb": return PlayerEffectHelper.ForceRigidBody(ReadFloat(args, 0, 0f), ReadFloat(args, 1, 0f), ReadFloat(args, 2, 0f), ReadFloat(args, 3, 10f)); case "player_set_health_pc": return PlayerEffectHelper.SetHealthPercent(ReadBool(args, 0, fallback: false), ReadFloat(args, 1, 100f)); default: ModLog.Warn("Effect command not implemented: " + text); return false; } } catch (Exception ex) { ModLog.Error("Effect command failed '" + commandLine + "': " + ex.Message); return false; } } private static string? MapActiveItemToNadeKind(string itemName) { string text = (itemName ?? "").ToLowerInvariant(); if (text.Contains("duct")) { return null; } if (text.Contains("explosive") || text.Contains("expl") || text.Contains("human")) { if (text.Contains("human")) { return null; } return "expl"; } if (text.Contains("shock")) { return "shock"; } if (text.Contains("stun") && text.Contains("grenade")) { return "stun"; } if (text.Contains("rubber_duck") || text.Contains("rubber duck") || (text.Contains("duck") && !text.Contains("bucket") && !text.Contains("duct"))) { return "duck"; } return null; } private static bool ApplyUpgradeEvent(string eventId) { try { if ((Object)(object)PunManager.instance == (Object)null) { return false; } PlayerAvatar val = EventContext.SoloTarget(); if ((Object)(object)val == (Object)null || PlayerTargeting.IsPlayerDead(val)) { return false; } string text = SemiFunc.PlayerGetSteamID(val); switch (eventId) { case "solo_upgrade_energy": PunManager.instance.UpgradePlayerEnergy(text, 1); break; case "solo_upgrade_health": PunManager.instance.UpgradePlayerHealth(text, 1); break; case "solo_upgrade_speed": PunManager.instance.UpgradePlayerSprintSpeed(text, 1); break; case "solo_upgrade_range": PunManager.instance.UpgradePlayerGrabRange(text, 1); break; case "solo_upgrade_strength": PunManager.instance.UpgradePlayerGrabStrength(text, 1); break; case "solo_upgrade_jump": PunManager.instance.UpgradePlayerExtraJump(text, 1); break; case "solo_upgrade_roll": PunManager.instance.UpgradePlayerTumbleLaunch(text, 1); break; case "solo_upgrade_wings": PunManager.instance.UpgradePlayerTumbleWings(text, 1); break; case "solo_upgrade_rest": PunManager.instance.UpgradePlayerCrouchRest(text, 1); break; default: return false; } return true; } catch (Exception ex) { ModLog.Debug("Upgrade failed: " + ex.Message); return false; } } private static string ReadNameThenFloats(IReadOnlyList args, out List rest) { rest = new List(); if (args.Count == 0) { return ""; } string text = args[0]; for (int i = 1; i < args.Count; i++) { rest.Add(args[i]); } return text.Trim(); } private static List SplitArgs(string line) { List list = new List(); string text = ""; bool flag = false; for (int i = 0; i < line.Length; i++) { char c = line[i]; if (c == '"') { flag = !flag; } else if (char.IsWhiteSpace(c) && !flag) { if (text.Length > 0) { list.Add(text); text = ""; } } else { text += c; } } if (text.Length > 0) { list.Add(text); } return list; } private static float ReadFloat(IReadOnlyList args, int index, float fallback) { if (index >= args.Count || !float.TryParse(args[index], NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return fallback; } return result; } private static float ReadDuration(IReadOnlyList args, int index, float fallback) { return Mathf.Max(0.1f, ReadFloat(args, index, fallback) * (float)Mathf.Max(1, EventContext.StackCount)); } private static int ReadInt(IReadOnlyList args, int index, int fallback) { if (index >= args.Count || !int.TryParse(args[index], NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)) { return fallback; } return result; } private static bool ReadBool(IReadOnlyList args, int index, bool fallback) { if (index >= args.Count || !bool.TryParse(args[index], out var result)) { return fallback; } return result; } private static string ReadString(IReadOnlyList args, int index, string fallback) { if (index >= args.Count || string.IsNullOrWhiteSpace(args[index])) { return fallback; } return args[index]; } } internal sealed class EffectTimerHost : MonoBehaviour { private sealed class TimedEffect { public Coroutine? Coroutine; public Action? OnEnd; public float RemainingSeconds; public Action? OnUpdate; } private static EffectTimerHost? _instance; private readonly Dictionary _running = new Dictionary(); internal static EffectTimerHost Instance { get { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected O, but got Unknown if ((Object)(object)_instance != (Object)null) { return _instance; } GameObject val = new GameObject("TokControlEffectHost"); Object.DontDestroyOnLoad((Object)(object)val); _instance = val.AddComponent(); return _instance; } } internal Coroutine RunRoutine(IEnumerator routine) { return ((MonoBehaviour)this).StartCoroutine(routine); } internal void RunAfterFrames(int frames, Action action) { if (action != null) { ((MonoBehaviour)this).StartCoroutine(AfterFrames(frames, action)); } } private static IEnumerator AfterFrames(int frames, Action action) { for (int i = 0; i < Math.Max(1, frames); i++) { yield return null; } try { action(); } catch (Exception ex) { ModLog.Debug("RunAfterFrames: " + ex.Message); } } internal void RunForSeconds(string id, float seconds, Action onUpdate, Action? onEnd = null) { seconds = Mathf.Max(0.1f, seconds); if (_running.TryGetValue(id, out TimedEffect value) && value.Coroutine != null && value.RemainingSeconds > 0.05f) { value.RemainingSeconds += seconds; if (onUpdate != null) { value.OnUpdate = onUpdate; } if (onEnd != null) { value.OnEnd = onEnd; } ModLog.Info($"Timed effect '{id}' extended +{seconds:0.#}s → {value.RemainingSeconds:0.#}s"); } else { Stop(id, invokeEnd: true); TimedEffect timedEffect = new TimedEffect { OnEnd = onEnd, OnUpdate = onUpdate, RemainingSeconds = seconds }; timedEffect.Coroutine = ((MonoBehaviour)this).StartCoroutine(RunTimer(id, timedEffect)); _running[id] = timedEffect; } } internal float GetRemaining(string id) { if (!_running.TryGetValue(id, out TimedEffect value)) { return 0f; } return Mathf.Max(0f, value.RemainingSeconds); } internal void Stop(string id, bool invokeEnd = false) { if (!_running.TryGetValue(id, out TimedEffect value)) { return; } _running.Remove(id); if (value.Coroutine != null) { ((MonoBehaviour)this).StopCoroutine(value.Coroutine); } if (!invokeEnd) { return; } try { value.OnEnd?.Invoke(); } catch (Exception ex) { ModLog.Warn("Timed effect end '" + id + "': " + ex.Message); } } private IEnumerator RunTimer(string id, TimedEffect effect) { while (effect.RemainingSeconds > 0f) { float unscaledDeltaTime = Time.unscaledDeltaTime; try { effect.OnUpdate?.Invoke(unscaledDeltaTime); } catch (Exception ex) { ModLog.Debug("Timed effect tick '" + id + "': " + ex.Message); } effect.RemainingSeconds -= unscaledDeltaTime; yield return null; } if (_running.TryGetValue(id, out TimedEffect value) && value == effect) { _running.Remove(id); } try { effect.OnEnd?.Invoke(); } catch (Exception ex2) { ModLog.Warn("Timed effect end '" + id + "': " + ex2.Message); } } } internal static class EnemyLifetimeGuard { private sealed class Entry { public EnemyParent? Parent; public float RegisteredAt; public bool SpawnFinalized; } private static readonly List Tracked = new List(); private static float _checkInSec; private const float SpawnProtectSeconds = 3f; private const float TrackMaxSeconds = 10f; public static void Register(Enemy? enemy) { if ((Object)(object)enemy == (Object)null) { return; } try { EnemyParent componentInParent = ((Component)enemy).GetComponentInParent(); if ((Object)(object)componentInParent == (Object)null) { return; } foreach (Entry item in Tracked) { if ((Object)(object)item.Parent == (Object)(object)componentInParent) { return; } } Tracked.Add(new Entry { Parent = componentInParent, RegisteredAt = Time.time, SpawnFinalized = false }); PreventInstantDespawn(componentInParent); } catch (Exception ex) { ModLog.Debug("EnemyLifetimeGuard.Register: " + ex.Message); } } public static void Clear() { Tracked.Clear(); _checkInSec = 0f; EnemySpawnTracker.Clear(); DirectorEnemyDeathGuard.Clear(); } public static void Tick(float dt) { _checkInSec -= dt; if (_checkInSec > 0f) { return; } _checkInSec = 0.35f; for (int num = Tracked.Count - 1; num >= 0; num--) { Entry entry = Tracked[num]; EnemyParent parent = entry.Parent; if ((Object)(object)parent == (Object)null || IsEnemyDead(parent)) { Tracked.RemoveAt(num); } else { float num2 = Time.time - entry.RegisteredAt; if (num2 >= 10f) { if (!entry.SpawnFinalized) { FinalizeSpawn(parent); } Tracked.RemoveAt(num); } else { if (!entry.SpawnFinalized && num2 >= 3f) { FinalizeSpawn(parent); entry.SpawnFinalized = true; } if (num2 < 10f) { PreventInstantDespawn(parent); } } } } } private static void FinalizeSpawn(EnemyParent parent) { try { float num = ReadFloatField(parent, "SpawnedTimeMax"); if (num > 0f) { SetFloatField(parent, "SpawnedTimer", num); } else { SetFloatField(parent, "SpawnedTimer", 9999f); } ModLog.Debug("EnemyLifetimeGuard: spawn finalized for '" + ((Object)parent).name + "'"); } catch (Exception ex) { ModLog.Debug("EnemyLifetimeGuard.FinalizeSpawn: " + ex.Message); } } private static void PreventInstantDespawn(EnemyParent parent) { try { if (parent.DespawnedTimer > 0f && parent.DespawnedTimer < 30f) { parent.DespawnedTimer = 30f; } } catch { TrySetFloatField(parent, "DespawnedTimer", 30f, onlyIfPositive: true); } } public static void ArmKillable(GameObject? instance) { if ((Object)(object)instance == (Object)null) { return; } bool flag = false; EnemyParent[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (EnemyParent val in componentsInChildren) { if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeInHierarchy) { ArmKillable(val); flag = true; } } if (!flag) { ArmKillable(instance.GetComponent() ?? instance.GetComponentInParent()); } } public static void ArmKillable(EnemyParent? parent) { if (!((Object)(object)parent == (Object)null)) { Enemy[] componentsInChildren = ((Component)parent).GetComponentsInChildren(true); foreach (Enemy enemy in componentsInChildren) { ArmKillable(enemy); } } } public static void ArmKillable(Enemy? enemy) { if ((Object)(object)enemy == (Object)null) { return; } try { if (!enemy.HasHealth) { EnemyHealth val = ((Component)enemy).GetComponent() ?? ((Component)enemy).GetComponentInChildren(true); if ((Object)(object)val != (Object)null) { enemy.Health = val; enemy.HasHealth = true; } } if (enemy.HasHealth && (Object)(object)enemy.Health != (Object)null) { enemy.Health.dead = false; } if (enemy.HasRigidbody && (Object)(object)enemy.Rigidbody != (Object)null) { PhysGrabObject physGrabObject = enemy.Rigidbody.physGrabObject; if ((Object)(object)physGrabObject != (Object)null) { physGrabObject.spawned = true; } } } catch (Exception ex) { ModLog.Debug("ArmKillable: " + ex.Message); } } private static bool IsEnemyDead(EnemyParent parent) { try { if ((Object)(object)parent == (Object)null || (Object)(object)((Component)parent).gameObject == (Object)null) { return true; } if (!((Component)parent).gameObject.activeInHierarchy) { return false; } Enemy componentInChildren = ((Component)parent).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return false; } if (ReadBool(componentInChildren, "isDead") || ReadBool(componentInChildren, "dead")) { return true; } if (ReadBool(parent, "dead")) { return true; } } catch { } return false; } private static bool ReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } } catch { } return false; } private static float ReadFloatField(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(float)) { return (float)field.GetValue(target); } } catch { } return 0f; } private static void SetFloatField(object target, string fieldName, float value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(float)) { field.SetValue(target, value); } } catch { } } private static void TrySetFloatField(object target, string fieldName, float value, bool onlyIfPositive) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null) && !(field.FieldType != typeof(float))) { float num = (float)field.GetValue(target); if (!onlyIfPositive || !(num <= 0f)) { field.SetValue(target, value); } } } catch { } } } internal static class EnemyRegistry { public static string ResolveInternalName(string eventIdOrSlug) { return RepoEventMap.ResolveEnemyInternalName(eventIdOrSlug); } public static IEnumerable GetCandidateNames(string query) { string internalName = ResolveInternalName(query); foreach (string item in RepoEventMap.ExpandEnemyResourceNames(internalName)) { yield return item; } foreach (string item2 in RepoEventMap.ExpandEnemyResourceNames(query)) { if (!string.Equals(item2, internalName, StringComparison.OrdinalIgnoreCase)) { yield return item2; } } } public static string FormatRepolibList() { StringBuilder stringBuilder = new StringBuilder(); if (Enemies.AllEnemies == null) { stringBuilder.AppendLine("(REPOLib AllEnemies is null)"); return stringBuilder.ToString(); } foreach (EnemySetup item in Enemies.AllEnemies.OrderBy((EnemySetup s) => (s == null) ? null : ((Object)s).name, StringComparer.OrdinalIgnoreCase)) { if (!((Object)(object)item == (Object)null)) { stringBuilder.AppendLine(((Object)item).name ?? "(unnamed)"); } } return stringBuilder.ToString(); } } internal static class EnemySpawnHelper { private const string EnemyPathPrefix = "Enemies/Enemy - "; public static bool TrySpawn(string enemyName, Vector3 position, out string? spawnedName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) spawnedName = EnemyRegistry.ResolveInternalName(enemyName); ModLog.Info($"Spawn enemy request '{enemyName}' -> internal '{spawnedName}' at {position}"); if (TrySpawnViaResources(spawnedName, position, out spawnedName)) { return true; } if (TrySpawnViaRepolib(spawnedName, position, out spawnedName)) { return true; } LogSpawnDiagnostics(spawnedName ?? enemyName); return false; } private static bool TrySpawnViaRepolib(string targetName, Vector3 position, out string? spawnedName) { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) spawnedName = targetName; EnemySetup val = FindEnemySetup(targetName); if ((Object)(object)val == (Object)null) { ModLog.Warn("REPOLib: no EnemySetup match for '" + targetName + "'"); return false; } try { List list = Enemies.SpawnEnemy(val, position, Quaternion.identity, false); if (list == null || list.Count == 0) { ModLog.Warn("REPOLib.SpawnEnemy returned empty for '" + ((Object)val).name + "'"); return false; } spawnedName = ((Object)val).name ?? targetName; bool flag = false; foreach (EnemyParent item in list) { if (!((Object)(object)item == (Object)null)) { FinalizeRepoLibSpawn(item, position, ((Object)val).name ?? targetName); flag = true; } } if (flag) { ModLog.Info($"Spawned via REPOLib: {spawnedName} x{list.Count}"); } return flag; } catch (Exception ex) { ModLog.Warn("REPOLib.SpawnEnemy failed for " + targetName + ": " + ex.Message); return false; } } private static void FinalizeRepoLibSpawn(EnemyParent parent, Vector3 position, string internalName) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) try { if (!((Object)(object)parent == (Object)null)) { FinalizeEnemySpawn(((Component)parent).gameObject, position, internalName); ModLog.Info($"REPOLib enemy ready at {position} ({Vector3.Distance(position, SpawnHelper.GetPlayerBodyPosition()):F1}m)"); } } catch (Exception ex) { ModLog.Warn("FinalizeRepoLibSpawn: " + ex.Message); } } private static EnemySetup? FindEnemySetup(string targetName) { if (Enemies.AllEnemies == null || Enemies.AllEnemies.Count == 0) { ModLog.Warn("REPOLib AllEnemies is empty — is the level loaded?"); return null; } EnemySetup val = null; int num = int.MaxValue; foreach (string candidateName in EnemyRegistry.GetCandidateNames(targetName)) { foreach (EnemySetup allEnemy in Enemies.AllEnemies) { if ((Object)(object)allEnemy == (Object)null) { continue; } int num2 = ScoreSetupName(((Object)allEnemy).name ?? "", candidateName); try { if (num2 < 0 && allEnemy.spawnObjects != null) { foreach (PrefabRef spawnObject in allEnemy.spawnObjects) { GameObject val2 = ((PrefabRef)(object)spawnObject)?.Prefab; if ((Object)(object)val2 == (Object)null) { continue; } int num3 = ScoreSetupName(((Object)val2).name ?? "", candidateName); if (num3 >= 0 && (num2 < 0 || num3 < num2)) { num2 = num3; } EnemyParent component = val2.GetComponent(); if ((Object)(object)component != (Object)null) { int num4 = ScoreSetupName(component.enemyName ?? "", candidateName); if (num4 >= 0 && (num2 < 0 || num4 < num2)) { num2 = num4; } } } } } catch { } if (num2 >= 0 && num2 < num) { num = num2; val = allEnemy; } } } if ((Object)(object)val != (Object)null) { ModLog.Info($"EnemySetup match '{targetName}' -> '{((Object)val).name}' (score={num})"); } if (num > 100) { return null; } return val; } private static int ScoreSetupName(string setupName, string term) { if (string.IsNullOrWhiteSpace(setupName) || string.IsNullOrWhiteSpace(term)) { return -1; } string text = NormalizeToken(setupName).Replace('_', ' '); string text2 = NormalizeToken(term).Replace('_', ' '); if (string.Equals(text, text2, StringComparison.OrdinalIgnoreCase)) { return 0; } if (text.EndsWith(text2, StringComparison.OrdinalIgnoreCase)) { return 5; } if (text.Contains(text2, StringComparison.OrdinalIgnoreCase)) { return 20 + text.Length; } if (text2.Contains(text, StringComparison.OrdinalIgnoreCase)) { return 30 + text.Length; } return -1; } private static string NormalizeToken(string value) { value = value.Trim(); if (value.StartsWith("Enemy - ", StringComparison.OrdinalIgnoreCase)) { value = value.Substring("Enemy - ".Length); } return value; } private static bool TrySpawnViaResources(string targetName, Vector3 position, out string? spawnedName) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) spawnedName = targetName; foreach (string candidateName in EnemyRegistry.GetCandidateNames(targetName)) { string text = "Enemies/Enemy - " + candidateName; GameObject val = Resources.Load(text); if ((Object)(object)val == (Object)null) { string text2 = candidateName.Replace('_', ' '); if (!string.Equals(text2, candidateName, StringComparison.Ordinal)) { text = "Enemies/Enemy - " + text2; val = Resources.Load(text); } } if ((Object)(object)val == (Object)null) { ModLog.Debug("Resources miss: Enemies/Enemy - " + candidateName); } else if (TryInstantiateEnemy(val, text, candidateName, position)) { spawnedName = candidateName; ModLog.Info("Spawned via Resources: " + candidateName + " (" + text + ")"); return true; } } return false; } private static bool TryInstantiateEnemy(GameObject prefab, string resourcePath, string displayName, Vector3 position) { //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0214: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) try { if ((Object)(object)RunManager.instance == (Object)null) { ModLog.Warn("RunManager null — enter a level/map before spawning " + displayName); return false; } RunManager.instance.EnemiesSpawnedRemoveStart(); GameObject val = (((Object)(object)GameManager.instance != (Object)null && GameManager.instance.gameMode != 0 && PhotonNetwork.IsConnected && SemiFunc.IsMasterClientOrSingleplayer()) ? PhotonNetwork.InstantiateRoomObject(resourcePath, position, Quaternion.identity, (byte)0, (object[])null) : Object.Instantiate(prefab, position, Quaternion.identity)); if ((Object)(object)val == (Object)null) { RunManager.instance.EnemiesSpawnedRemoveEnd(); return false; } EnemyParent component = val.GetComponent(); Enemy componentInChildren = val.GetComponentInChildren(true); if ((Object)(object)component != (Object)null) { try { FieldInfo field = typeof(EnemyParent).GetField("SetupDone", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(component, true); } else { component.SetupDone = true; } } catch { try { component.SetupDone = true; } catch { } } if ((Object)(object)componentInChildren != (Object)null) { EnemySpawnTracker.Track(componentInChildren); componentInChildren.EnemyTeleported(position); try { foreach (PlayerAvatar item in PlayerTargeting.AllPlayers()) { if (!((Object)(object)item?.photonView == (Object)null)) { try { componentInChildren.PlayerAdded(item.photonView.ViewID); } catch { } } } } catch { } } try { if ((Object)(object)LevelGenerator.Instance != (Object)null) { FieldInfo field2 = typeof(LevelGenerator).GetField("EnemiesSpawnTarget", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field2 != null && field2.FieldType == typeof(int)) { field2.SetValue(LevelGenerator.Instance, (int)field2.GetValue(LevelGenerator.Instance) + 1); } } } catch { } EnemyDirector instance = EnemyDirector.instance; if (instance != null) { instance.FirstSpawnPointAdd(component); } } RunManager.instance.EnemiesSpawnedRemoveEnd(); FinalizeEnemySpawn(val, position, displayName); return true; } catch (Exception ex) { ModLog.Error("Instantiate failed for " + displayName + ": " + ex.Message); try { RunManager instance2 = RunManager.instance; if (instance2 != null) { instance2.EnemiesSpawnedRemoveEnd(); } } catch { } return false; } } private static void TryActivateEnemyNear(Vector3 position) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) EnemyParent val = null; float num = 4f; EnemyParent[] array = Object.FindObjectsOfType(); foreach (EnemyParent val2 in array) { if (!((Object)(object)val2 == (Object)null)) { float num2 = Vector3.Distance(((Component)val2).transform.position, position); if (!(num2 >= num)) { num = num2; val = val2; } } } if ((Object)(object)val != (Object)null) { FinalizeEnemySpawn(((Component)val).gameObject, position, ((Object)val).name); } } private static void FinalizeEnemySpawn(GameObject instance, Vector3 position, string internalName) { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0041: 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_006b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)instance.GetComponentInChildren(true) != (Object)null) { FinalizeHeartHuggerSpawn(instance, position); return; } string text = NormalizeEnemyToken(internalName); if (text.Contains("bang")) { FinalizeBangSpawn(instance, position); } else if (text.Contains("gnome")) { FinalizeGnomeSpawn(instance, position); } else if (text.Contains("ceiling") || text.Contains("peeper")) { FinalizeCeilingEyeSpawn(instance, position); } else { ForceActivateEnemy(instance, position); } } private static string NormalizeEnemyToken(string value) { value = value.Trim(); if (value.StartsWith("Enemy - ", StringComparison.OrdinalIgnoreCase)) { value = value.Substring("Enemy - ".Length); } return value.Replace('_', ' ').Trim().ToLowerInvariant(); } private static void FinalizeBangSpawn(GameObject instance, Vector3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) EnsureBangDirector(instance); EnemyBang keep = KeepPrimaryPackUnit(instance.GetComponentsInChildren(true), instance); TrackKeepOnly((Component?)(object)keep); ForceActivateEnemy(instance, position); BindBangPack(instance, position, keep); SchedulePackBind(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) BindBangPack(instance, position, keep); }); EnemyLifetimeGuard.ArmKillable(instance); ModLog.Info("Bang spawn: 1 unit bound, extras silenced"); } private static void FinalizeGnomeSpawn(GameObject instance, Vector3 position) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) EnsureGnomeDirector(instance); EnemyGnome keep = KeepPrimaryPackUnit(instance.GetComponentsInChildren(true), instance); TrackKeepOnly((Component?)(object)keep); ForceActivateEnemy(instance, position); BindGnomePack(instance, position, keep); SchedulePackBind(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) BindGnomePack(instance, position, keep); }); EnemyLifetimeGuard.ArmKillable(instance); ModLog.Info("Gnome spawn: 1 unit bound, extras silenced"); } private static void DetachDirectorFromPack(Component director, GameObject pack) { if ((Object)(object)director == (Object)null || (Object)(object)pack == (Object)null || (Object)(object)director.transform == (Object)(object)pack.transform) { return; } try { GameObject val = LevelGenerator.Instance?.EnemyParent; if ((Object)(object)val != (Object)null) { if ((Object)(object)director.transform.parent != (Object)(object)val.transform) { director.transform.SetParent(val.transform, true); } } else if (director.transform.IsChildOf(pack.transform)) { director.transform.SetParent((Transform)null, true); } } catch { } } private static T CreateFallbackDirector(GameObject pack, string objectName) where T : Component { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Expected O, but got Unknown //IL_001f: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(objectName); val.transform.SetParent(pack.transform, false); val.transform.localPosition = Vector3.zero; return val.AddComponent(); } private static EnemyBangDirector? EnsureBangDirector(GameObject pack) { EnemyBangDirector val = EnemyBangDirector.instance; if ((Object)(object)val == (Object)null) { val = pack.GetComponentInChildren(true); } if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType(true); } try { GameObject val2 = LevelGenerator.Instance?.EnemyParent; if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null) { val = val2.GetComponentInChildren(true); } } catch { } if ((Object)(object)val == (Object)null) { val = CreateFallbackDirector(pack, "TokControlBangDirector"); ModLog.Warn("Bang spawn: added fallback EnemyBangDirector"); } ((Behaviour)val).enabled = true; val.debugOneOnly = false; EnemyBangDirector val3 = val; if (val3.units == null) { val3.units = new List(); } val3 = val; if (val3.destinations == null) { val3.destinations = new List(); } EnemyBangDirector.instance = val; DetachDirectorFromPack((Component)(object)val, pack); return val; } private static EnemyGnomeDirector? EnsureGnomeDirector(GameObject pack) { EnemyGnomeDirector val = EnemyGnomeDirector.instance; if ((Object)(object)val == (Object)null) { val = pack.GetComponentInChildren(true); } if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType(true); } try { GameObject val2 = LevelGenerator.Instance?.EnemyParent; if ((Object)(object)val == (Object)null && (Object)(object)val2 != (Object)null) { val = val2.GetComponentInChildren(true); } } catch { } if ((Object)(object)val == (Object)null) { val = CreateFallbackDirector(pack, "TokControlGnomeDirector"); ModLog.Warn("Gnome spawn: added fallback EnemyGnomeDirector"); } ((Behaviour)val).enabled = true; val.debugOneOnly = false; EnemyGnomeDirector val3 = val; if (val3.gnomes == null) { val3.gnomes = new List(); } val3 = val; if (val3.destinations == null) { val3.destinations = new List(); } EnemyGnomeDirector.instance = val; DetachDirectorFromPack((Component)(object)val, pack); return val; } private static void TrackKeepOnly(Component? keep) { if (!((Object)(object)keep == (Object)null)) { Enemy val = keep.GetComponent() ?? keep.GetComponentInParent() ?? keep.GetComponentInChildren(true); if (!((Object)(object)val == (Object)null)) { EnemySpawnTracker.Track(val); EnemyLifetimeGuard.Register(val); } } } private static void TrackAllEnemies(GameObject instance) { if (!((Object)(object)instance == (Object)null)) { Enemy[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (Enemy enemy in componentsInChildren) { EnemySpawnTracker.Track(enemy); EnemyLifetimeGuard.Register(enemy); } } } private static void SchedulePackBind(Action bind) { MainThreadDispatcher.EnqueueDelayed(bind, 0.12f); MainThreadDispatcher.EnqueueDelayed(bind, 0.45f); MainThreadDispatcher.EnqueueDelayed(bind, 1.1f); } private static T? KeepPrimaryPackUnit(T[] units, GameObject packRoot) where T : Behaviour { if (units == null || units.Length == 0) { return default(T); } T val = default(T); int num = -1; foreach (T val2 in units) { if ((Object)(object)val2 == (Object)null) { continue; } int num2 = 0; try { num2 = ((Component)(object)val2).GetComponentsInChildren(true).Length; } catch { } object obj2 = val2; EnemyBang val3 = (EnemyBang)((obj2 is EnemyBang) ? obj2 : null); if (val3 != null && val3.headObjects != null) { GameObject[] headObjects = val3.headObjects; foreach (GameObject val4 in headObjects) { if ((Object)(object)val4 != (Object)null) { num2 += 80; } } } if ((Object)(object)val == (Object)null || num2 > num) { val = val2; num = num2; } } foreach (T val5 in units) { if (!((Object)(object)val5 == (Object)null)) { if ((object)val5 == (object)val || SharesVisualBody((Behaviour)(object)val5, (Behaviour?)(object)val)) { ((Behaviour)val5).enabled = true; } else { SilencePackExtra((Behaviour)(object)val5, packRoot); } } } return val; } private static void SilencePackExtra(Behaviour unit, GameObject packRoot) { if ((Object)(object)unit == (Object)null) { return; } unit.enabled = false; Enemy val = null; try { val = ((Component)unit).GetComponent() ?? ((Component)unit).GetComponentInParent(); } catch { } EnemyParent val2 = null; try { val2 = (((Object)(object)val != (Object)null) ? val.EnemyParent : ((Component)unit).GetComponentInParent()); } catch { } EnemyParent val3 = null; try { val3 = (((Object)(object)packRoot != (Object)null) ? (packRoot.GetComponent() ?? packRoot.GetComponentInParent()) : null); } catch { } if ((Object)(object)val2 != (Object)null && (Object)(object)val2 != (Object)(object)val3) { DirectorEnemyDeathGuard.PreventRespawn(val2); ((Component)val2).gameObject.SetActive(false); return; } GameObject val4 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : ((Component)unit).gameObject); if ((Object)(object)packRoot != (Object)null && (Object)(object)val4 == (Object)(object)packRoot) { HideRenderersAndColliders((Component)(object)unit); } else { val4.SetActive(false); } } private static void HideRenderersAndColliders(Component unit) { Renderer[] componentsInChildren = unit.GetComponentsInChildren(true); foreach (Renderer val in componentsInChildren) { if ((Object)(object)val != (Object)null) { val.enabled = false; } } Collider[] componentsInChildren2 = unit.GetComponentsInChildren(true); foreach (Collider val2 in componentsInChildren2) { if ((Object)(object)val2 != (Object)null) { val2.enabled = false; } } } private static void BindBangPack(GameObject pack, Vector3 position, EnemyBang? keep) { //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_012e: Unknown result type (might be due to invalid IL or missing references) //IL_017b: Unknown result type (might be due to invalid IL or missing references) //IL_014f: Unknown result type (might be due to invalid IL or missing references) //IL_01a4: Unknown result type (might be due to invalid IL or missing references) //IL_0196: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pack == (Object)null) { return; } EnemyBangDirector val = EnsureBangDirector(pack); if ((Object)(object)val == (Object)null) { ModLog.Warn("Bang spawn: no EnemyBangDirector singleton"); return; } val.debugOneOnly = false; if ((Object)(object)keep == (Object)null) { return; } EnemyBang[] componentsInChildren = pack.GetComponentsInChildren(true); foreach (EnemyBang val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2 != keep && !SharesVisualBody((Behaviour)(object)val2, (Behaviour?)(object)keep)) { SilencePackExtra((Behaviour)(object)val2, pack); } } TrackAllEnemies(((Component)keep).gameObject); try { val.SetupSingle(keep); } catch (Exception ex) { ModLog.Debug("Bang SetupSingle: " + ex.Message); } ActivateBangFullBody(keep); try { if (SemiFunc.IsMultiplayer() && (Object)(object)keep.photonView != (Object)null) { keep.photonView.RPC("SetHeadRPC", (RpcTarget)0, new object[1] { 0 }); } } catch { } ActivateBangFullBody(keep); EnsureUnitOnDirector(val.units, val.destinations, keep, position); PruneDirectorList(val.units, val.destinations, keep); keep.directorIndex = 0; val.setup = true; val.debugOneOnly = false; DetachDirectorFromPack((Component)(object)val, pack); EnsureParentInDirectorList(pack); if (DestinationsTooClose(val.destinations, position)) { KickDirectorWalk((Component)(object)val, val.units?.Count ?? 0, val.destinations, position); } try { val.OnSpawn(keep); } catch (Exception ex2) { ModLog.Debug("Bang OnSpawn: " + ex2.Message); } try { if ((int)keep.currentState == 0) { WarpPackAgent(keep.enemy, ((Object)(object)keep.enemy != (Object)null) ? ((Component)keep.enemy).transform.position : position); } } catch { } EnemyLifetimeGuard.ArmKillable(pack); } private static bool SharesVisualBody(Behaviour unit, Behaviour? keep) { if ((Object)(object)unit == (Object)null || (Object)(object)keep == (Object)null) { return false; } try { if (((Component)unit).transform.IsChildOf(((Component)keep).transform) || ((Component)keep).transform.IsChildOf(((Component)unit).transform)) { return true; } Enemy val = ((Component)unit).GetComponent() ?? ((Component)unit).GetComponentInParent(); Enemy val2 = ((Component)keep).GetComponent() ?? ((Component)keep).GetComponentInParent(); return (Object)(object)val != (Object)null && val == val2; } catch { return false; } } private static void ActivateBangFullBody(EnemyBang? bang) { if ((Object)(object)bang == (Object)null) { return; } try { ((Component)bang).gameObject.SetActive(true); } catch { } try { ((Behaviour)bang).enabled = true; } catch { } GameObject val = null; GameObject[] headObjects = bang.headObjects; if (headObjects != null) { GameObject[] array = headObjects; foreach (GameObject val2 in array) { if (!((Object)(object)val2 == (Object)null) && (val2.activeSelf || val2.activeInHierarchy)) { val = val2; break; } } if ((Object)(object)val == (Object)null) { GameObject[] array2 = headObjects; foreach (GameObject val3 in array2) { if (!((Object)(object)val3 == (Object)null)) { val = val3; break; } } } GameObject[] array3 = headObjects; foreach (GameObject val4 in array3) { if (!((Object)(object)val4 == (Object)null)) { try { val4.SetActive(val4 == val); } catch { } } } } Renderer[] componentsInChildren = ((Component)bang).GetComponentsInChildren(true); foreach (Renderer val5 in componentsInChildren) { if ((Object)(object)val5 == (Object)null) { continue; } try { if (!((Component)val5).gameObject.activeSelf) { ((Component)val5).gameObject.SetActive(true); } val5.enabled = true; } catch { } } Transform[] componentsInChildren2 = ((Component)bang).GetComponentsInChildren(true); foreach (Transform val6 in componentsInChildren2) { if ((Object)(object)val6 == (Object)null || ((Component)val6).gameObject.activeSelf) { continue; } string text = ((Object)val6).name.ToLowerInvariant(); if (text.Contains("head") || text.Contains("body") || text.Contains("mesh") || text.Contains("model") || text.Contains("leg") || text.Contains("arm")) { try { ((Component)val6).gameObject.SetActive(true); } catch { } } } } private static void EnsureBangHeadVisible(EnemyBang? bang) { ActivateBangFullBody(bang); } private static void BindGnomePack(GameObject pack, Vector3 position, EnemyGnome? keep) { //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00df: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_0155: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)pack == (Object)null) { return; } EnemyGnomeDirector val = EnsureGnomeDirector(pack); if ((Object)(object)val == (Object)null) { ModLog.Warn("Gnome spawn: no EnemyGnomeDirector singleton"); return; } val.debugOneOnly = false; if ((Object)(object)keep == (Object)null) { return; } EnemyGnome[] componentsInChildren = pack.GetComponentsInChildren(true); foreach (EnemyGnome val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null) && val2 != keep) { SilencePackExtra((Behaviour)(object)val2, pack); } } TrackAllEnemies(((Component)keep).gameObject); try { val.SetupSingle(keep); } catch (Exception ex) { ModLog.Debug("Gnome SetupSingle: " + ex.Message); } EnsureUnitOnDirector(val.gnomes, val.destinations, keep, position); PruneDirectorList(val.gnomes, val.destinations, keep); keep.directorIndex = 0; val.setup = true; val.debugOneOnly = false; DetachDirectorFromPack((Component)(object)val, pack); EnsureParentInDirectorList(pack); if (DestinationsTooClose(val.destinations, position)) { KickDirectorWalk((Component)(object)val, val.gnomes?.Count ?? 0, val.destinations, position); } try { val.OnSpawn(keep); } catch (Exception ex2) { ModLog.Debug("Gnome OnSpawn: " + ex2.Message); } try { if ((int)keep.currentState == 0) { WarpPackAgent(keep.enemy, ((Object)(object)keep.enemy != (Object)null) ? ((Component)keep.enemy).transform.position : position); keep.UpdateState((State)1); } } catch { } EnemyLifetimeGuard.ArmKillable(pack); } private static void PruneDirectorList(List? units, List? destinations, T keep) where T : class { if (units == null) { return; } for (int num = units.Count - 1; num >= 0; num--) { if (units[num] != keep) { units.RemoveAt(num); if (destinations != null && num < destinations.Count) { destinations.RemoveAt(num); } } } } private static void EnsureParentInDirectorList(GameObject pack) { EnemyParent val = pack.GetComponent() ?? pack.GetComponentInParent(); EnemyDirector instance = EnemyDirector.instance; if (!((Object)(object)val == (Object)null) && instance?.enemiesSpawned != null && !instance.enemiesSpawned.Contains(val)) { instance.enemiesSpawned.Add(val); } } private static void EnsureUnitOnDirector(List? units, List? destinations, T keep, Vector3 position) where T : class { //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (units != null && keep != null && !units.Contains(keep)) { units.Add(keep); destinations?.Add(position); } } private static bool DestinationsTooClose(List? destinations, Vector3 from) { //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) if (destinations == null || destinations.Count == 0) { return true; } return Vector3.Distance(destinations[0], from) < 2.25f; } private static void KickDirectorWalk(Component director, int unitCount, List? destinations, Vector3 from) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: 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_00af: 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_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)director == (Object)null) { return; } Vector3 val = from; try { LevelPoint val2 = SemiFunc.LevelPointGet(from, 8f, 28f) ?? SemiFunc.LevelPointGet(from, 0f, 999f); if ((Object)(object)val2 != (Object)null) { val = ((Component)val2).transform.position; } else { Vector3 playerBodyPosition = SpawnHelper.GetPlayerBodyPosition(); Vector3 val3 = playerBodyPosition - from; if (((Vector3)(ref val3)).sqrMagnitude < 1f) { val3 = Vector3.forward; } val = from + ((Vector3)(ref val3)).normalized * 8f; } } catch { val = from + Vector3.forward * 8f; } if (!TryInvokeBool(director, "SetPosition", val)) { PlaceDirectorDestinations(director, unitCount, destinations, from, 5.5f); ModLog.Debug("Pack director: fallback roam destinations (SetPosition missed navmesh)"); } } private static void WarpPackAgent(Enemy? enemy, Vector3 position) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy?.NavMeshAgent == (Object)null) { return; } Vector3 val = position; NavMeshHit val2 = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val2, 8f, -1)) { val = ((NavMeshHit)(ref val2)).position; } try { enemy.NavMeshAgent.Warp(val, false); } catch { } try { enemy.NavMeshAgent.ResetPath(); } catch { } } private static void PlaceDirectorDestinations(Component director, int unitCount, List? destinations, Vector3 position, float roamRadius = 0.65f) { //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00e8: Unknown result type (might be due to invalid IL or missing references) //IL_00ed: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)director == (Object)null || destinations == null || unitCount <= 0) { return; } Vector3 val = position; NavMeshHit val2 = default(NavMeshHit); val = ((!NavMesh.SamplePosition(position, ref val2, 8f, -1)) ? SpawnHelper.SnapToFloor(position, 0.2f) : ((NavMeshHit)(ref val2)).position); if ((Object)(object)director.transform.parent == (Object)null || ((Object)(object)LevelGenerator.Instance?.EnemyParent != (Object)null && (Object)(object)director.transform.parent == (Object)(object)LevelGenerator.Instance.EnemyParent.transform)) { try { director.transform.position = val; } catch { } } while (destinations.Count < unitCount) { destinations.Add(val); } float num = Mathf.Max(roamRadius, 0.65f); NavMeshHit val5 = default(NavMeshHit); for (int i = 0; i < unitCount && i < destinations.Count; i++) { Vector3 val3 = Quaternion.Euler(0f, 360f / (float)unitCount * (float)i, 0f) * Vector3.forward * num; Vector3 val4 = val + val3; if (NavMesh.SamplePosition(val4, ref val5, 8f, -1)) { val4 = ((NavMeshHit)(ref val5)).position; } destinations[i] = val4; } } private static bool TryInvokeBool(Component comp, string methodName, Vector3 arg) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return false; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length != 1 || parameters[0].ParameterType != typeof(Vector3)) { return false; } object obj = method.Invoke(comp, new object[1] { arg }); return obj is bool && (bool)obj; } catch { return false; } } private static void TryInvoke(Component comp, string methodName, Vector3 arg) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null)) { ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1 && !(parameters[0].ParameterType != typeof(Vector3))) { method.Invoke(comp, new object[1] { arg }); } } } catch { } } private static void AttachNoRespawnGuard(GameObject instance) { EnemyParent component = instance.GetComponent(); Enemy componentInChildren = instance.GetComponentInChildren(true); if (!((Object)(object)component == (Object)null) && !((Object)(object)componentInChildren == (Object)null)) { DirectorEnemyDeathGuard directorEnemyDeathGuard = instance.GetComponent() ?? instance.AddComponent(); directorEnemyDeathGuard.Configure(component, componentInChildren); EnemyLifetimeGuard.Register(componentInChildren); } } private static void FinalizeCeilingEyeSpawn(GameObject instance, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) Vector3 position2 = ResolveCeilingSpawnPosition(position); ForceActivateEnemy(instance, position2); EnemyCeilingEye componentInChildren = instance.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { ((Component)componentInChildren).transform.position = position2; TryInvoke((Component)(object)componentInChildren, "OnSpawn"); TryInvokeEnum((Component)(object)componentInChildren, "UpdateState", "Spawn"); AttachNoRespawnGuard(instance); } } private static Vector3 ResolveCeilingSpawnPosition(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) Vector3 val = position + Vector3.up * 0.5f; RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.up, ref val2, 12f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val2)).point - Vector3.up * 0.15f; } return val + Vector3.up * 2.5f; } private static void FinalizeHeartHuggerSpawn(GameObject instance, Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: 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_002a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) Vector3 position2 = SpawnHelper.SnapToFloor(position, 0.2f); EnemyParent component = instance.GetComponent(); EnemyHeartHugger componentInChildren = instance.GetComponentInChildren(true); if ((Object)(object)component != (Object)null) { ((Component)component).transform.position = position2; } instance.transform.position = position2; if ((Object)(object)componentInChildren != (Object)null) { ((Component)componentInChildren).transform.position = position2; TryInvoke((Component)(object)componentInChildren, "StateSpawn"); TryInvoke((Component)(object)componentInChildren, "VisualStateNormal"); } if ((Object)(object)component != (Object)null) { EnemyDirector instance2 = EnemyDirector.instance; if (instance2 != null) { instance2.FirstSpawnPointAdd(component); } } AttachNoRespawnGuard(instance); } private static Vector3 SettleEnemyOnFloor(Vector3 position) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) NavMeshHit val = default(NavMeshHit); if (NavMesh.SamplePosition(position, ref val, 3f, -1)) { return ((NavMeshHit)(ref val)).position; } RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(position + Vector3.up * 0.6f, Vector3.down, ref val2, 3.5f, -1, (QueryTriggerInteraction)1)) { return ((RaycastHit)(ref val2)).point + Vector3.up * 0.2f; } return position; } private static void ForceActivateEnemy(GameObject instance, Vector3 position) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_018f: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) //IL_01bc: Unknown result type (might be due to invalid IL or missing references) //IL_01cc: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) instance.SetActive(true); Vector3 val = SettleEnemyOnFloor(position); EnemyParent component = instance.GetComponent(); Enemy componentInChildren = instance.GetComponentInChildren(true); if ((Object)(object)component != (Object)null) { try { FieldInfo field = typeof(EnemyParent).GetField("SetupDone", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(component, true); } else { component.SetupDone = true; } } catch { try { component.SetupDone = true; } catch { } } } if ((Object)(object)componentInChildren != (Object)null) { EnemySpawnTracker.Track(componentInChildren); ((Component)componentInChildren).gameObject.SetActive(true); try { foreach (PlayerAvatar item in PlayerTargeting.AllPlayers()) { if (!((Object)(object)item?.photonView == (Object)null)) { try { componentInChildren.PlayerAdded(item.photonView.ViewID); } catch { } } } } catch { } TryInvoke((Component)(object)componentInChildren, "Spawned"); componentInChildren.EnemyTeleported(val); ((Component)componentInChildren).transform.position = val; if (componentInChildren.HasNavMeshAgent && (Object)(object)componentInChildren.NavMeshAgent != (Object)null) { try { componentInChildren.NavMeshAgent.Warp(val, false); } catch { } try { componentInChildren.NavMeshAgent.ResetPath(); } catch { } } } if ((Object)(object)component != (Object)null) { ((Component)component).transform.position = val; try { component.Spawn(); } catch { TryInvoke((Component)(object)component, "Spawn"); } } instance.transform.position = val; if ((Object)(object)component != (Object)null) { EnemyDirector instance2 = EnemyDirector.instance; if (instance2 != null) { instance2.FirstSpawnPointAdd(component); } } AttachNoRespawnGuard(instance); EnemyLifetimeGuard.Register(componentInChildren); float num = Vector3.Distance(val, SpawnHelper.GetPlayerBodyPosition()); ModLog.Info($"Enemy activated at {val} ({num:F1}m from player)"); } private static void RegisterSpawnedEnemy(Enemy? enemy, Vector3 grounded) { //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)enemy == (Object)null) { return; } EnemySpawnTracker.Track(enemy); ((Component)enemy).gameObject.SetActive(true); try { foreach (PlayerAvatar item in PlayerTargeting.AllPlayers()) { if (!((Object)(object)item?.photonView == (Object)null)) { try { enemy.PlayerAdded(item.photonView.ViewID); } catch { } } } } catch { } TryInvoke((Component)(object)enemy, "Spawned"); enemy.EnemyTeleported(grounded); ((Component)enemy).transform.position = grounded; } private static void TryInvoke(Component comp, string methodName) { try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 0) { method.Invoke(comp, null); } } catch { } } private static void TryInvokeEnum(Component comp, string methodName, string enumValueName) { try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 1) { Type parameterType = method.GetParameters()[0].ParameterType; if (parameterType.IsEnum) { object obj = Enum.Parse(parameterType, enumValueName); method.Invoke(comp, new object[1] { obj }); } } } catch { } } private static void TrySetBoolField(Component comp, string fieldName) { try { FieldInfo field = ((object)comp).GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null) && !(field.FieldType != typeof(bool))) { field.SetValue(comp, true); } } catch { } } private static void LogSpawnDiagnostics(string targetName) { int num = Enemies.AllEnemies?.Count ?? 0; ModLog.Warn($"Enemy spawn failed: '{targetName}' | REPOLib={num} | RunManager={(Object)(object)RunManager.instance != (Object)null} | MenuLevel={SemiFunc.MenuLevel()}"); if (num > 0) { string text = string.Join(", ", from s in Enemies.AllEnemies.Where((EnemySetup s) => (Object)(object)s != (Object)null).Take(16) select ((Object)s).name); ModLog.Info("REPOLib names: " + text); } } } internal static class EnemySpawnTracker { private static readonly HashSet ForceSpawn = new HashSet(); private static readonly HashSet BlockDespawn = new HashSet(); public static void Track(Enemy? enemy) { if (!((Object)(object)enemy == (Object)null)) { ForceSpawn.Add(enemy); BlockDespawn.Add(enemy); } } public static void Clear() { ForceSpawn.Clear(); BlockDespawn.Clear(); } public static bool TryConsumeForceSpawn(Enemy? enemy) { if ((Object)(object)enemy == (Object)null) { return false; } if (!ForceSpawn.Contains(enemy)) { return false; } ForceSpawn.Remove(enemy); EnemyLifetimeGuard.Register(enemy); return true; } public static bool TryBlockDespawn(Enemy? enemy, out float spawnedTimeMax) { spawnedTimeMax = 0f; if ((Object)(object)enemy == (Object)null) { return false; } if (!BlockDespawn.Contains(enemy)) { return false; } BlockDespawn.Remove(enemy); return true; } } [HarmonyPatch(typeof(SemiFunc), "EnemySpawn")] internal static class SemiFuncEnemySpawnPatch { [HarmonyPrefix] private static bool Prefix(ref bool __result, Enemy enemy) { if (!EnemySpawnTracker.TryConsumeForceSpawn(enemy)) { return true; } __result = true; return false; } } [HarmonyPatch(typeof(EnemyParent), "Despawn")] internal static class EnemyParentDespawnPatch { [HarmonyPrefix] private static bool Prefix(Enemy ___Enemy, float ___SpawnedTimeMax, ref float ___SpawnedTimer) { if (!EnemySpawnTracker.TryBlockDespawn(___Enemy, out var _)) { return true; } if (___SpawnedTimeMax > 0f) { ___SpawnedTimer = ___SpawnedTimeMax; } ModLog.Debug("Blocked early despawn for '" + ((___Enemy != null) ? ((Object)___Enemy).name : null) + "'"); return false; } } [HarmonyPatch(typeof(EnemyParent), "Spawn")] internal static class EnemyParentSpawnPatch { [HarmonyPrefix] private static bool Prefix(EnemyParent __instance) { if (!DirectorEnemyDeathGuard.ShouldBlockSpawn(__instance)) { return true; } ModLog.Debug("Blocked post-death spawn for '" + ((__instance != null) ? ((Object)__instance).name : null) + "'"); return false; } } [HarmonyPatch(typeof(EnemyGnome), "OnDeath")] internal static class EnemyGnomeOnDeathPatch { [HarmonyPostfix] private static void Postfix(EnemyGnome __instance) { try { EnemyParent val = __instance?.enemy?.EnemyParent; DirectorEnemyDeathGuard.PreventRespawn(val); if ((Object)(object)__instance == (Object)null) { return; } GameObject val2 = (((Object)(object)val != (Object)null) ? ((Component)val).gameObject : ((Component)((Component)__instance).transform.root).gameObject); EnemyGnome[] componentsInChildren = val2.GetComponentsInChildren(true); foreach (EnemyGnome val3 in componentsInChildren) { if (!((Object)(object)val3 == (Object)null) && val3 != __instance) { ((Component)val3).gameObject.SetActive(false); if ((Object)(object)val3.enemy?.EnemyParent != (Object)null && (Object)(object)val3.enemy.EnemyParent != (Object)(object)val) { DirectorEnemyDeathGuard.PreventRespawn(val3.enemy.EnemyParent); ((Component)val3.enemy.EnemyParent).gameObject.SetActive(false); } } } } catch { } } } [HarmonyPatch(typeof(EnemyDirector), "SetInvestigate")] internal static class EnemyDirectorSetInvestigatePatch { [HarmonyFinalizer] private static Exception? Finalizer(Exception? __exception) { if (__exception == null) { return null; } ModLog.Debug("SetInvestigate ignored: " + __exception.GetType().Name + ": " + __exception.Message); return null; } } [HarmonyPatch(typeof(EnemyStateInvestigate), "Set")] internal static class EnemyStateInvestigateSetPatch { [HarmonyPrefix] private static bool Prefix(EnemyStateInvestigate __instance) { try { if ((Object)(object)__instance == (Object)null) { return false; } Enemy componentInParent = ((Component)__instance).GetComponentInParent(true); if ((Object)(object)componentInParent == (Object)null) { return false; } if (!((Behaviour)componentInParent).isActiveAndEnabled) { return false; } if (!((Component)componentInParent).gameObject.activeInHierarchy) { return false; } if (!componentInParent.HasStateInvestigate) { return false; } if (!componentInParent.HasNavMeshAgent) { return false; } return true; } catch { return false; } } } [HarmonyPatch(typeof(EnemyBangDirector), "Awake")] internal static class EnemyBangDirectorAwakePatch { [HarmonyPrefix] private static bool Prefix(EnemyBangDirector __instance) { try { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)__instance) { EnemyBangDirector.instance = __instance; ((Behaviour)__instance).enabled = true; __instance.debugOneOnly = false; return false; } ((Behaviour)__instance).enabled = false; __instance.debugOneOnly = false; return false; } catch { EnemyBangDirector.instance = __instance; return false; } } } [HarmonyPatch(typeof(EnemyGnomeDirector), "Awake")] internal static class EnemyGnomeDirectorAwakePatch { [HarmonyPrefix] private static bool Prefix(EnemyGnomeDirector __instance) { try { EnemyGnomeDirector instance = EnemyGnomeDirector.instance; if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)__instance) { EnemyGnomeDirector.instance = __instance; ((Behaviour)__instance).enabled = true; __instance.debugOneOnly = false; return false; } ((Behaviour)__instance).enabled = false; __instance.debugOneOnly = false; return false; } catch { EnemyGnomeDirector.instance = __instance; return false; } } } [HarmonyPatch(typeof(EnemyBang), "Start")] internal static class EnemyBangStartPatch { [HarmonyPrefix] private static bool Prefix(EnemyBang __instance) { try { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance != (Object)null && instance.setup) { instance.SetupSingle(__instance); } } catch { } return false; } } [HarmonyPatch(typeof(EnemyGnome), "Start")] internal static class EnemyGnomeStartPatch { [HarmonyPrefix] private static bool Prefix(EnemyGnome __instance) { try { if ((Object)(object)__instance?.enemy?.NavMeshAgent != (Object)null) { float num = Random.Range(__instance.speedMin, __instance.speedMax); __instance.enemy.NavMeshAgent.DefaultSpeed = num; if ((Object)(object)__instance.enemy.NavMeshAgent.Agent != (Object)null) { __instance.enemy.NavMeshAgent.Agent.speed = num; } } EnemyGnomeDirector instance = EnemyGnomeDirector.instance; if ((Object)(object)instance != (Object)null && instance.setup) { instance.SetupSingle(__instance); } } catch { } return false; } } [HarmonyPatch(typeof(EnemyBang), "OnVision")] internal static class EnemyBangOnVisionPatch { [HarmonyPrefix] private static bool Prefix() { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance != (Object)null) { return instance.setup; } return false; } } [HarmonyPatch(typeof(EnemyBang), "OnInvestigate")] internal static class EnemyBangOnInvestigatePatch { [HarmonyPrefix] private static bool Prefix() { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance != (Object)null) { return instance.setup; } return false; } } [HarmonyPatch(typeof(EnemyBangDirector), "SetupSingle")] internal static class EnemyBangDirectorSetupSinglePatch { [HarmonyPrefix] private static void Prefix(EnemyBangDirector __instance) { if ((Object)(object)__instance != (Object)null) { __instance.debugOneOnly = false; } } } [HarmonyPatch(typeof(EnemyGnomeDirector), "SetupSingle")] internal static class EnemyGnomeDirectorSetupSinglePatch { [HarmonyPrefix] private static void Prefix(EnemyGnomeDirector __instance) { if ((Object)(object)__instance != (Object)null) { __instance.debugOneOnly = false; } } } [HarmonyPatch(typeof(EnemyBang), "RotationLogic")] internal static class EnemyBangRotationLogicPatch { [HarmonyPrefix] private static bool Prefix(EnemyBang __instance) { try { if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.enemy == (Object)null || (Object)(object)__instance.enemy.Rigidbody == (Object)null) { return false; } if ((Object)(object)__instance.rotationTransform == (Object)null) { return false; } return (Object)(object)EnemyBangDirector.instance != (Object)null; } catch { return false; } } } [HarmonyPatch(typeof(EnemyBang), "FuseLogic")] internal static class EnemyBangFuseLogicPatch { [HarmonyPrefix] private static bool Prefix() { return (Object)(object)EnemyBangDirector.instance != (Object)null; } } [HarmonyPatch(typeof(EnemyBang), "MoveOffsetLogic")] internal static class EnemyBangMoveOffsetLogicPatch { [HarmonyPrefix] private static bool Prefix(EnemyBang __instance) { try { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance == (Object)null || (Object)(object)__instance?.enemy?.Rigidbody == (Object)null) { return false; } List destinations = instance.destinations; if (destinations == null || __instance.directorIndex < 0 || __instance.directorIndex >= destinations.Count) { return false; } return true; } catch { return false; } } } [HarmonyPatch(typeof(EnemyBang), "StateIdle")] internal static class EnemyBangStateIdlePatch { [HarmonyPrefix] private static bool Prefix(EnemyBang __instance) { try { EnemyBangDirector instance = EnemyBangDirector.instance; if ((Object)(object)instance == (Object)null || !instance.setup) { return false; } if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.enemy == (Object)null) { return false; } List destinations = instance.destinations; if (destinations == null || __instance.directorIndex < 0 || __instance.directorIndex >= destinations.Count) { return false; } return true; } catch { return false; } } } [HarmonyPatch(typeof(EnemyGnome), "OnVision")] internal static class EnemyGnomeOnVisionPatch { [HarmonyPrefix] private static bool Prefix() { if ((Object)(object)EnemyGnomeDirector.instance != (Object)null) { return EnemyGnomeDirector.instance.setup; } return false; } } [HarmonyPatch(typeof(EnemyBang), "OnSpawn")] internal static class EnemyBangOnSpawnPatch { [HarmonyPrefix] private static bool Prefix() { return (Object)(object)EnemyBangDirector.instance != (Object)null; } } [HarmonyPatch(typeof(EnemyGnome), "OnSpawn")] internal static class EnemyGnomeOnSpawnPatch { [HarmonyPrefix] private static bool Prefix() { return (Object)(object)EnemyGnomeDirector.instance != (Object)null; } } internal static class EventCommandCatalog { private static Dictionary? _map; private static bool _loaded; private static readonly Dictionary LocalExtras = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["solo_toycars_around"] = "spawn_toycars_around 5", ["solo_toyplanes_around"] = "spawn_toyplanes_around 5", ["solo_chomp_book"] = "spawn_chomp_book", ["solo_debuff_kill_named"] = "explode_player", ["all_debuff_kill_named"] = "explode_player", ["solo_debuff_crouch"] = "hold_input 60 Crouch", ["solo_poop_shock_mines"] = "spawn_items_from_player Item_Mine_Shockwave 15 1 0.3 1 1", ["spawn_ceiling_eye"] = "spawn_enemy Ceiling_Eye", ["spawn_gnome"] = "spawn_enemy Gnome", ["spawn_bang"] = "spawn_enemy Bang", ["active_nade_stun"] = "tok_active_nade stun", ["active_nade_shock"] = "tok_active_nade shock", ["active_nade_expl"] = "tok_active_nade expl", ["active_nade_duck"] = "tok_active_nade duck", ["all_speak_random"] = "all_players_speak", ["all_nade_burst"] = "nade_from_all_players expl 1", ["all_nade_duck"] = "nade_from_all_players duck 2", ["all_debuff_hurt"] = "slap_all_room 10; rel_force_move -15 0" }; public static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; _map = new Dictionary(StringComparer.OrdinalIgnoreCase); try { string text = ResolveDataPath("commands.data"); if (text != null && File.Exists(text)) { ParseCommandsFile(File.ReadAllText(text)); ModLog.Info($"Loaded {_map.Count} event commands from {text}"); } else { ModLog.Warn("commands.data not found — using built-in fallback map"); SeedFallbackFromRepoEventMap(); } } catch (Exception ex) { ModLog.Warn("commands.data load failed: " + ex.Message); SeedFallbackFromRepoEventMap(); } foreach (KeyValuePair localExtra in LocalExtras) { _map[localExtra.Key] = localExtra.Value; } } public static bool TryGetCommandLine(string eventId, out string commandLine) { EnsureLoaded(); commandLine = ""; if (string.IsNullOrWhiteSpace(eventId)) { return false; } string key = Normalize(eventId); return _map.TryGetValue(key, out commandLine); } public static bool HasEvent(string eventId) { EnsureLoaded(); if (!string.IsNullOrWhiteSpace(eventId)) { return _map.ContainsKey(Normalize(eventId)); } return false; } private static string Normalize(string value) { value = value.Trim().ToLowerInvariant().Replace(' ', '_'); while (value.StartsWith("repo_", StringComparison.Ordinal)) { value = value.Substring(5); } return value; } private static void ParseCommandsFile(string json) { foreach (Match item in Regex.Matches(json, "\"([^\"]+)\"\\s*:\\s*\"([^\"]*)\"")) { string text = item.Groups[1].Value.Trim(); string text2 = item.Groups[2].Value.Trim(); if (text.Length != 0 && text2.Length != 0 && !(text == "test_event")) { _map[text] = text2; } } } private static void SeedFallbackFromRepoEventMap() { foreach (KeyValuePair localExtra in LocalExtras) { _map[localExtra.Key] = localExtra.Value; } if (RepoEventMap.TryGetEffectCommand("solo_buff_heal", out string commandLine)) { _map["solo_buff_heal"] = commandLine; } } private static string? ResolveDataPath(string fileName) { try { string location = Assembly.GetExecutingAssembly().Location; if (!string.IsNullOrEmpty(location)) { string directoryName = Path.GetDirectoryName(location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, fileName); if (File.Exists(text)) { return text; } string text2 = Path.Combine(directoryName, "Data", fileName); if (File.Exists(text2)) { return text2; } } } } catch { } try { string text3 = Path.Combine(Paths.PluginPath, "TokControlREPOBridge", "Data", fileName); if (File.Exists(text3)) { return text3; } } catch { } return null; } } internal static class EventContext { private static int _stickyViewId; public static PlayerAvatar? TargetPlayer { get; private set; } public static int StackCount { get; private set; } = 1; public static void SetTarget(PlayerAvatar? player) { TargetPlayer = player; _stickyViewId = 0; try { if ((Object)(object)player?.photonView != (Object)null) { _stickyViewId = player.photonView.ViewID; } } catch { } } public static void SetStackCount(int count) { StackCount = Mathf.Max(1, Mathf.Min(count, 100)); } public static void Clear() { TargetPlayer = null; StackCount = 1; } public static PlayerAvatar? SoloTarget() { if (IsUsable(TargetPlayer)) { return TargetPlayer; } if (_stickyViewId > 0) { try { PlayerAvatar val = SemiFunc.PlayerAvatarGetFromPhotonID(_stickyViewId); if (IsUsable(val)) { TargetPlayer = val; return val; } } catch { } } return SemiFunc.PlayerAvatarLocal(); } private static bool IsUsable(PlayerAvatar? player) { if ((Object)(object)player == (Object)null) { return false; } try { return (Object)(object)((Component)player).gameObject != (Object)null; } catch { return false; } } } internal static class EventLangCatalog { private static Dictionary? _en; private static bool _loaded; public static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; _en = new Dictionary(StringComparer.OrdinalIgnoreCase); try { string text = ResolveDataPath("langs.data"); if (text == null || !File.Exists(text)) { ModLog.Warn("langs.data not found — using formatted event ids"); return; } string input = File.ReadAllText(text); foreach (Match item in Regex.Matches(input, "\"([^\"]+)\"\\s*:\\s*\\{[^}]*?\"en\"\\s*:\\s*\"([^\"]*)\"", RegexOptions.Singleline)) { string text2 = item.Groups[1].Value.Trim(); string text3 = item.Groups[2].Value.Trim(); if (text2.Length != 0 && text3.Length != 0 && !text2.StartsWith("%", StringComparison.Ordinal)) { _en[text2] = text3; } } ModLog.Info($"Loaded {_en.Count} event labels from {text}"); } catch (Exception ex) { ModLog.Warn("langs.data load failed: " + ex.Message); } } public static string GetLabel(string eventId) { EnsureLoaded(); if (string.IsNullOrWhiteSpace(eventId)) { return "event"; } string text = eventId.Trim().ToLowerInvariant(); while (text.StartsWith("repo_", StringComparison.Ordinal)) { text = text.Substring(5); } if (_en.TryGetValue(text, out string value) && !string.IsNullOrWhiteSpace(value)) { return value; } return Titleize(text); } private static string Titleize(string id) { string[] array = id.Replace('_', ' ').Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (array[i].Length != 0) { array[i] = char.ToUpperInvariant(array[i][0]) + array[i].Substring(1); } } return string.Join(" ", array); } private static string? ResolveDataPath(string fileName) { try { string location = Assembly.GetExecutingAssembly().Location; if (!string.IsNullOrEmpty(location)) { string directoryName = Path.GetDirectoryName(location); if (!string.IsNullOrEmpty(directoryName)) { string text = Path.Combine(directoryName, fileName); if (File.Exists(text)) { return text; } string text2 = Path.Combine(directoryName, "Data", fileName); if (File.Exists(text2)) { return text2; } } } } catch { } try { string text3 = Path.Combine(Paths.PluginPath, "TokControlREPOBridge", "Data", fileName); if (File.Exists(text3)) { return text3; } } catch { } return null; } } internal sealed class FrogHopBehavior : MonoBehaviour { private Rigidbody? _rb; private float _nextHop; private float _duration = 120f; private float _elapsed; private bool _wasAirborne; public void Configure(float durationSeconds = 120f) { _duration = Mathf.Max(10f, durationSeconds); _rb = ((Component)this).GetComponentInChildren(); _nextHop = Random.Range(0.4f, 1f); if ((Object)(object)_rb != (Object)null) { _rb.isKinematic = false; _rb.WakeUp(); } } private void FixedUpdate() { //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0138: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0142: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rb == (Object)null || ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { Object.Destroy((Object)(object)this); return; } bool flag = IsGrounded(); if (flag && _wasAirborne) { ValuableDamageHelper.ApplyImpactDamage(((Component)this).gameObject, 0.18f); if (ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); return; } } _wasAirborne = !flag; _nextHop -= Time.fixedDeltaTime; if (!(_nextHop > 0f) && flag && !(_rb.velocity.y > 1.5f)) { _nextHop = Random.Range(1.1f, 2f); Vector3 forward = ((Component)this).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.forward; } ((Vector3)(ref forward)).Normalize(); Vector3 val = forward * Random.Range(1.2f, 2.4f) + Vector3.up * Random.Range(2.8f, 4.2f); _rb.AddForce(val, (ForceMode)1); } } private bool IsGrounded() { //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_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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) Vector3 val = ((Component)this).transform.position + Vector3.up * 0.15f; return Physics.Raycast(val, Vector3.down, 0.55f, -5, (QueryTriggerInteraction)1); } } internal static class HostEventPolicy { private static readonly HashSet MustRunOnHost = new HashSet(StringComparer.OrdinalIgnoreCase) { "solo_buff_resurrect", "all_buff_resurrect_rand", "all_buff_resurrect_all", "all_buff_hp_average", "all_goal_dec", "all_goal_inc", "all_debuff_kill_rand", "all_debuff_kill_named", "solo_debuff_kill_named", "all_debuff_hurt", "all_cart_spread", "active_nade_stun", "active_nade_shock", "active_nade_expl", "active_nade_duck", "spawn_duck", "spawn_spewer", "spawn_upscream", "spawn_alien", "spawn_animal", "spawn_baby", "spawn_thinman", "spawn_hidden", "spawn_frog", "spawn_bowtie", "spawn_huntsman", "spawn_head", "spawn_trudge", "spawn_clown", "spawn_robe", "spawn_reaper", "spawn_dogo", "spawn_tick", "spawn_birthday_boy", "spawn_gambit", "spawn_headgrab", "spawn_heart_hugger", "spawn_cleanup_crew", "spawn_bella", "spawn_oogly", "spawn_loom", "item_health_small", "item_health_med", "item_health_big", "item_crystal", "item_nade_stun", "item_nade_shock", "item_nade_expl", "item_nade_f1", "item_nade_duck_f1", "item_mine_stun", "item_mine_shock", "item_mine_expl", "item_rubber_duck", "item_book_roll", "item_book_speed", "item_book_energy", "item_book_health", "item_book_range", "item_book_strength", "item_book_jump", "item_book_wings", "item_book_rest", "item_book_battery", "item_book_climb", "item_drone_roll", "item_drone_gravity", "item_drone_feather", "item_drone_energy", "item_drone_shield", "item_sphere_gravity", "item_frying_pan", "item_inflatable_hammer", "item_sword", "item_baseball_bat", "item_sledge_hammer", "item_valuable_tracker", "item_extraction_tracker", "item_cart_small", "item_cart_medium", "item_cart_cannon", "item_cart_laser", "item_cart_scooter", "item_cart_scooter_small", "item_tranq", "item_handgun", "item_shotgun", "item_duck_bucket", "item_melee_prodzap", "item_gun_boltzap", "item_gun_pulse", "item_bridge", "item_photon_blaster", "item_staff_gravity", "item_staff_torque", "item_staff_void", "item_walkie_talkie", "item_revive", "loot_rand_small", "loot_rand_med", "loot_rand_big", "loot_rand_huge", "loot_rand_enemy", "loot_rand_beta_small", "loot_rand_beta_med", "loot_money_rain", "loot_frog", "loot_bottle", "loot_love_potion", "loot_gramophone", "loot_power_crystal", "loot_fan", "loot_clown", "loot_guitar", "loot_propane_tank", "loot_music_box", "loot_television", "loot_flamethrower", "loot_saw", "loot_time_glass", "loot_doll", "loot_barrel", "loot_sword", "loot_staff", "loot_animal_crate", "loot_creature_leg", "loot_ice_block", "loot_broom", "loot_painting", "loot_harp", "loot_grandfather_clock", "loot_golden_statue", "loot_science_station", "loot_server_rack", "loot_dinosaur", "loot_griffin_statue", "loot_piano", "loot_mug_deluxe", "loot_baby_head", "loot_gem_burger", "loot_ac_gumball", "loot_ac_boombox", "loot_milk", "loot_golden_swirl", "loot_ac_blender", "loot_horse", "loot_ac_trafic_light", "loot_star_wand", "loot_lev_potion", "loot_jackhammer", "loot_coffin", "loot_tray", "loot_dragon_skull", "solo_frogs_around", "solo_chomp_book", "solo_poop_diamonds", "solo_poop_mines", "solo_poop_nades", "all_stun_enemies", "all_cart_teleport_rand", "all_cart_teleport_start", "all_teleport_rand", "solo_teleport_rand", "solo_teleport_start", "all_teleport_start", "all_teleport_shuffle", "solo_upgrade_roll", "solo_upgrade_speed", "solo_upgrade_energy", "solo_upgrade_health", "solo_upgrade_range", "solo_upgrade_strength", "solo_upgrade_jump", "solo_upgrade_wings", "solo_upgrade_rest", "solo_toycars_around", "solo_toyplanes_around", "solo_poop_shock_mines", "all_nade_burst", "all_nade_duck", "all_speak_random", "spawn_ceiling_eye", "spawn_gnome", "spawn_bang", "spawn_item", "spawn_enemy", "spawn_ghost", "spawn_valuable", "spawn_batch" }; public static bool MustRunFromHost(string eventOrCmd) { if (string.IsNullOrWhiteSpace(eventOrCmd)) { return false; } string text = eventOrCmd.Trim().ToLowerInvariant(); while (text.StartsWith("repo_", StringComparison.Ordinal)) { text = text.Substring(5); } return MustRunOnHost.Contains(text); } } internal static class ImpactLaunchHelper { public static void PrepareForImpactBreak(GameObject go) { PhysGrabObjectImpactDetector componentInChildren = go.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.destroyDisable = false; componentInChildren.destroyDisableTeleport = false; componentInChildren.indestructibleBreakEffects = false; TrySetField(componentInChildren, "isIndestructible", false); TrySetField(componentInChildren, "indestructibleSpawnTimer", 0f); TrySetField(componentInChildren, "impulseTimerDeactivateImpacts", 0f); TrySetField(componentInChildren, "impactDisable", false); } } public static void LaunchBackwardBurst(GameObject go, PlayerAvatar player, float force) { //IL_0029: 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_003f: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInChildren = go.GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null) && !((Object)(object)player == (Object)null)) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); componentInChildren.position = GetRearSpawnPosition(player); componentInChildren.velocity = Vector3.zero; componentInChildren.angularVelocity = Vector3.zero; ((MonoBehaviour)EffectTimerHost.Instance).StartCoroutine(LaunchBurstRoutine(componentInChildren, ((Component)player).transform, force)); } } private static IEnumerator LaunchBurstRoutine(Rigidbody rb, Transform playerTransform, float force) { yield return null; Vector3 val = -playerTransform.forward; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = playerTransform.forward * -1f; } ((Vector3)(ref val)).Normalize(); Vector3 launch = val * force; for (int i = 0; i < 3; i++) { if ((Object)(object)rb == (Object)null) { break; } rb.AddTorque(Random.insideUnitSphere * 2f, (ForceMode)1); rb.AddForce(launch, (ForceMode)1); yield return (object)new WaitForSeconds(0.2f); } } private static Vector3 GetRearSpawnPosition(PlayerAvatar player) { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)player).transform.forward; Vector3 val = -((Vector3)(ref forward)).normalized; return ((Component)player).transform.position + val * 0.55f + Vector3.up * 0.75f; } private static void TrySetField(object target, string fieldName, object value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { field.SetValue(target, value); } } catch (Exception ex) { ModLog.Debug("ImpactLaunchHelper field " + fieldName + ": " + ex.Message); } } } internal static class ItemPostSpawnHelper { internal static void Initialize(GameObject instance, string? assetName, int scatterIndex = 0, bool holdInPlace = false, bool skipGrenadeDormant = false) { if (!((Object)(object)instance == (Object)null)) { EnsureGrabbable(instance); EnsureUsable(instance); RegisterItemInGame(assetName ?? ((Object)instance).name); ChargeItem(instance, 0.5f); if (holdInPlace) { HoldInPlace(instance); ((MonoBehaviour)EffectTimerHost.Instance).StartCoroutine(ReleaseHoldAfterSettle(instance)); } else { ScatterForward(instance, scatterIndex); } if (!skipGrenadeDormant && (Object)(object)instance.GetComponentInChildren(true) != (Object)null) { ThrowableHelper.PreparePickupGrenade(instance); } } } private static IEnumerator ReleaseHoldAfterSettle(GameObject instance) { yield return (object)new WaitForSeconds(0.18f); if (!((Object)(object)instance == (Object)null)) { ReleaseHold(instance); EnsureUsable(instance); if ((Object)(object)instance.GetComponentInChildren(true) != (Object)null) { ThrowableHelper.PreparePickupGrenade(instance); } } } public static void EnsureUsablePublic(GameObject instance) { EnsureUsable(instance); } private static void EnsureUsable(GameObject instance) { PhysGrabObject[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (PhysGrabObject val in componentsInChildren) { try { ((Behaviour)val).enabled = true; FieldInfo field = typeof(PhysGrabObject).GetField("spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(val, true); } } catch { } } ItemToggle[] componentsInChildren2 = instance.GetComponentsInChildren(true); foreach (ItemToggle val2 in componentsInChildren2) { ((Behaviour)val2).enabled = true; } ItemEquippable[] componentsInChildren3 = instance.GetComponentsInChildren(true); foreach (ItemEquippable val3 in componentsInChildren3) { ((Behaviour)val3).enabled = true; } } public static void ScatterForward(GameObject instance, int scatterIndex = 0) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInChildren = instance.GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); float num = (float)scatterIndex * 18f - 9f; Vector3 playerBodyForward = SpawnHelper.GetPlayerBodyForward(); Vector3 val = Quaternion.Euler(0f, num, 0f) * playerBodyForward; Vector3 normalized = ((Vector3)(ref val)).normalized; normalized.y = 0.1f; componentInChildren.velocity = normalized * Random.Range(2.2f, 3.6f); componentInChildren.angularVelocity = Random.insideUnitSphere * 1.5f; } } public static void HoldInPlace(GameObject instance) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) Rigidbody[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (Rigidbody val in componentsInChildren) { val.velocity = Vector3.zero; val.angularVelocity = Vector3.zero; val.isKinematic = true; } } public static void ReleaseHold(GameObject instance) { Rigidbody[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (Rigidbody val in componentsInChildren) { val.isKinematic = false; val.WakeUp(); } } private static void EnsureGrabbable(GameObject instance) { instance.SetActive(true); PhysGrabObject[] componentsInChildren = instance.GetComponentsInChildren(true); foreach (PhysGrabObject val in componentsInChildren) { ((Behaviour)val).enabled = true; } } private static void RegisterItemInGame(string assetName) { if (string.IsNullOrWhiteSpace(assetName) || !assetName.StartsWith("Item ")) { return; } try { StatsManager instance = StatsManager.instance; if (instance?.itemDictionary != null && instance.itemDictionary.ContainsKey(assetName)) { if (instance.itemsPurchased.TryGetValue(assetName, out var value)) { instance.itemsPurchased[assetName] = value + 1; } else { instance.itemsPurchased[assetName] = 1; } if (instance.itemsPurchasedTotal.TryGetValue(assetName, out var value2)) { instance.itemsPurchasedTotal[assetName] = value2 + 1; } else { instance.itemsPurchasedTotal[assetName] = 1; } ModLog.Debug("Registered spawned item: " + assetName); } } catch (Exception ex) { ModLog.Debug("RegisterItemInGame failed: " + ex.Message); } } private static void ChargeItem(GameObject instance, float delaySeconds, int bars = 10) { ItemBattery componentInParent = instance.GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { ((MonoBehaviour)EffectTimerHost.Instance).StartCoroutine(ChargeRoutine(componentInParent, delaySeconds, bars)); } } private static IEnumerator ChargeRoutine(ItemBattery battery, float delaySeconds, int bars) { if (delaySeconds > 0f) { yield return (object)new WaitForSeconds(delaySeconds); } if ((Object)(object)battery == (Object)null) { yield break; } try { MethodInfo method = ((object)battery).GetType().GetMethod("BatteryFullPercentChange", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null) { method.Invoke(battery, new object[2] { bars, true }); } } catch (Exception ex) { ModLog.Debug("ChargeItem failed: " + ex.Message); } } } internal static class ItemRegistry { private static readonly Dictionary ByKey = new Dictionary(StringComparer.OrdinalIgnoreCase); private static bool _loaded; public static void EnsureLoaded() { if (_loaded) { return; } _loaded = true; try { foreach (Item allItem in Items.AllItems) { if (!((Object)(object)allItem == (Object)null) && !string.IsNullOrWhiteSpace(allItem.itemName)) { Register(allItem.itemName, allItem); } } ModLog.Info($"ItemRegistry loaded {ByKey.Count} keys from {Items.AllItems?.Count() ?? 0} items"); } catch (Exception ex) { ModLog.Error("ItemRegistry load failed: " + ex.Message); } } private static void Register(string name, Item item) { if (string.IsNullOrWhiteSpace(name)) { return; } foreach (string item2 in ExpandTerms(name)) { if (!ByKey.ContainsKey(item2)) { ByKey[item2] = item; } } } public static IEnumerable GetSearchTerms(string query) { if (RepoEventMap.TryGetItemInternalName(query, out string itemId)) { foreach (string item in ExpandTerms(itemId)) { yield return item; } } foreach (string item2 in ExpandTerms(query)) { yield return item2; } } public static Item? Resolve(string query) { EnsureLoaded(); if (string.IsNullOrWhiteSpace(query)) { return null; } if (RepoEventMap.TryGetItemInternalName(query, out string itemId)) { query = itemId; } else if (!query.StartsWith("item_", StringComparison.OrdinalIgnoreCase) && RepoEventMap.TryGetItemInternalName("item_" + query.Replace(' ', '_'), out itemId)) { query = itemId; } foreach (string item in ExpandTerms(query)) { if (ByKey.TryGetValue(item, out Item value) && ItemMatchesTerm(value, item)) { return value; } } Item result = null; int num = int.MaxValue; foreach (string item2 in ExpandTerms(query)) { if (item2.Length < 4) { continue; } foreach (Item allItem in Items.AllItems) { if (!((Object)(object)allItem == (Object)null)) { int num2 = ScoreMatch(allItem.itemName ?? "", item2); if (num2 >= 0 && num2 < num) { num = num2; result = allItem; } } } } if (num > 20) { return null; } return result; } public static IEnumerable GetAllItemNames() { EnsureLoaded(); HashSet hashSet = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (Item allItem in Items.AllItems) { if (allItem != null && allItem.itemName != null) { hashSet.Add(allItem.itemName); } } GameObject[] array = Resources.LoadAll("Items"); foreach (GameObject val in array) { if ((Object)(object)val != (Object)null) { hashSet.Add(((Object)val).name); } } return hashSet.OrderBy((string n) => n, StringComparer.OrdinalIgnoreCase); } public static string FormatList() { return string.Join(Environment.NewLine, GetAllItemNames()); } private static bool ItemMatchesTerm(Item item, string term) { string a = Normalize(item.itemName ?? ""); string b = Normalize(term); return string.Equals(a, b, StringComparison.OrdinalIgnoreCase); } private static IEnumerable ExpandTerms(string query) { yield return query; yield return query.Replace("_", " "); if (query.StartsWith("Item_", StringComparison.OrdinalIgnoreCase)) { yield return "Item " + query.Substring(5).Replace("_", " "); yield return query.Substring(5).Replace("_", " "); } else if (query.StartsWith("Item ", StringComparison.OrdinalIgnoreCase)) { yield return query.Substring(5); yield return "Item_" + query.Substring(5).Replace(" ", "_"); } else if (query.StartsWith("Valuable_", StringComparison.OrdinalIgnoreCase)) { yield return query.Substring(9).Replace("_", " "); } else { yield return "Item " + query; yield return "Item_" + query.Replace(" ", "_"); } } private static int ScoreMatch(string itemName, string term) { string text = Normalize(itemName); string text2 = Normalize(term); if (string.Equals(text, text2, StringComparison.OrdinalIgnoreCase)) { return 0; } if (IsThrowableFamily(text) || IsThrowableFamily(text2)) { return -1; } if (text.Contains("gun", StringComparison.OrdinalIgnoreCase) && text2.Contains("gun", StringComparison.OrdinalIgnoreCase) && !string.Equals(text, text2, StringComparison.OrdinalIgnoreCase)) { return -1; } if (text.EndsWith(text2, StringComparison.OrdinalIgnoreCase)) { return 5 + text.Length; } return -1; } private static bool IsThrowableFamily(string name) { string text = name.ToLowerInvariant(); if (!text.Contains("grenade") && !text.Contains("mine") && !text.Contains("duck") && !text.Contains("nade")) { return text.Contains("duct"); } return true; } private static string Normalize(string value) { value = value.Trim().Replace('_', ' '); if (value.StartsWith("Item ", StringComparison.OrdinalIgnoreCase)) { value = value.Substring(5); } return value; } } internal static class ItemSpawnHelper { private const string ItemsPathPrefix = "Items/"; public static GameObject? TrySpawn(string query, Vector3 pos, Quaternion rot, out string? spawnedLabel, int scatterIndex = 0, bool holdInPlace = false, bool skipGrenadeDormant = false) { //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) spawnedLabel = null; if (string.IsNullOrWhiteSpace(query)) { return null; } if (RepoEventMap.TryGetItemInternalName(query, out string itemId) || RepoEventMap.TryGetItemInternalName("item_" + query.Replace(' ', '_'), out itemId) || RepoEventMap.TryGetActiveItem(query, out itemId)) { query = itemId; } if (IsGunQuery(query)) { GameObject val = TrySpawnFromGame(query, pos, rot, out spawnedLabel, scatterIndex, holdInPlace, skipGrenadeDormant); if ((Object)(object)val != (Object)null) { return val; } } Item val2 = ItemRegistry.Resolve(query); if ((Object)(object)val2 != (Object)null && ItemMatchesQuery(val2, query)) { try { GameObject val3 = Items.SpawnItem(val2, pos, rot); if ((Object)(object)val3 != (Object)null) { spawnedLabel = val2.itemName ?? query; val3.transform.position = pos; ItemPostSpawnHelper.Initialize(val3, spawnedLabel, scatterIndex, holdInPlace, skipGrenadeDormant); ModLog.Info("Spawned item via REPOLib: " + spawnedLabel); return val3; } } catch (Exception ex) { ModLog.Warn("REPOLib SpawnItem failed for '" + query + "': " + ex.Message); } } return TrySpawnFromGame(query, pos, rot, out spawnedLabel, scatterIndex, holdInPlace, skipGrenadeDormant); } private static GameObject? TrySpawnFromGame(string query, Vector3 pos, Quaternion rot, out string? spawnedLabel, int scatterIndex = 0, bool holdInPlace = false, bool skipGrenadeDormant = false) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) spawnedLabel = null; foreach (string resourcePath in GetResourcePaths(query)) { GameObject val = Resources.Load(resourcePath); if ((Object)(object)val == (Object)null) { continue; } try { GameObject val2 = InstantiateItem(resourcePath, val, pos, rot); if ((Object)(object)val2 == (Object)null) { continue; } val2.transform.position = pos; spawnedLabel = ((Object)val).name; ItemPostSpawnHelper.Initialize(val2, ((Object)val).name, scatterIndex, holdInPlace, skipGrenadeDormant); ModLog.Info("Spawned item via game resources: " + resourcePath); return val2; } catch (Exception ex) { ModLog.Warn("Item instantiate failed for " + resourcePath + ": " + ex.Message); } } return null; } private static GameObject? InstantiateItem(string resourcePath, GameObject prefab, Vector3 pos, Quaternion rot) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) if (SemiFunc.IsMultiplayer() && PhotonNetwork.IsConnected && SemiFunc.IsMasterClientOrSingleplayer() && !SemiFunc.MenuLevel()) { return PhotonNetwork.InstantiateRoomObject(resourcePath, pos, rot, (byte)0, (object[])null); } return Object.Instantiate(prefab, pos, rot); } private static bool IsGunQuery(string query) { string text = query.Replace('_', ' '); return text.IndexOf("Gun", StringComparison.OrdinalIgnoreCase) >= 0; } private static bool ItemMatchesQuery(Item item, string query) { string a = (item.itemName ?? "").Replace('_', ' '); foreach (string searchTerm in ItemRegistry.GetSearchTerms(query)) { string text = searchTerm.Replace('_', ' '); if (string.Equals(a, text, StringComparison.OrdinalIgnoreCase)) { return true; } if (string.Equals(a, "Item " + text, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private static IEnumerable GetResourcePaths(string query) { HashSet seen = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (string searchTerm in ItemRegistry.GetSearchTerms(query)) { foreach (string item in BuildPaths(searchTerm)) { if (seen.Add(item)) { yield return item; } } } } private static IEnumerable BuildPaths(string term) { yield return "Items/" + term; if (!term.StartsWith("Item ", StringComparison.OrdinalIgnoreCase)) { yield return "Items/Item " + term; } if (term.StartsWith("Item ", StringComparison.OrdinalIgnoreCase)) { yield return "Items/" + term.Substring(5); } } } internal static class PlayerEffectHelper { private static bool _movementShuffleActive; private static readonly string[] MovementBindNames = new string[4] { "Up", "Down", "Left", "Right" }; public static bool ForceCrouchHeld { get; private set; } public static bool IsMovementShuffleActive => _movementShuffleActive; public static PlayerAvatar? GetLocalPlayer() { return EventContext.SoloTarget() ?? SemiFunc.PlayerAvatarLocal(); } public static bool DisableAiming(float seconds) { InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { return false; } instance.DisableAiming(seconds); return true; } public static bool DisableMovement(float seconds) { InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { return false; } instance.DisableMovement(seconds); return true; } public static bool DisableInputKey(string keyName, float seconds) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) if (!Enum.TryParse(keyName, ignoreCase: true, out InputKey key)) { ModLog.Warn("Unknown input key: " + keyName); return false; } if ((int)key == 0) { return DisableMovement(seconds); } InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { return false; } List list = (from InputKey k in Enum.GetValues(typeof(InputKey)) where k != key select k).ToList(); instance.DisableControlsExcept(seconds, list); return true; } public static bool HoldInputKey(string keyName, float seconds) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Invalid comparison between Unknown and I4 if (!Enum.TryParse(keyName, ignoreCase: true, out InputKey result)) { return false; } if ((int)result == 12) { seconds = Mathf.Max(1f, seconds); ForceCrouchHeld = true; ForceCrouchOnce(GetLocalPlayer()); EffectTimerHost.Instance.RunForSeconds("hold_crouch", seconds, delegate { KeepForcedCrouchHeld(GetLocalPlayer()); }, delegate { ForceCrouchHeld = false; ModLog.Info("hold_input Crouch ended — Ctrl hold released"); }); return true; } return DisableInputKey(keyName, seconds); } private static void ForceCrouchOnce(PlayerAvatar? player) { if ((Object)(object)player == (Object)null) { return; } try { if (!player.isCrouching && !player.isCrawling) { player.StandToCrouch(); } } catch { KeepForcedCrouchHeld(player); } } private static void KeepForcedCrouchHeld(PlayerAvatar? player) { if ((Object)(object)player == (Object)null) { return; } try { if (!player.isCrouching && !player.isCrawling) { player.StandToCrouch(); } return; } catch { } WriteBoolField(player, "isCrouching", value: true); WriteBoolField(player, "isCrawling", value: false); try { MethodInfo method = ((object)player).GetType().GetMethod("Crouch", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method != null && method.GetParameters().Length == 0) { method.Invoke(player, null); } } catch { } } private static void WriteBoolField(object target, string fieldName, bool value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(target, value); } } catch { } } public static bool ShuffleMovement(float seconds) { seconds = Mathf.Max(1f, seconds); if (_movementShuffleActive && EffectTimerHost.Instance.GetRemaining("shuffle_movement") > 0.05f) { EffectTimerHost.Instance.RunForSeconds("shuffle_movement", seconds, delegate { }, delegate { RestoreMovementBinds(); ModLog.Info("shuffle_player_movement ends — WASD restored"); }); return true; } ForceEndMovementShuffle(); if (!ShuffleMovementBinds()) { return false; } _movementShuffleActive = true; ModLog.Info($"shuffle_player_movement active for {seconds:0}s"); EffectTimerHost.Instance.RunForSeconds("shuffle_movement", seconds, delegate { }, delegate { RestoreMovementBinds(); ModLog.Info("shuffle_player_movement ends — WASD restored"); }); return true; } public static void ForceEndMovementShuffle() { try { EffectTimerHost.Instance.Stop("shuffle_movement"); } catch { } RestoreMovementBinds(); } private static InputAction? GetMovementAction() { InputManager instance = InputManager.instance; if ((Object)(object)instance == (Object)null) { return null; } try { if (instance.inputActions != null && instance.inputActions.TryGetValue((InputKey)0, out var value)) { return value; } } catch { } try { return instance.GetMovementAction(); } catch { return null; } } private static bool ShuffleMovementBinds() { //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0119: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) InputAction movementAction = GetMovementAction(); if (movementAction == null) { ModLog.Warn("shuffle_player_movement: Movement InputAction missing"); return false; } InputBinding? val = null; InputBinding? val2 = null; InputBinding? val3 = null; InputBinding? val4 = null; Enumerator enumerator = movementAction.bindings.GetEnumerator(); try { while (enumerator.MoveNext()) { InputBinding current = enumerator.Current; switch (((InputBinding)(ref current)).name) { case "Up": val = current; break; case "Down": val2 = current; break; case "Left": val3 = current; break; case "Right": val4 = current; break; } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } if (!val.HasValue || !val2.HasValue || !val3.HasValue || !val4.HasValue) { ModLog.Warn("shuffle_player_movement: missing Up/Down/Left/Right bindings"); return false; } SwapMovementBind(movementAction, val.Value, val2.Value); SwapMovementBind(movementAction, val3.Value, val4.Value); return true; } private static void SwapMovementBind(InputAction action, InputBinding a, InputBinding b) { //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) string path = ((InputBinding)(ref a)).path; string text = (((InputBinding)(ref a)).overridePath = ((InputBinding)(ref b)).path); ((InputBinding)(ref b)).overridePath = path; InputActionRebindingExtensions.ApplyBindingOverride(action, a); InputActionRebindingExtensions.ApplyBindingOverride(action, b); ModLog.Debug("WASD swap " + ((InputBinding)(ref a)).name + ":" + path + "->" + text + ", " + ((InputBinding)(ref b)).name + ":" + text + "->" + path); } private static void RestoreMovementBinds() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) _movementShuffleActive = false; InputAction movementAction = GetMovementAction(); if (movementAction == null) { return; } try { Enumerator enumerator = movementAction.bindings.GetEnumerator(); try { while (enumerator.MoveNext()) { InputBinding current = enumerator.Current; if (MovementBindNames.Contains(((InputBinding)(ref current)).name)) { InputBinding val = current; ((InputBinding)(ref val)).overridePath = null; InputActionRebindingExtensions.ApplyBindingOverride(movementAction, val); } } } finally { ((IDisposable)enumerator/*cast due to .constrained prefix*/).Dispose(); } } catch (Exception ex) { ModLog.Warn("RestoreMovementBinds failed: " + ex.Message); } } public static bool Knockdown(float force, float rotatePower) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) PlayerAvatar localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer?.tumble == (Object)null) { return false; } Vector3 force2 = (((Object)(object)localPlayer.localCamera != (Object)null) ? (((Component)localPlayer.localCamera).transform.forward * force) : (((Component)localPlayer).transform.forward * force)); ActivateTumble(localPlayer.tumble, localPlayer, force2, rotatePower); return true; } public static bool HurtPlayerAmount(bool allPlayers, int amount, bool savingGrace) { //IL_0059: Unknown result type (might be due to invalid IL or missing references) bool result = false; foreach (PlayerAvatar target in GetTargets(allPlayers)) { if ((Object)(object)target?.playerHealth == (Object)null) { continue; } int health = target.playerHealth.health; int num = amount; if (savingGrace && health <= num) { num = Mathf.Max(0, health - 1); if (num == 0) { continue; } } target.playerHealth.HurtOther(num, Vector3.zero, savingGrace, -1, false); result = true; } return result; } public static bool SlapAllRoom(int amount) { //IL_0050: Unknown result type (might be due to invalid IL or missing references) int num = Mathf.Max(1, amount); if (num >= 100) { num = 10; } int num2 = 0; foreach (PlayerAvatar item in PlayerTargeting.AlivePlayers()) { if (!((Object)(object)item?.playerHealth == (Object)null) && item.playerHealth.health > 0) { item.playerHealth.HurtOther(num, Vector3.zero, false, -1, false); num2++; } } if (num2 > 0) { ModLog.Info($"SlapAllRoom: -{num} HP x{num2} alive players"); } return num2 > 0; } public static bool HealPlayerAmount(bool allPlayers, int amount) { bool result = false; foreach (PlayerAvatar target in GetTargets(allPlayers)) { if (!((Object)(object)target?.playerHealth == (Object)null)) { target.playerHealth.HealOther(amount, true); result = true; } } return result; } public static bool ExplodeLocalPlayer() { return ExplodeTargetPlayer(GetLocalPlayer()); } public static bool ExplodeTargetPlayer(PlayerAvatar? player) { //IL_0033: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null || PlayerTargeting.IsPlayerDead(player)) { return false; } string playerName = PlayerTargeting.GetPlayerName(player); try { if ((Object)(object)player.playerHealth != (Object)null) { player.playerHealth.HurtOther(999, Vector3.zero, false, -1, false); } } catch { } try { player.PlayerDeath(-1); } catch { return false; } ModLog.Info("Destruct hit '" + playerName + "'"); return true; } public static bool RestoreStamina() { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null) { return false; } instance.EnergyCurrent = instance.EnergyStart; return true; } public static bool InfiniteStamina(float seconds) { string id = "infinite_stamina"; EffectTimerHost.Instance.RunForSeconds(id, seconds, delegate { PlayerController instance = PlayerController.instance; if (!((Object)(object)instance == (Object)null)) { instance.EnergyCurrent = instance.EnergyStart; } }); return true; } public static bool DrainStamina(float seconds, float powerPerSecond) { EffectTimerHost.Instance.RunForSeconds("drain_stamina", seconds, delegate(float dt) { PlayerController instance = PlayerController.instance; if (!((Object)(object)instance == (Object)null)) { instance.EnergyCurrent = Mathf.Max(0f, instance.EnergyCurrent - powerPerSecond * dt); } }); return true; } public static bool Invincible(float seconds) { EffectTimerHost.Instance.RunForSeconds("invincible", seconds, delegate { PlayerAvatar localPlayer = GetLocalPlayer(); if (localPlayer != null) { PlayerHealth playerHealth = localPlayer.playerHealth; if (playerHealth != null) { playerHealth.InvincibleSet(0.25f); } } }); return true; } public static bool SetSpeedMultiplier(float seconds, float multiplier) { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null) { return false; } instance.OverrideSpeed(multiplier, seconds); return true; } public static bool SetJumpPower(float seconds, float jumpForce) { PlayerController pc = PlayerController.instance; if ((Object)(object)pc == (Object)null) { return false; } float original = pc.JumpForce; pc.JumpForce = jumpForce; EffectTimerHost.Instance.RunForSeconds("jump_power", seconds, delegate { pc.JumpForce = jumpForce; }, delegate { if ((Object)(object)PlayerController.instance != (Object)null) { PlayerController.instance.JumpForce = original; } }); return true; } public static bool EnableAntiGravity(float seconds) { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null) { return false; } instance.AntiGravity(seconds); return true; } public static bool SetHeavyGravity(float seconds, float gravity) { PlayerController instance = PlayerController.instance; if ((Object)(object)instance == (Object)null) { return false; } float original = instance.CustomGravity; float originalPlayer = ReadFloatField(instance, "playerOriginalCustomGravity", original); instance.CustomGravity = gravity; WriteFloatField(instance, "playerOriginalCustomGravity", gravity); EffectTimerHost.Instance.RunForSeconds("heavy_gravity", seconds, delegate { if (!((Object)(object)PlayerController.instance == (Object)null)) { PlayerController.instance.CustomGravity = gravity; WriteFloatField(PlayerController.instance, "playerOriginalCustomGravity", gravity); } }, delegate { if (!((Object)(object)PlayerController.instance == (Object)null)) { PlayerController.instance.CustomGravity = original; WriteFloatField(PlayerController.instance, "playerOriginalCustomGravity", originalPlayer); } }); return true; } public static bool RelativeForceMove(float forward, float right, float rotatePower) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return false; } Vector3 val = ((Component)localPlayer).transform.forward; Vector3 val2 = ((Vector3)(ref val)).normalized * forward; val = ((Component)localPlayer).transform.right; Vector3 val3 = val2 + ((Vector3)(ref val)).normalized * (0f - right); localPlayer.ForceImpulse(val3); if (localPlayer.isCrouching || localPlayer.isCrawling) { ActivateTumble(localPlayer.tumble, localPlayer, val3, rotatePower); } return true; } public static bool ForceRigidBody(float x, float y, float z, float rotatePower) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer?.tumble == (Object)null) { return false; } ActivateTumble(localPlayer.tumble, localPlayer, new Vector3(x, y, z), rotatePower); return true; } public static bool SetHealthPercent(bool allPlayers, float percent) { //IL_0085: Unknown result type (might be due to invalid IL or missing references) bool result = false; foreach (PlayerAvatar target in GetTargets(allPlayers)) { if (!((Object)(object)target?.playerHealth == (Object)null)) { int maxHealth = target.playerHealth.maxHealth; int num = Mathf.Clamp(Mathf.CeilToInt((float)maxHealth * (percent / 100f)), 1, maxHealth); int num2 = num - target.playerHealth.health; if (num2 > 0) { target.playerHealth.HealOther(num2, true); } else if (num2 < 0) { target.playerHealth.HurtOther(-num2, Vector3.zero, false, -1, false); } result = true; } } return result; } private static IEnumerable GetTargets(bool allPlayers) { return PlayerTargeting.GetAliveEventTargets(allPlayers); } public static bool DropInventory() { PlayerAvatar localPlayer = GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null || PlayerTargeting.IsPlayerDead(localPlayer)) { return false; } try { PhysGrabber componentInChildren = ((Component)localPlayer).GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { TryInvoke((Component)(object)componentInChildren, "ReleaseObject"); TryInvoke((Component)(object)componentInChildren, "DropObject"); } } catch (Exception ex) { ModLog.Debug("DropInventory: " + ex.Message); } return true; } private static void TryInvoke(Component comp, string methodName) { try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 0) { method.Invoke(comp, null); } } catch { } } private static void ActivateTumble(PlayerTumble tumble, PlayerAvatar player, Vector3 force, float rotatePower) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) tumble.TumbleForce(force); tumble.TumbleTorque(((Component)tumble).transform.right * rotatePower); try { MethodInfo method = typeof(PlayerTumble).GetMethod("BreakFree", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); Vector3 val = (((Object)(object)player.localCamera != (Object)null) ? ((Component)player.localCamera).transform.forward : ((Component)player).transform.forward); method?.Invoke(tumble, new object[1] { val }); } catch (Exception ex) { ModLog.Debug("BreakFree failed: " + ex.Message); } tumble.TumbleSet(true, false); } private static float ReadFloatField(object target, string fieldName, float fallback) { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field != null)) { return fallback; } return (float)field.GetValue(target); } private static void WriteFloatField(object target, string fieldName, float value) { target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(target, value); } } internal static class PlayerTargeting { private static readonly Regex NameTagRegex = new Regex("<[^>]+>|\\[[^\\]]*\\]", RegexOptions.Compiled); public static IEnumerable AllPlayers() { try { List list = SemiFunc.PlayerGetList(); if (list != null && list.Count > 0) { return list.Where((PlayerAvatar p) => (Object)(object)p != (Object)null); } } catch { } return from p in Object.FindObjectsOfType() where (Object)(object)p != (Object)null select p; } public static bool IsPlayerDead(PlayerAvatar? player) { if ((Object)(object)player == (Object)null) { return false; } try { return player.isDisabled; } catch { return ReadBool(player, "isDisabled"); } } public static bool IsPlayerAlive(PlayerAvatar? player) { if ((Object)(object)player != (Object)null) { return !IsPlayerDead(player); } return false; } public static bool AnyPlayerAlive() { return AllPlayers().Any(IsPlayerAlive); } public static List AlivePlayers() { return AllPlayers().Where(IsPlayerAlive).ToList(); } public static List DeadPlayers() { return AllPlayers().Where(IsPlayerDead).ToList(); } public static PlayerAvatar? FindAliveByName(string? query) { string text = NormalizeName(query); if (string.IsNullOrEmpty(text)) { return null; } List list = AlivePlayers(); if (list.Count == 0) { return null; } foreach (PlayerAvatar item in list) { foreach (string playerNameAlias in GetPlayerNameAliases(item)) { if (NormalizeName(playerNameAlias) == text) { return item; } } } PlayerAvatar val = null; int num = 0; foreach (PlayerAvatar item2 in list) { foreach (string playerNameAlias2 in GetPlayerNameAliases(item2)) { string text2 = NormalizeName(playerNameAlias2); if (!string.IsNullOrEmpty(text2) && text2.StartsWith(text, StringComparison.Ordinal)) { if ((Object)(object)val != (Object)(object)item2) { val = item2; num++; } break; } } } if (num == 1) { return val; } PlayerAvatar val2 = null; int num2 = 0; foreach (PlayerAvatar item3 in list) { foreach (string playerNameAlias3 in GetPlayerNameAliases(item3)) { string text3 = NormalizeName(playerNameAlias3); if (!string.IsNullOrEmpty(text3) && text3.Contains(text)) { if ((Object)(object)val2 != (Object)(object)item3) { val2 = item3; num2++; } break; } } } if (num2 != 1) { return null; } return val2; } public static List AliveRosterNames() { return (from n in AlivePlayers().Select(GetPlayerName) where !string.IsNullOrWhiteSpace(n) select n).Distinct(StringComparer.OrdinalIgnoreCase).ToList(); } public static string FormatAliveRoster() { List list = AliveRosterNames(); if (list.Count != 0) { return string.Join(", ", list); } return "(none)"; } public static IEnumerable GetPlayerNameAliases(PlayerAvatar? player) { List list = new List(); if ((Object)(object)player == (Object)null) { return list; } try { string text = SemiFunc.PlayerGetName(player); if (!string.IsNullOrWhiteSpace(text)) { list.Add(text); } } catch { } try { if (!string.IsNullOrWhiteSpace(player.playerName)) { list.Add(player.playerName); } } catch { } try { PhotonView photonView = player.photonView; object obj3; if (photonView == null) { obj3 = null; } else { Player owner = photonView.Owner; obj3 = ((owner != null) ? owner.NickName : null); } string text2 = (string)obj3; if (!string.IsNullOrWhiteSpace(text2)) { list.Add(text2); } } catch { } try { string text3 = (((Object)(object)((Component)player).gameObject != (Object)null) ? ((Object)((Component)player).gameObject).name : ""); if (!string.IsNullOrWhiteSpace(text3)) { list.Add(text3.Replace("(Clone)", "").Trim()); } } catch { } return list; } public static string GetPlayerName(PlayerAvatar? player) { foreach (string playerNameAlias in GetPlayerNameAliases(player)) { if (!string.IsNullOrWhiteSpace(playerNameAlias)) { return playerNameAlias; } } return ""; } private static string NormalizeName(string? value) { if (string.IsNullOrWhiteSpace(value)) { return ""; } string text = NameTagRegex.Replace(value.Trim(), ""); text = text.Replace("(Clone)", "", StringComparison.OrdinalIgnoreCase); char[] array = text.ToLowerInvariant().ToCharArray(); return new string(Array.FindAll(array, (char c) => !char.IsWhiteSpace(c) && !char.IsControl(c))); } public static List GetAliveEventTargets(bool massEffect) { if (massEffect) { return AlivePlayers(); } PlayerAvatar val = EventContext.SoloTarget(); if ((Object)(object)val != (Object)null && IsPlayerAlive(val)) { return new List { val }; } return new List(); } public static List GetDeadEventTargets(bool massEffect) { if (massEffect) { return DeadPlayers(); } PlayerAvatar val = EventContext.SoloTarget(); if ((Object)(object)val != (Object)null && IsPlayerDead(val)) { return new List { val }; } return new List(); } private static bool ReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { return (bool)field.GetValue(target); } } catch { } return false; } } internal static class RepoEventMap { private static readonly Dictionary EnemyByEventId = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["spawn_duck"] = "Duck", ["spawn_spewer"] = "Slow_Mouth", ["spawn_upscream"] = "Upscream", ["spawn_alien"] = "Floater", ["spawn_animal"] = "Animal", ["spawn_baby"] = "Valuable_Thrower", ["spawn_thinman"] = "Thin_Man", ["spawn_hidden"] = "Hidden", ["spawn_frog"] = "Tumbler", ["spawn_bowtie"] = "Bowtie", ["spawn_huntsman"] = "Hunter", ["spawn_head"] = "Head", ["spawn_trudge"] = "Slow_Walker", ["spawn_clown"] = "Beamer", ["spawn_robe"] = "Robe", ["spawn_reaper"] = "Runner", ["spawn_dogo"] = "Elsa", ["spawn_tick"] = "Tick", ["spawn_birthday_boy"] = "Birthday_boy", ["spawn_gambit"] = "Spinny", ["spawn_headgrab"] = "Head_Grabber", ["spawn_heart_hugger"] = "Heart_Hugger", ["spawn_cleanup_crew"] = "Bomb_Thrower", ["spawn_bella"] = "Tricycle", ["spawn_oogly"] = "Oogly", ["spawn_loom"] = "Shadow", ["spawn_ceiling_eye"] = "Ceiling Eye", ["spawn_gnome"] = "Gnome", ["spawn_bang"] = "Bang" }; private static readonly Dictionary ActiveItemByEventId = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["active_nade_stun"] = "Item_Grenade_Stun", ["active_nade_shock"] = "Item_Grenade_Shockwave", ["active_nade_expl"] = "Item_Grenade_Explosive", ["active_nade_duck"] = "Item_Rubber_Duck" }; private static readonly Dictionary ItemByEventId = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["item_health_small"] = "Item_Health_Pack_Small", ["item_health_med"] = "Item_Health_Pack_Medium", ["item_health_big"] = "Item_Health_Pack_Large", ["item_crystal"] = "Item_Power_Crystal", ["item_nade_stun"] = "Item_Grenade_Stun", ["item_nade_shock"] = "Item_Grenade_Shockwave", ["item_nade_expl"] = "Item_Grenade_Explosive", ["item_nade_f1"] = "Item_Grenade_Human", ["item_nade_duck_f1"] = "Item_Grenade_Duct_Taped", ["item_mine_stun"] = "Item_Mine_Stun", ["item_mine_shock"] = "Item_Mine_Shockwave", ["item_mine_expl"] = "Item_Mine_Explosive", ["item_rubber_duck"] = "Item_Rubber_Duck", ["item_handgun"] = "Item_Gun_Handgun", ["item_shotgun"] = "Item_Gun_Shotgun", ["item_tranq"] = "Item_Gun_Tranq", ["item_frying_pan"] = "Item_Melee_Frying_Pan", ["item_baseball_bat"] = "Item_Melee_Baseball_Bat", ["item_sledge_hammer"] = "Item_Melee_Sledge_Hammer", ["item_sword"] = "Item_Melee_Sword", ["item_duck_bucket"] = "Item_Duck_Bucket", ["item_photon_blaster"] = "Item_Gun_Laser", ["item_revive"] = "Item_ReviveItem", ["item_book_roll"] = "Item_Upgrade_Player_Tumble_Launch", ["item_book_speed"] = "Item_Upgrade_Player_Sprint_Speed", ["item_book_energy"] = "Item_Upgrade_Player_Energy", ["item_book_health"] = "Item_Upgrade_Player_Health", ["item_book_range"] = "Item_Upgrade_Player_Grab_Range", ["item_book_strength"] = "Item_Upgrade_Player_Grab_Strength", ["item_book_jump"] = "Item_Upgrade_Player_Extra_Jump", ["item_book_wings"] = "Item_Upgrade_Player_Tumble_Wings", ["item_book_rest"] = "Item_Upgrade_Player_Crouch_Rest", ["item_book_battery"] = "Item_Upgrade_Death_Head_Battery", ["item_book_climb"] = "Item_Upgrade_Player_Tumble_Climb", ["item_drone_roll"] = "Item_Drone_Torque", ["item_drone_gravity"] = "Item_Drone_Zero_Gravity", ["item_drone_feather"] = "Item_Drone_Feather", ["item_drone_energy"] = "Item_Drone_Battery", ["item_drone_shield"] = "Item_Drone_Indestructible", ["item_sphere_gravity"] = "Item_Orb_Zero_Gravity", ["item_inflatable_hammer"] = "Item_Melee_Inflatable_Hammer", ["item_valuable_tracker"] = "Item_Valuable_Tracker", ["item_extraction_tracker"] = "Item_Extraction_Tracker", ["item_cart_small"] = "Item_Cart_Small", ["item_cart_medium"] = "Item_Cart_Medium", ["item_cart_cannon"] = "Item_Cart_Cannon", ["item_cart_laser"] = "Item_Cart_Laser", ["item_cart_scooter"] = "Item_Vehicle_Semiscooter", ["item_cart_scooter_small"] = "Item_Vehicle_Semiscooter_Small", ["item_bridge"] = "Item_Phase_Bridge", ["item_melee_prodzap"] = "Item_Melee_Stun_Baton", ["item_gun_boltzap"] = "Item_Gun_Stun", ["item_gun_pulse"] = "Item_Gun_Shockwave", ["item_staff_gravity"] = "Item_Staff_Zero_Gravity", ["item_staff_torque"] = "Item_Staff_Torque", ["item_staff_void"] = "Item_Staff_Void", ["item_walkie_talkie"] = "Item_WalkieTalkieBox" }; private static readonly Dictionary EffectByEventId = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["solo_debuff_camera"] = "disable_player_aiming 30", ["solo_debuff_freez"] = "disable_player_aiming 10; disable_player_movement 10; disable_input 10 Movement; disable_input 10 Jump; disable_input 10 Crouch; disable_input 10 Grab", ["solo_debuff_grab"] = "disable_input 45 Grab", ["solo_debuff_crouch"] = "hold_input 60 Crouch", ["solo_debuff_wasd"] = "shuffle_player_movement 30", ["solo_debuff_hurt"] = "hurt_player_amount false 10 true; rel_force_move -15 0", ["solo_debuff_energy"] = "drain_player_stamina 30 20", ["solo_debuff_knockdown"] = "knockdown_player 10 10", ["solo_debuff_slow"] = "set_player_speed_mult 45 0.33", ["solo_debuff_gravity"] = "set_player_gravity 45 120", ["solo_debuff_push_up"] = "force_rb 0 100 0 10", ["solo_debuff_push_front"] = "rel_force_move 100 0 20", ["solo_debuff_push_back"] = "rel_force_move -100 0 20", ["solo_debuff_kill"] = "explode_player", ["solo_debuff_kill_named"] = "explode_player", ["all_debuff_kill_named"] = "explode_player", ["solo_buff_heal"] = "heal_player_amount false 25", ["solo_buff_energy"] = "restore_stamina", ["solo_buff_full_restore"] = "player_set_health_pc false 100; restore_stamina", ["solo_buff_speed"] = "set_player_speed_mult 60 3", ["solo_buff_jump"] = "set_player_jump_power 60 40", ["solo_buff_energymode"] = "infinite_player_stamina 60", ["solo_buff_godmode"] = "invincible_player 60", ["solo_buff_gravity"] = "enable_anti_gravity 60", ["all_buff_heal"] = "heal_player_amount true 25", ["all_buff_full_restore"] = "player_set_health_pc true 100", ["all_debuff_hurt"] = "slap_all_room 10; rel_force_move -15 0", ["all_debuff_kill_rand"] = "explode_random_player", ["solo_teleport_start"] = "teleport_player_rnd_point_start_room false", ["solo_teleport_rand"] = "teleport_player_rnd_point_rnd_room false", ["solo_buff_resurrect"] = "resurrect_player", ["solo_frogs_around"] = "spawn_items_around_player Valuable_Manor_Frog 1 1 6", ["solo_chomp_book"] = "spawn_chomp_book", ["solo_toycars_around"] = "spawn_toycars_around 5", ["solo_toyplanes_around"] = "spawn_toyplanes_around 5", ["solo_poop_diamonds"] = "spawn_items_from_player Valuable_Wizard_Diamond 15 0.5 0.3 0.5 90", ["solo_poop_mines"] = "spawn_items_from_player Item_Mine_Explosive 15 1 0.3 1 1", ["solo_poop_shock_mines"] = "spawn_items_from_player Item_Mine_Shockwave 15 1 0.3 1 1", ["solo_poop_nades"] = "spawn_items_from_player group_item_rand_nades 15 1 0.3 0.75 10", ["all_debuff_hp_shuffle"] = "shuffle_players_hp", ["all_goal_dec"] = "change_extract_goal_percents 0.75", ["all_goal_inc"] = "change_extract_goal_percents 1.25", ["all_teleport_shuffle"] = "teleport_shuffle_players", ["all_teleport_start"] = "teleport_player_rnd_point_start_room true", ["all_teleport_rand"] = "teleport_player_rnd_point_rnd_room true", ["all_cart_spread"] = "shake_cart_items_delayed 0 0.05 45 70 0 0 0.2 5", ["all_cart_teleport_start"] = "teleport_carts_to_start", ["all_cart_teleport_rand"] = "teleport_carts_to_random_room", ["all_buff_resurrect_rand"] = "resurrect_random_player", ["all_buff_resurrect_all"] = "resurrect_all_players", ["item_revive"] = "spawn_item Item_ReviveItem 0 1", ["all_stun_enemies"] = "stun_enemies 7", ["all_speak_random"] = "all_players_speak", ["all_nade_burst"] = "nade_from_all_players expl 1", ["all_nade_duck"] = "nade_from_all_players duck 2" }; private static readonly Dictionary LootByEventId = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["loot_frog"] = "Valuable_Manor_Frog", ["loot_bottle"] = "Valuable_Manor_Bottle", ["loot_love_potion"] = "Valuable_Wizard_Love_Potion", ["loot_gramophone"] = "Valuable_Manor_Gramophone", ["loot_power_crystal"] = "Valuable_Wizard_Power_Crystal", ["loot_fan"] = "Valuable_Arctic_Fan", ["loot_clown"] = "Valuable_Manor_Clown", ["loot_guitar"] = "Valuable_Arctic_Guitar", ["loot_propane_tank"] = "Valuable_Arctic_Propane_Tank", ["loot_music_box"] = "Valuable_Manor_Music_Box", ["loot_television"] = "Valuable_Manor_Television", ["loot_flamethrower"] = "Valuable_Arctic_Flamethrower", ["loot_saw"] = "Valuable_Arctic_Ice_Saw", ["loot_time_glass"] = "Valuable_Wizard_Time_Glass", ["loot_doll"] = "Valuable_Manor_Scream_Doll", ["loot_barrel"] = "Valuable_Arctic_Barrel", ["loot_sword"] = "Valuable_Wizard_Sword", ["loot_staff"] = "Valuable_Wizard_Dumgolfs_Staff", ["loot_animal_crate"] = "Valuable_Manor_Animal_Crate", ["loot_creature_leg"] = "Valuable_Arctic_Creature_Leg", ["loot_ice_block"] = "Valuable_Arctic_Ice_Block", ["loot_broom"] = "Valuable_Wizard_Broom", ["loot_painting"] = "Valuable_Manor_Painting", ["loot_harp"] = "Valuable_Manor_Harp", ["loot_grandfather_clock"] = "Valuable_Manor_Grandfather_Clock", ["loot_golden_statue"] = "Valuable_Manor_Golden_Statue", ["loot_science_station"] = "Valuable_Arctic_Science_Station", ["loot_server_rack"] = "Valuable_Arctic_Server_Rack", ["loot_dinosaur"] = "Valuable_Manor_Dinosaur", ["loot_griffin_statue"] = "Valuable_Wizard_Griffin_Statue", ["loot_piano"] = "Valuable_Manor_Piano", ["loot_mug_deluxe"] = "Valuable_Museum_Uranium_Mug_Deluxe", ["loot_baby_head"] = "Valuable_Museum_Baby_Head", ["loot_gem_burger"] = "Valuable_Museum_Gem_Burger", ["loot_ac_gumball"] = "Valuable_Museum_Gumball", ["loot_ac_boombox"] = "Valuable_Museum_Boombox", ["loot_milk"] = "Valuable_Museum_Milk", ["loot_golden_swirl"] = "Valuable_Museum_Golden_Swirl", ["loot_ac_blender"] = "Valuable_Museum_Blender", ["loot_horse"] = "Valuable_Museum_Horse", ["loot_ac_trafic_light"] = "Valuable_Museum_Traffic_Light", ["loot_star_wand"] = "Valuable_Wizard_Star_Wand", ["loot_lev_potion"] = "Valuable_Wizard_Levitation_Potion", ["loot_jackhammer"] = "Valuable_Arctic_Jackhammer", ["loot_coffin"] = "Valuable_Manor_Coffin", ["loot_tray"] = "Valuable_Museum_Tray", ["loot_dragon_skull"] = "Valuable_Wizard_Dragon_Skull" }; public static IEnumerable ExpandEnemyResourceNames(string internalName) { if (!string.IsNullOrWhiteSpace(internalName)) { yield return internalName; yield return internalName.Replace('_', ' '); string text = internalName.Replace(' ', '_'); if (!string.Equals(text, internalName, StringComparison.Ordinal)) { yield return text; } } } public static bool TryGetEffectCommand(string eventId, out string commandLine) { if (EventCommandCatalog.TryGetCommandLine(eventId, out commandLine)) { return true; } commandLine = ""; if (string.IsNullOrWhiteSpace(eventId)) { return false; } return EffectByEventId.TryGetValue(NormalizeEventId(eventId), out commandLine); } public static bool TryGetLootInternalName(string eventId, out string valuableId) { valuableId = ""; if (string.IsNullOrWhiteSpace(eventId)) { return false; } return LootByEventId.TryGetValue(NormalizeEventId(eventId), out valuableId); } public static bool TryGetEnemyInternalName(string eventOrSlug, out string internalName) { internalName = ""; if (string.IsNullOrWhiteSpace(eventOrSlug)) { return false; } string text = NormalizeEventId(eventOrSlug); if (EnemyByEventId.TryGetValue(text, out internalName)) { return true; } string text2 = (text.StartsWith("spawn_", StringComparison.Ordinal) ? text.Substring(6) : text); foreach (KeyValuePair item in EnemyByEventId) { if (item.Key.EndsWith("_" + text2, StringComparison.Ordinal) || string.Equals(item.Key, "spawn_" + text2, StringComparison.Ordinal)) { internalName = item.Value; return true; } } return false; } public static string ResolveEnemyInternalName(string eventOrSlug) { if (TryGetEnemyInternalName(eventOrSlug, out string internalName)) { return internalName; } return eventOrSlug.Trim().Replace(" ", "_"); } public static bool TryGetActiveItem(string eventId, out string itemId) { itemId = ""; if (string.IsNullOrWhiteSpace(eventId)) { return false; } return ActiveItemByEventId.TryGetValue(NormalizeEventId(eventId), out itemId); } public static bool TryGetItemInternalName(string eventOrSlug, out string itemId) { itemId = ""; if (string.IsNullOrWhiteSpace(eventOrSlug)) { return false; } string text = NormalizeEventId(eventOrSlug); if (ItemByEventId.TryGetValue(text, out itemId)) { return true; } if (text.StartsWith("item_", StringComparison.Ordinal)) { itemId = "Item_" + text.Substring(5); return true; } return false; } public static IEnumerable ExpandItemSearchIds(string itemId) { yield return itemId; yield return itemId.Replace("_", " "); if (itemId.StartsWith("Item_", StringComparison.Ordinal)) { string text = itemId.Substring(5).Replace("_", " "); yield return "Item " + text; } } private static string NormalizeEventId(string value) { value = value.Trim().ToLowerInvariant().Replace(' ', '_'); while (value.StartsWith("repo_", StringComparison.Ordinal)) { value = value.Substring(5); } while (value.Contains("__", StringComparison.Ordinal)) { value = value.Replace("__", "_", StringComparison.Ordinal); } return value; } } public static class RepoEventResolver { private static readonly TextInfo TextInfo = CultureInfo.InvariantCulture.TextInfo; private static readonly HashSet ItemSpawnSlugs = new HashSet(StringComparer.OrdinalIgnoreCase) { "gun", "handgun", "shotgun", "medkit", "flashlight", "grenade", "mine", "cart", "drone", "bat", "baseball_bat", "energy_drink", "health", "stun", "shock", "sword", "tranq", "revive", "crystal", "rubber_duck", "frying_pan", "sledge_hammer" }; public static bool TryResolve(string eventId, out string spawnCmd, out string targetName) { spawnCmd = ""; targetName = ""; if (string.IsNullOrWhiteSpace(eventId)) { return false; } eventId = eventId.Trim().ToLowerInvariant(); if (eventId.StartsWith("spawn_", StringComparison.Ordinal)) { string text = eventId.Substring(6); if (ItemSpawnSlugs.Contains(text)) { spawnCmd = "spawn_item"; targetName = ItemSearchFromSlug(text); } else { spawnCmd = "spawn_ghost"; targetName = RepoEventMap.ResolveEnemyInternalName(eventId); } return true; } if (eventId.StartsWith("item_", StringComparison.Ordinal)) { spawnCmd = "spawn_item"; targetName = ItemSearchFromSlug(eventId.Substring(5)); return true; } if (eventId.StartsWith("loot_", StringComparison.Ordinal)) { if (eventId.Contains("rand", StringComparison.OrdinalIgnoreCase)) { spawnCmd = "spawn_valuable"; targetName = DropGroupCatalog.GroupForLootEvent(eventId); return true; } spawnCmd = "spawn_valuable"; targetName = LootSearchFromId(eventId); return true; } return false; } private static string ItemSearchFromSlug(string slug) { string text = slug.Replace(' ', '_').Trim(); if (!text.StartsWith("item_", StringComparison.Ordinal)) { text = "item_" + text; } if (RepoEventMap.TryGetItemInternalName(text, out string itemId)) { return itemId; } return TitleizeSlug(slug.Replace('_', ' ')); } private static string LootSearchFromId(string eventId) { if (RepoEventMap.TryGetLootInternalName(eventId, out string valuableId)) { return valuableId; } string text = (eventId.StartsWith("loot_", StringComparison.Ordinal) ? eventId.Substring(5) : eventId); return "Valuable_" + text.Replace(' ', '_'); } private static string TitleizeSlug(string slug) { string[] array = slug.Split(new char[2] { '_', ' ' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { if (array[i].Length > 0) { array[i] = TextInfo.ToTitleCase(array[i]); } } return string.Join(" ", array); } } internal static class RunGate { private static bool _wasLevelGenerated; private static bool _wasMenuLevel = true; public static bool IsReadyForGameEvents() { try { bool flag = false; try { flag = (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated; } catch { flag = false; } if (flag && !_wasLevelGenerated) { OnLevelGenerated(); } _wasLevelGenerated = flag; bool flag2 = false; try { flag2 = SemiFunc.MenuLevel(); } catch { flag2 = false; } if (flag2 && !_wasMenuLevel) { OnMenuLevel(); } _wasMenuLevel = flag2; if (!flag || flag2) { return false; } try { if (!AnyPlayerAlive()) { return false; } } catch (Exception ex) { ModLog.Debug("RunGate alive check: " + ex.Message); } return true; } catch (Exception ex2) { ModLog.Debug("RunGate error: " + ex2.Message); return false; } } public static void Tick(float dt) { if (IsReadyForGameEvents()) { EnemyLifetimeGuard.Tick(dt); } } private static void OnLevelGenerated() { ModLog.Info("Level generated — clearing spawn guards"); EnemyLifetimeGuard.Clear(); } private static void OnMenuLevel() { ModLog.Info("Menu level — clearing spawn guards / timers"); EnemyLifetimeGuard.Clear(); try { PlayerEffectHelper.ForceEndMovementShuffle(); } catch { } } private static bool AnyPlayerAlive() { return PlayerTargeting.AnyPlayerAlive(); } } internal static class SpawnBlocklist { private static readonly HashSet BlockedEventIds = new HashSet(StringComparer.OrdinalIgnoreCase) { "spawn_gnome" }; private static readonly HashSet BlockedEnemySlugs = new HashSet(StringComparer.OrdinalIgnoreCase) { "gnome" }; public static bool IsBlockedEventId(string? eventId) { if (string.IsNullOrWhiteSpace(eventId)) { return false; } string text = eventId.Trim().ToLowerInvariant(); if (BlockedEventIds.Contains(text)) { return true; } if (text.StartsWith("spawn_", StringComparison.Ordinal)) { return BlockedEnemySlugs.Contains(text.Substring(6)); } return false; } public static bool IsBlockedEnemy(string? enemyName) { if (string.IsNullOrWhiteSpace(enemyName)) { return false; } if (IsBlockedEventId(enemyName)) { return true; } string text = EnemyRegistry.ResolveInternalName(enemyName); string[] array = new string[2] { enemyName, text }; foreach (string text2 in array) { if (!string.IsNullOrWhiteSpace(text2)) { string item = text2.Trim().ToLowerInvariant().Replace(' ', '_'); if (BlockedEnemySlugs.Contains(item)) { return true; } } } return false; } } internal static class SpawnHelper { private readonly struct SpawnCandidate { public Vector3 Position { get; } public int Priority { get; } public float DistanceToPlayer { get; } public SpawnCandidate(Vector3 position, int priority, float distanceToPlayer) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) Position = position; Priority = priority; DistanceToPlayer = distanceToPlayer; } } public const float ItemForwardBase = 1.1f; public const float ItemForwardSpread = 0.45f; public const float ItemEyeHeightFallback = 1.45f; public const float EnemyForwardOffset = 3f; public const float SellPointForwardOffset = 2.5f; public const float ItemGroundOffset = 0.35f; public const float EnemyGroundOffset = 0.2f; public const float ValuableGroundOffset = 0.35f; public const float MaxSpawnDistanceFromLevelPoint = 16f; public const float MinEnemySpawnDistance = 2.5f; public const float MaxEnemyDoorSpawnDistance = 18f; public const float ActiveNadeForwardDistance = 0.65f; public const float WallCheckDistance = 1.6f; public static Vector3 GetItemSpawnPosition(int index = 0) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return GetItemSpawnPosition(0f, 1f, index); } public static Vector3 GetItemSpawnPosition(float length, float height, int index = 0) { //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00f1: Unknown result type (might be due to invalid IL or missing references) //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_0103: Unknown result type (might be due to invalid IL or missing references) //IL_0105: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar val = EventContext.SoloTarget() ?? SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val == (Object)null) { return GetEyeLevelPositionInFront(index, Mathf.Max(1.1f, length + 0.5f)); } Transform transform = ((Component)val).transform; Vector3 spawnForwardDirection = GetSpawnForwardDirection(); Vector3 val2 = Vector3.Cross(Vector3.up, spawnForwardDirection); Vector3 normalized = ((Vector3)(ref val2)).normalized; float num = ((float)(index % 5) - 2f) * 0.12f; float num2 = ((length > 0.05f) ? length : 1.1f); float num3 = ((height > 0.2f) ? height : 1.45f); try { if ((Object)(object)val.localCamera != (Object)null) { float num4 = ((Component)val.localCamera).transform.position.y - transform.position.y; if (num4 > 0.8f) { num3 = Mathf.Max(num3, num4); } } } catch { } Vector3 candidate = transform.position + spawnForwardDirection * num2 + Vector3.up * num3 + normalized * num; return KeepEyeLevelPosition(candidate, num3); } public static Vector3 KeepEyeLevelPosition(Vector3 candidate, float eyeHeight) { //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_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); float num = playerBodyPosition.y + Mathf.Max(0.95f, eyeHeight * 0.75f); Vector3 val = candidate; if (val.y < num) { val.y = num; } Vector3 spawnForwardDirection = GetSpawnForwardDirection(); Vector3 val2 = playerBodyPosition + Vector3.up * GetEyeHeightOffset(); Vector3 val3 = val - val2; val3.y = 0f; RaycastHit val4 = default(RaycastHit); if (((Vector3)(ref val3)).sqrMagnitude > 0.01f && Physics.Raycast(val2, ((Vector3)(ref val3)).normalized, ref val4, ((Vector3)(ref val3)).magnitude + 0.15f, -1, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val4)).normal.y < 0.55f) { val = playerBodyPosition - spawnForwardDirection * 1.1f + Vector3.up * (val.y - playerBodyPosition.y); if (val.y < num) { val.y = num; } } return val; } public static Vector3 GetActiveItemSpawnPosition(int index = 0) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return GetItemSpawnPosition(0.65f, 1.45f, index); } public static void GetItemOffsetForName(string itemName, out float length, out float height) { length = 0f; height = 1f; string text = (itemName ?? "").ToLowerInvariant(); if (text.Contains("cart") || text.Contains("vehicle") || text.Contains("scooter")) { length = 1f; height = 1f; } } public static Vector3 GetValuableSpawnPosition(int index = 0) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return GetItemSpawnPosition(0f, 1f, index); } public static Vector3 GetEnemySpawnPosition(int index = 0) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return GetInstantEnemySpawnPosition(index); } public static Vector3 GetInstantEnemySpawnPosition(int index = 0) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 playerBodyForward = GetPlayerBodyForward(); Vector3? val = TryGetClosestLevelPointToPlayer(playerBodyPosition, index); if (val.HasValue) { return ClampEnemySpawnNearPlayer(val.Value); } float num = 35f + (float)index * 40f; float num2 = 3.5f + (float)index * 0.35f; Vector3 val2 = Quaternion.Euler(0f, num, 0f) * playerBodyForward; return SnapToFloor(playerBodyPosition + ((Vector3)(ref val2)).normalized * num2, 0.2f); } public static Vector3 GetEnemyFallbackSpawnNearPlayer(int index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 playerBodyForward = GetPlayerBodyForward(); float num = 3.2f + (float)index * 0.4f; return SnapToFloor(playerBodyPosition + playerBodyForward * num, 0.2f); } private static Vector3? TryGetClosestLevelPointToPlayer(Vector3 start, int index) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { return null; } List list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where HorizontalDistance(pos, start) >= 2.125f orderby HorizontalDistanceSqr(pos, start) select pos).ToList(); if (list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos orderby HorizontalDistanceSqr(pos, start) select pos).ToList(); } if (list2.Count == 0) { return null; } return list2[Math.Min(index % list2.Count, list2.Count - 1)]; } catch (Exception ex) { ModLog.Debug("TryGetClosestLevelPointToPlayer failed: " + ex.Message); return null; } } private static Vector3? TryGetClosestLevelPointOutsidePlayerRooms(Vector3 start, int index) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) try { List source = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List(); HashSet playerRoomSet = new HashSet(source.Where((LevelPoint p) => (Object)(object)p != (Object)null)); List list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { return null; } List list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck && !playerRoomSet.Contains(p) select SnapToFloor(((Component)p).transform.position, 0.2f) into pos orderby HorizontalDistanceSqr(pos, start) select pos).ToList(); if (list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos orderby HorizontalDistanceSqr(pos, start) select pos).ToList(); } if (list2.Count == 0) { return null; } return list2[Math.Min(index % list2.Count, list2.Count - 1)]; } catch (Exception ex) { ModLog.Debug("TryGetClosestLevelPointOutsidePlayerRooms failed: " + ex.Message); return null; } } private static Vector3 GetEnemyFallbackSpawnPosition(int index) { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) float yawDegrees = 85f + (float)index * 40f; float distance = 4f + (float)index * 0.35f; return SnapToFloor(GetOffsetFromPlayerBody(distance, yawDegrees), 0.2f); } public static Vector3 GetEnemyClusterPosition(Vector3 basePosition, int index) { //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) if (index <= 0) { return basePosition; } float num = (float)index * 137.50777f * (MathF.PI / 180f); float num2 = Mathf.Min(1.25f, 0.12f + (float)index * 0.03f); Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); return ClampEnemySpawnNearPlayer(basePosition + val); } public static Vector3 GetGrenadeSpreadPosition(int scatterIndex) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) return GetItemSpawnPosition(0.65f, 1.45f, scatterIndex); } public static Vector3 GetEyeLevelPositionInFront(int scatterIndex, float distance) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return GetItemSpawnPosition(distance, 1.45f, scatterIndex); } public static Vector3 ResolveInMapPosition(Vector3 candidate, float groundOffset, int fallbackIndex = 0, bool enemySpawn = false) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) Vector3 val = SnapToFloor(candidate, groundOffset); if (IsInsideMap(val, groundOffset)) { if (!enemySpawn) { return val; } return ClampEnemySpawnNearPlayer(val); } foreach (Vector3 inMapFallbackPosition in GetInMapFallbackPositions(fallbackIndex, groundOffset, enemySpawn)) { if (IsInsideMap(inMapFallbackPosition, groundOffset)) { if (!enemySpawn) { return inMapFallbackPosition; } Vector3 val2 = ClampEnemySpawnNearPlayer(inMapFallbackPosition); if (HorizontalDistance(val2, GetPlayerBodyPosition()) >= 2.5f) { return val2; } } } if (enemySpawn) { return ClampEnemySpawnNearPlayer(GetEnemyFallbackSpawnPosition(fallbackIndex)); } Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 spawnForwardDirection = GetSpawnForwardDirection(); return SnapToFloor(playerBodyPosition + spawnForwardDirection * 1.2f, groundOffset); } public static Vector3 ClampEnemySpawnNearPlayer(Vector3 pos) { //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_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); float num = HorizontalDistance(pos, playerBodyPosition); if (num >= 2.5f) { return SnapToFloor(pos, 0.2f); } Vector3 val = pos - playerBodyPosition; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f || Vector3.Dot(GetPlayerBodyForward(), ((Vector3)(ref val)).normalized) > 0.55f) { val = Quaternion.Euler(0f, 75f + Random.Range(-15f, 15f), 0f) * GetPlayerBodyForward(); } return SnapToFloor(playerBodyPosition + ((Vector3)(ref val)).normalized * 2.5f, 0.2f); } public static Vector3 EnforceEnemySpawnDistance(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ClampEnemySpawnNearPlayer(pos); } public static Vector3 GetSpawnForwardDirection() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_004e: 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_0047: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyForward = GetPlayerBodyForward(); Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 val = playerBodyPosition + Vector3.up * GetEyeHeightOffset(); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, playerBodyForward, ref val2, 1.6f, -1, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val2)).normal.y < 0.55f) { return -playerBodyForward; } return playerBodyForward; } private static bool IsDirectlyAheadOfPlayer(Vector3 pos, float maxDistance) { //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_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0040: 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) Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 val = pos - playerBodyPosition; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > maxDistance * maxDistance) { return false; } if (((Vector3)(ref val)).sqrMagnitude < 0.25f) { return true; } Vector3 playerBodyForward = GetPlayerBodyForward(); float num = Vector3.Dot(((Vector3)(ref playerBodyForward)).normalized, ((Vector3)(ref val)).normalized); return num > 0.55f; } private static Vector3? TryGetEnemySpawnAtNearestDoor(int index) { //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_0301: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fc: 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_010b: Unknown result type (might be due to invalid IL or missing references) //IL_010e: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_01ee: Unknown result type (might be due to invalid IL or missing references) //IL_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0209: Unknown result type (might be due to invalid IL or missing references) //IL_020c: Unknown result type (might be due to invalid IL or missing references) //IL_0213: Unknown result type (might be due to invalid IL or missing references) try { Vector3 playerPos = GetPlayerBodyPosition(); List source = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List(); HashSet hashSet = new HashSet(source.Where((LevelPoint p) => (Object)(object)p != (Object)null)); List candidates = new List(); HashSet seen = new HashSet(); foreach (LevelPoint item2 in source.Where((LevelPoint p) => (Object)(object)p != (Object)null && !p.Truck)) { if (!item2.ModuleConnect || item2.ConnectedPoints == null) { continue; } foreach (LevelPoint connectedPoint in item2.ConnectedPoints) { if (!((Object)(object)connectedPoint == (Object)null) && !connectedPoint.Truck && !hashSet.Contains(connectedPoint)) { Vector3 position = Vector3.Lerp(((Component)item2).transform.position, ((Component)connectedPoint).transform.position, 0.58f); AddDoorCandidate(SnapToFloor(position, 0.2f)); } } } List list = SemiFunc.LevelPointsGetAll(); if (list != null) { foreach (LevelPoint item3 in list.Where((LevelPoint p) => (Object)(object)p != (Object)null && !p.Truck && p.ModuleConnect)) { if (!hashSet.Contains(item3) || item3.ConnectedPoints == null) { continue; } foreach (LevelPoint connectedPoint2 in item3.ConnectedPoints) { if (!((Object)(object)connectedPoint2 == (Object)null) && !connectedPoint2.Truck && !hashSet.Contains(connectedPoint2)) { Vector3 position2 = Vector3.Lerp(((Component)item3).transform.position, ((Component)connectedPoint2).transform.position, 0.58f); AddDoorCandidate(SnapToFloor(position2, 0.2f)); } } } } if (candidates.Count == 0) { return null; } List list2 = (from pos in candidates where HorizontalDistance(pos, playerPos) >= 2.5f where !IsDirectlyAheadOfPlayer(pos, 3.5f) orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); if (list2.Count == 0) { list2 = candidates.OrderBy((Vector3 pos) => HorizontalDistanceSqr(pos, playerPos)).ToList(); } return list2[Math.Min(index % list2.Count, list2.Count - 1)]; void AddDoorCandidate(Vector3 pos) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (!(HorizontalDistance(pos, playerPos) > 18f)) { long item = ((long)Mathf.Round(pos.x * 4f) << 32) | (uint)Mathf.Round(pos.z * 4f); if (seen.Add(item)) { candidates.Add(pos); } } } } catch (Exception ex) { ModLog.Debug("TryGetEnemySpawnAtNearestDoor failed: " + ex.Message); return null; } } private static Vector3? TryGetEnemySpawnOutsidePlayerRoom(int index) { //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_02d5: Unknown result type (might be due to invalid IL or missing references) try { Vector3 playerPos = GetPlayerBodyPosition(); List source = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List(); HashSet playerRoomSet = new HashSet(source.Where((LevelPoint p) => (Object)(object)p != (Object)null)); List list = SemiFunc.LevelPointsGetAll(); if (list == null || list.Count == 0) { return null; } float minDistSqr = 6.25f; List list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck && !playerRoomSet.Contains(p) select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where HorizontalDistanceSqr(pos, playerPos) >= minDistSqr where HorizontalDistance(pos, playerPos) <= 18f where !HudRoomHelper.IsInCurrentRoom(pos) where !IsDirectlyAheadOfPlayer(pos, 6f) orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); if (list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where HorizontalDistanceSqr(pos, playerPos) >= minDistSqr where HorizontalDistance(pos, playerPos) <= 18f where !HudRoomHelper.IsInCurrentRoom(pos) where !IsDirectlyAheadOfPlayer(pos, 6f) orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); } if (list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where HorizontalDistanceSqr(pos, playerPos) >= minDistSqr where !HudRoomHelper.IsInCurrentRoom(pos) orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); } if (list2.Count == 0) { return null; } return list2[Math.Min(index % list2.Count, list2.Count - 1)]; } catch (Exception ex) { ModLog.Debug("TryGetEnemySpawnOutsidePlayerRoom failed: " + ex.Message); return null; } } private static bool IsInsideMap(Vector3 pos, float groundOffset) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) if (IsPositionInTruckArea(pos)) { return false; } float y = GetPlayerBodyPosition().y; RaycastHit? val = FindFloorHit(pos, y, 12f); if (!val.HasValue) { return false; } RaycastHit value = val.Value; Vector3 point = ((RaycastHit)(ref value)).point; if (Physics.Raycast(point + Vector3.up * 0.08f, Vector3.up, 0.55f, -1, (QueryTriggerInteraction)1)) { return false; } if (!IsNearValidLevelPoint(point)) { return false; } return true; } private static bool IsPositionInTruckArea(Vector3 pos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) try { if (SemiFunc.MenuLevel()) { return true; } } catch { } SpawnPoint[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return false; } return array.Any((SpawnPoint p) => (Object)(object)p != (Object)null && HorizontalDistanceSqr(((Component)p).transform.position, pos) < 64f); } private static bool IsNearValidLevelPoint(Vector3 pos) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetAll(); if (list != null && list.Count > 0) { return list.Any((LevelPoint p) => (Object)(object)p != (Object)null && !p.Truck && HorizontalDistance(((Component)p).transform.position, pos) <= 16f); } List list2 = SemiFunc.LevelPointGetWithinDistance(GetPlayerBodyPosition(), 2f, 22f); if (list2 != null && list2.Count > 0) { return list2.Any((LevelPoint p) => (Object)(object)p != (Object)null && !p.Truck && HorizontalDistance(((Component)p).transform.position, pos) <= 16f); } List list3 = SemiFunc.LevelPointsGetInPlayerRooms(); if (list3 != null && list3.Count > 0) { return list3.Any((LevelPoint p) => (Object)(object)p != (Object)null && !p.Truck && HorizontalDistance(((Component)p).transform.position, pos) <= 16f); } } catch (Exception ex) { ModLog.Debug("IsNearValidLevelPoint failed: " + ex.Message); } return false; } private static IEnumerable GetInMapFallbackPositions(int index, float groundOffset, bool enemySpawn = false) { for (int i = 0; i < 10; i++) { int idx = (index + i) % 10; Vector3? val = TryGetNearbyLevelPointSpawn(idx, enemySpawn); if (val.HasValue) { yield return val.Value; } Vector3? val2 = TryGetStartRoomLevelPoint(idx, enemySpawn); if (val2.HasValue) { yield return val2.Value; } } if (enemySpawn) { for (int i = 0; i < 8; i++) { yield return GetEnemyFallbackSpawnPosition(index + i); } yield break; } Vector3 body = GetPlayerBodyPosition(); Vector3 forward = GetSpawnForwardDirection(); for (int i = 0; i < 6; i++) { float num = (float)i * 60f + (float)index * 13f; Vector3 val3 = Quaternion.Euler(0f, num, 0f) * forward; Vector3 normalized = ((Vector3)(ref val3)).normalized; yield return SnapToFloor(body + normalized * (0.9f + (float)i * 0.25f), groundOffset); } Vector3 val4 = -GetPlayerBodyForward(); yield return SnapToFloor(body + val4 * 1.4f, groundOffset); } private static bool ShouldUseExteriorEnemySpawn() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) if (IsInTruckArea()) { return true; } try { Vector3 playerPos = GetPlayerBodyPosition(); List list = SemiFunc.LevelPointsGetInStartRoom(); if (list == null || list.Count == 0) { return false; } return list.Any((LevelPoint p) => (Object)(object)p != (Object)null && HorizontalDistanceSqr(((Component)p).transform.position, playerPos) < 144f); } catch { return false; } } private static Vector3? TryGetExteriorDoorSpawn(int index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_02b5: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_0182: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0191: Unknown result type (might be due to invalid IL or missing references) //IL_0193: Unknown result type (might be due to invalid IL or missing references) //IL_0195: Unknown result type (might be due to invalid IL or missing references) //IL_01d3: Unknown result type (might be due to invalid IL or missing references) //IL_01d7: Unknown result type (might be due to invalid IL or missing references) //IL_01d9: Unknown result type (might be due to invalid IL or missing references) Vector3 truckReferencePosition = GetTruckReferencePosition(); Vector3 playerBodyPosition = GetPlayerBodyPosition(); List list = new List(); try { List list2 = SemiFunc.LevelPointsGetAll(); if (list2 != null) { foreach (LevelPoint item in list2) { if ((Object)(object)item == (Object)null || item.Truck) { continue; } Vector3 val = SnapToFloor(((Component)item).transform.position, 0.2f); float num = HorizontalDistance(val, truckReferencePosition); if (!(num < 4.5f)) { int num2 = 100; if (item.ModuleConnect) { num2 -= 40; } if (!item.inStartRoom) { num2 -= 25; } num2 = ((num >= 5f && num <= 8.5f) ? (num2 - 20) : ((!(num <= 12f)) ? (num2 + 15) : (num2 - 5))); list.Add(new SpawnCandidate(val, num2, HorizontalDistanceSqr(val, playerBodyPosition))); } } foreach (LevelPoint item2 in list2.Where((LevelPoint p) => (Object)(object)p != (Object)null && p.inStartRoom && p.ModuleConnect)) { if (item2.ConnectedPoints == null) { continue; } foreach (LevelPoint connectedPoint in item2.ConnectedPoints) { if ((Object)(object)connectedPoint == (Object)null || connectedPoint.Truck) { continue; } Vector3 val2 = SnapToFloor(((Component)connectedPoint).transform.position, 0.2f); float num3 = HorizontalDistance(val2, truckReferencePosition); if (!(num3 < 4.5f)) { int num4 = 10; if (connectedPoint.ModuleConnect) { num4 -= 5; } if (num3 >= 5f && num3 <= 8.5f) { num4 -= 10; } list.Add(new SpawnCandidate(val2, num4, HorizontalDistanceSqr(val2, playerBodyPosition))); } } } } } catch (Exception ex) { ModLog.Debug("TryGetExteriorDoorSpawn level points failed: " + ex.Message); } if (list.Count == 0) { return GetTruckExteriorSpawn(index); } List list3 = (from c in list orderby c.Priority, c.DistanceToPlayer select c).ToList(); return list3[Math.Min(index, list3.Count - 1)].Position; } private static Vector3 GetTruckReferencePosition() { //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00a5: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) SpawnPoint[] array = Object.FindObjectsOfType(); if (array != null && array.Length != 0) { List list = (from p in array where (Object)(object)p != (Object)null select ((Component)p).transform.position).ToList(); if (list.Count > 0) { Vector3 val = Vector3.zero; foreach (Vector3 item in list) { val += item; } return val / (float)list.Count; } } return GetPlayerBodyPosition(); } public static Vector3 SnapToGround(Vector3 position, float heightOffset = 0.35f) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return SnapToFloor(position, heightOffset); } public static Vector3 SnapToFloor(Vector3 position, float heightOffset) { //IL_0000: 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_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) float y = GetPlayerBodyPosition().y; RaycastHit? val = FindFloorHit(position, y, 12f); RaycastHit value; if (val.HasValue) { value = val.Value; return ((RaycastHit)(ref value)).point + Vector3.up * heightOffset; } val = FindFloorHit(position + Vector3.up * 40f, y, 120f); if (val.HasValue) { value = val.Value; return ((RaycastHit)(ref value)).point + Vector3.up * heightOffset; } return new Vector3(position.x, y + heightOffset, position.z); } private static Vector3 ResolveVisibleSpawnPosition(int index, float forwardDistance, Vector3? forwardOverride = null, bool holdAtEyeLevel = false) { //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_001b: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 val = (Vector3)(((??)forwardOverride) ?? GetSpawnForwardDirection()); float num = (float)index * 22f; Vector3 val2 = Quaternion.Euler(0f, num, 0f) * val; Vector3 normalized = ((Vector3)(ref val2)).normalized; float eyeHeightOffset = GetEyeHeightOffset(); Vector3 eyeOrigin = playerBodyPosition + Vector3.up * eyeHeightOffset; Vector3 val3 = AvoidObstacleSpawn(eyeOrigin, normalized, forwardDistance, eyeHeightOffset); if (holdAtEyeLevel) { return val3; } return SnapToFloor(val3, 0.35f); } private static Vector3 AvoidObstacleSpawn(Vector3 eyeOrigin, Vector3 dir, float forwardDistance, float eyeHeight) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_00e0: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_010a: Unknown result type (might be due to invalid IL or missing references) //IL_010f: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Unknown result type (might be due to invalid IL or missing references) //IL_011a: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0126: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_00f8: Unknown result type (might be due to invalid IL or missing references) //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00bf: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0146: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) Vector3 result = eyeOrigin + dir * forwardDistance; RaycastHit val = default(RaycastHit); Vector3 val2; if (Physics.Raycast(eyeOrigin, dir, ref val, forwardDistance + 0.35f, -1, (QueryTriggerInteraction)1)) { if (((RaycastHit)(ref val)).normal.y > 0.55f && ((RaycastHit)(ref val)).point.y > GetPlayerBodyPosition().y + 0.25f) { return ((RaycastHit)(ref val)).point + Vector3.up * 0.35f; } Vector3 playerBodyPosition = GetPlayerBodyPosition(); val2 = GetPlayerBodyForward(); Vector3 val3 = -((Vector3)(ref val2)).normalized; float num = Random.Range(-25f, 25f); val2 = Quaternion.Euler(0f, num, 0f) * val3; val3 = ((Vector3)(ref val2)).normalized; return SnapToFloor(playerBodyPosition + val3 * (forwardDistance + 0.4f), 0.35f); } RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(eyeOrigin, Vector3.up, ref val4, 2.2f, -1, (QueryTriggerInteraction)1) || Physics.Raycast(eyeOrigin, dir, ref val4, 0.6f, -1, (QueryTriggerInteraction)1)) { Vector3 playerBodyPosition2 = GetPlayerBodyPosition(); val2 = GetPlayerBodyForward(); Vector3 val5 = -((Vector3)(ref val2)).normalized; return SnapToFloor(playerBodyPosition2 + val5 * (forwardDistance + 0.5f), 0.35f); } return result; } private static float GetEyeHeightOffset() { //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) PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val?.localCamera != (Object)null) { return Mathf.Max(1.15f, ((Component)val.localCamera).transform.position.y - GetPlayerBodyPosition().y); } return 1.45f; } private static RaycastHit? FindFloorHit(Vector3 fromPosition, float referenceY, float maxDistance) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) Vector3 val = fromPosition + Vector3.up * 0.5f; RaycastHit[] array = Physics.RaycastAll(val, Vector3.down, maxDistance, -1, (QueryTriggerInteraction)1); RaycastHit? result = null; float num = float.MaxValue; RaycastHit[] array2 = array; for (int i = 0; i < array2.Length; i++) { RaycastHit value = array2[i]; if (!(((RaycastHit)(ref value)).normal.y < 0.6f) && !(((RaycastHit)(ref value)).point.y > referenceY + 1.5f)) { float num2 = Mathf.Abs(((RaycastHit)(ref value)).point.y - referenceY) + HorizontalDistance(((RaycastHit)(ref value)).point, fromPosition) * 0.05f; if (!(num2 >= num)) { num = num2; result = value; } } } return result; } private static bool IsShopDoorOpen() { TruckDoor[] array = Object.FindObjectsOfType(); foreach (TruckDoor val in array) { if ((Object)(object)val != (Object)null && val.doorOpen) { return true; } } MonoBehaviour[] array2 = Object.FindObjectsOfType(); foreach (MonoBehaviour val2 in array2) { if (!((Object)(object)val2 == (Object)null)) { FieldInfo field = ((object)val2).GetType().GetField("doorOpen", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field?.FieldType == typeof(bool) && (bool)field.GetValue(val2)) { return true; } } } return false; } private static bool IsInTruckArea() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) try { if (SemiFunc.MenuLevel()) { return true; } } catch { } Vector3 playerPos = GetPlayerPosition(); SpawnPoint[] array = Object.FindObjectsOfType(); if (array == null || array.Length == 0) { return false; } return array.Any((SpawnPoint p) => (Object)(object)p != (Object)null && HorizontalDistanceSqr(((Component)p).transform.position, playerPos) < 36f); } public static Vector3? TryGetNearbyLevelPointSpawn(int index, bool enemySpawn = false) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_023b: Unknown result type (might be due to invalid IL or missing references) try { Vector3 playerPos = GetPlayerBodyPosition(); float num = (enemySpawn ? 2.5f : 0f); float minDistSqr = num * num; List list = SemiFunc.LevelPointGetWithinDistance(playerPos, num, enemySpawn ? 48f : 22f); if (list == null || list.Count == 0) { return null; } List list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where !enemySpawn || HorizontalDistanceSqr(pos, playerPos) >= minDistSqr where !enemySpawn || !IsDirectlyAheadOfPlayer(pos, 6f) orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); if (enemySpawn && list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where HorizontalDistanceSqr(pos, playerPos) >= minDistSqr orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); } else if (!enemySpawn && list2.Count == 0) { list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); } if (list2.Count == 0) { return null; } return list2[Math.Min(index, list2.Count - 1)]; } catch { return null; } } public static Vector3? TryGetStartRoomLevelPoint(int index, bool enemySpawn = false) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) try { Vector3 playerPos = GetPlayerBodyPosition(); List list = SemiFunc.LevelPointsGetInStartRoom(); if (list == null || list.Count == 0) { return null; } List list2 = (from p in list where (Object)(object)p != (Object)null && !p.Truck select SnapToFloor(((Component)p).transform.position, 0.2f) into pos where !enemySpawn || HorizontalDistanceSqr(pos, playerPos) >= 6.25f orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); if (list2.Count == 0) { return null; } return list2[Math.Min(index, list2.Count - 1)]; } catch { return null; } } private static Vector3? GetTruckExteriorSpawn(int index) { //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_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00ba: Unknown result type (might be due to invalid IL or missing references) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00eb: Unknown result type (might be due to invalid IL or missing references) //IL_00ef: Unknown result type (might be due to invalid IL or missing references) //IL_00f4: Unknown result type (might be due to invalid IL or missing references) //IL_00fe: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) Vector3 truckReferencePosition = GetTruckReferencePosition(); Vector3 playerPos = GetPlayerPosition(); SpawnPoint[] array = Object.FindObjectsOfType(); if (array != null && array.Length != 0) { List list = (from p in array where (Object)(object)p != (Object)null select ((Component)p).transform.position into pos orderby HorizontalDistanceSqr(pos, playerPos) select pos).ToList(); if (list.Count > 0) { Vector3 val = list[Math.Min(index, list.Count - 1)]; Vector3 val2 = val - truckReferencePosition; Vector3 normalized = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref normalized)).sqrMagnitude < 0.01f) { val2 = GetPlayerBodyForward(); normalized = ((Vector3)(ref val2)).normalized; } float num = 6.5f + (float)index * 0.35f; return SnapToFloor(truckReferencePosition + normalized * num, 0.2f); } } return SnapToFloor(GetOffsetFromPlayerBody(6.5f + (float)index * 1.5f, (float)index * 60f), 0.2f); } public static Vector3 GetPlayerPosition() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetPlayerBodyPosition(); } public static Vector3 GetPlayerForward() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetPlayerBodyForward(); } public static Vector3 GetPlayerBodyPosition() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) Transform playerBodyTransform = GetPlayerBodyTransform(); if (!((Object)(object)playerBodyTransform != (Object)null)) { return Vector3.up * 2f; } return playerBodyTransform.position; } public static Vector3 GetPlayerBodyForward() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) Transform playerBodyTransform = GetPlayerBodyTransform(); if ((Object)(object)playerBodyTransform == (Object)null) { return Vector3.forward; } Vector3 forward = playerBodyTransform.forward; forward.y = 0f; if (!(((Vector3)(ref forward)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private static Vector3 GetOffsetFromPlayerBody(float distance, float yawDegrees) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) Vector3 playerBodyPosition = GetPlayerBodyPosition(); Vector3 playerBodyForward = GetPlayerBodyForward(); Vector3 val = Quaternion.Euler(0f, yawDegrees, 0f) * playerBodyForward; return playerBodyPosition + ((Vector3)(ref val)).normalized * distance; } private static Transform? GetPlayerBodyTransform() { PlayerAvatar val = EventContext.SoloTarget() ?? SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null) { return ((Component)val).transform; } GameObject val2 = GameObject.FindGameObjectWithTag("Player"); if (!((Object)(object)val2 != (Object)null)) { return null; } return val2.transform; } private static float HorizontalDistanceSqr(Vector3 a, Vector3 b) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) a.y = 0f; b.y = 0f; Vector3 val = a - b; return ((Vector3)(ref val)).sqrMagnitude; } private static float HorizontalDistance(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) return Mathf.Sqrt(HorizontalDistanceSqr(a, b)); } } internal static class SpeakHelper { private const int MaxLength = 180; private static string _pendingMessage = ""; private static string _pendingUser = "viewer"; private static MethodInfo? _chatMessageSend; private static bool _chatMethodResolved; public static CommandResult TrySpeak(string text, string user) { if (string.IsNullOrWhiteSpace(text)) { return CommandResult.Fail("speak_requires_text"); } string text2 = Sanitize(text.Trim()); if (text2.Length == 0) { return CommandResult.Fail("speak_requires_text"); } if (text2.Length > 180) { text2 = text2.Substring(0, 180); } _pendingMessage = text2; _pendingUser = (string.IsNullOrWhiteSpace(user) ? "viewer" : user.Trim()); BurstCoalescer.Debounce("repo_speak", FlushPendingSpeak); return CommandResult.Ok("speak_queued", text2); } public static void ForceSpeakNow(string text) { string text2 = Sanitize((text ?? "").Trim()); if (text2.Length != 0) { if (text2.Length > 180) { text2 = text2.Substring(0, 180); } SendChat(text2); } } private static void FlushPendingSpeak() { string pendingMessage = _pendingMessage; string pendingUser = _pendingUser; _pendingMessage = ""; if (string.IsNullOrWhiteSpace(pendingMessage)) { return; } try { if (SemiFunc.MenuLevel()) { ModLog.Debug("Speak skipped — not in level"); return; } SpeakOnAllPlayers(pendingMessage); ModLog.Info("In-game speak all (burst @" + pendingUser + "): " + pendingMessage); } catch (Exception ex) { ModLog.Error("Speak failed: " + ex.Message); } } public static void SpeakOnAllPlayers(string text) { string text2 = Sanitize((text ?? "").Trim()); if (text2.Length == 0) { return; } if (text2.Length > 180) { text2 = text2.Substring(0, 180); } if (SemiFunc.MenuLevel()) { return; } int num = 0; List list = PlayerTargeting.AlivePlayers(); if (list.Count == 0) { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null) { list.Add(val); } } foreach (PlayerAvatar item in list) { if (!((Object)(object)item == (Object)null) && SpeakAsAvatar(item, text2)) { num++; } } if (num == 0) { SpeakBroadcast.Broadcast(text2); } } private static float SpeakTime(string message) { int num = Math.Max(1, (message ?? "").Length); return Mathf.Clamp((float)num * 0.12f, 3.4f, 16f); } private static float SpeakFloatArg(ParameterInfo p, string message) { string text = (p.Name ?? "").ToLowerInvariant(); if (text.Contains("rate") || text.Contains("speed") || text.Contains("pitch") || text.Contains("mult")) { return 0.7f; } return SpeakTime(message); } private static bool SpeakAsAvatar(PlayerAvatar player, string message) { try { EnsureChatMethod(); bool result = false; if (_chatMessageSend != null) { ParameterInfo[] parameters = _chatMessageSend.GetParameters(); object[] array = new object[parameters.Length]; for (int i = 0; i < parameters.Length; i++) { ParameterInfo parameterInfo = parameters[i]; if (parameterInfo.ParameterType == typeof(string)) { array[i] = message; } else if (parameterInfo.ParameterType == typeof(bool)) { array[i] = false; } else if (parameterInfo.ParameterType == typeof(float)) { array[i] = SpeakFloatArg(parameterInfo, message); } else if (parameterInfo.HasDefaultValue) { array[i] = parameterInfo.DefaultValue; } else { array[i] = (parameterInfo.ParameterType.IsValueType ? Activator.CreateInstance(parameterInfo.ParameterType) : null); } } _chatMessageSend.Invoke(player, array); result = true; } PhotonView photonView = player.photonView; PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((!((Object)(object)val != (Object)null) || (!((Object)(object)player == (Object)(object)val) && (!((Object)(object)photonView != (Object)null) || !((Object)(object)val.photonView != (Object)null) || photonView.ViewID != val.photonView.ViewID))) && (Object)(object)photonView != (Object)null) { try { photonView.RPC("ChatMessageSendRPC", (RpcTarget)0, new object[1] { message }); result = true; } catch { try { photonView.RPC("ChatMessageSendRPC", (RpcTarget)0, new object[2] { message, false }); result = true; } catch { } } } return result; } catch (Exception ex) { ModLog.Debug("SpeakAsAvatar failed: " + ex.Message); return false; } } private static void EnsureChatMethod() { if (_chatMethodResolved) { return; } _chatMethodResolved = true; try { MethodInfo[] methods = typeof(PlayerAvatar).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!(methodInfo.Name != "ChatMessageSend")) { ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != 0 && !(parameters[0].ParameterType != typeof(string))) { _chatMessageSend = methodInfo; break; } } } } catch (Exception ex) { ModLog.Debug("ChatMessageSend resolve failed: " + ex.Message); } } private static void SendChat(string message) { try { if (!SemiFunc.MenuLevel()) { if ((Object)(object)ChatManager.instance == (Object)null) { GameNotifier.AnnounceCustom("Voice Troll", message, 3f); return; } ChatManager.instance.ForceSendMessage(message); TryPossessChat(message); } } catch (Exception ex) { ModLog.Debug("Force speak failed: " + ex.Message); } } private static void TryPossessChat(string message) { //IL_00dc: Unknown result type (might be due to invalid IL or missing references) try { ChatManager instance = ChatManager.instance; if ((Object)(object)instance == (Object)null) { return; } MethodInfo[] methods = ((object)instance).GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "PossessChat") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length < 2) { continue; } object[] array = new object[parameters.Length]; for (int j = 0; j < parameters.Length; j++) { ParameterInfo parameterInfo = parameters[j]; if (parameterInfo.ParameterType == typeof(string)) { array[j] = message; } else if (parameterInfo.ParameterType == typeof(float)) { array[j] = SpeakFloatArg(parameterInfo, message); } else if (parameterInfo.ParameterType == typeof(Color)) { array[j] = Color.white; } else if (parameterInfo.ParameterType == typeof(bool)) { array[j] = true; } else if (parameterInfo.ParameterType.IsEnum) { array[j] = Enum.ToObject(parameterInfo.ParameterType, 0); } else if (parameterInfo.HasDefaultValue) { array[j] = parameterInfo.DefaultValue; } else { array[j] = (parameterInfo.ParameterType.IsValueType ? Activator.CreateInstance(parameterInfo.ParameterType) : null); } } methodInfo.Invoke(instance, array); break; } } catch { } } private static string Sanitize(string input) { StringBuilder stringBuilder = new StringBuilder(input.Length); foreach (char c in input) { if (!char.IsControl(c) || c == '\n' || c == '\r') { stringBuilder.Append(c); } } return stringBuilder.ToString().Trim(); } } internal static class SpecialEffectHelper { private static readonly string[] RandomNadeKinds = new string[3] { "stun", "shock", "expl" }; private static readonly Dictionary _poopRemaining = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly string[] RandomSpeakLines = new string[15] { "Help me!", "Watch out!", "I got this!", "Run!", "Oh no!", "Don't leave me!", "That was close!", "I need backup!", "Grab that!", "Why is it always me?", "This is fine.", "Chat did this!", "Not again...", "Someone save me!", "I blame the stream!" }; public static bool SpawnToyCarsAroundPlayer(int count = 5) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return false; } Vector3 position = ((Component)localPlayer).transform.position; int num = 0; for (int i = 0; i < Mathf.Max(1, count); i++) { float num2 = 360f / (float)Mathf.Max(1, count) * (float)i * (MathF.PI / 180f); Vector3 val = new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * 1.65f; Vector3 pos = SpawnHelper.ResolveInMapPosition(position + val, 0.35f, i); if (TrySpawnToyCar(pos, out GameObject spawned)) { bool flag = Random.value < 0.2f; OrientToyCarToward(spawned, flag ? (position + Vector3.up * 0.35f) : GetRandomMapDriveTarget(position)); ActivateToyCar(spawned, flag); num++; } } return num > 0; } private static bool TrySpawnToyCar(Vector3 pos, out GameObject? spawned) { //IL_0003: 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_001e: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) spawned = null; if (TrySpawnToyCarFromRepolib(pos, out spawned)) { return true; } if (TrySpawnToyCarFromResources(pos, out spawned)) { return true; } if (ValuableSpawnHelper.TrySpawn("Toy Car", pos, Quaternion.identity, out string _, out spawned)) { return (Object)(object)spawned != (Object)null; } return false; } private static bool TrySpawnToyCarFromRepolib(Vector3 pos, out GameObject? spawned) { //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) spawned = null; try { IReadOnlyList allValuables = Valuables.AllValuables; if (allValuables == null) { return false; } foreach (PrefabRef item in allValuables.Where((PrefabRef v) => ((PrefabRef)(object)v)?.IsValid() ?? false)) { string text = (((PrefabRef)(object)item).PrefabName ?? "").ToLowerInvariant(); if (text.Contains("keycard") || text.Contains("key card") || text.Contains("cart")) { continue; } GameObject prefab = ((PrefabRef)(object)item).Prefab; if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab.GetComponentInChildren(true) == (Object)null)) { spawned = Valuables.SpawnValuable(item, pos, Quaternion.identity); if ((Object)(object)spawned != (Object)null) { ModLog.Info("Spawned toy car via REPOLib: " + ((PrefabRef)(object)item).PrefabName); return true; } } } } catch (Exception ex) { ModLog.Debug("Toy car REPOLib search failed: " + ex.Message); } return false; } private static bool TrySpawnToyCarFromResources(Vector3 pos, out GameObject? spawned) { //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) spawned = null; try { GameObject[] array = Resources.LoadAll("Valuables"); foreach (GameObject val in array) { if (!((Object)(object)val == (Object)null) && !((Object)(object)val.GetComponentInChildren(true) == (Object)null)) { spawned = Object.Instantiate(val, pos, Quaternion.identity); if ((Object)(object)spawned != (Object)null) { ModLog.Info("Spawned toy car via Resources: " + ((Object)val).name); return true; } } } } catch (Exception ex) { ModLog.Debug("Toy car Resources search failed: " + ex.Message); } return false; } private static void OrientToyCarToward(GameObject? go, Vector3 target) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)go == (Object)null)) { Vector3 val = target - go.transform.position; val.y = 0f; if (!(((Vector3)(ref val)).sqrMagnitude < 0.01f)) { go.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val)).normalized, Vector3.up); } } } private static Vector3 GetRandomMapDriveTarget(Vector3 fallback) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetAll(); if (list != null && list.Count > 0) { List list2 = list.Where((LevelPoint p) => (Object)(object)p != (Object)null).ToList(); if (list2.Count > 0) { return ((Component)list2[Random.Range(0, list2.Count)]).transform.position; } } } catch { } return fallback; } private static void ActivateToyCar(GameObject? go, bool aggressive) { if ((Object)(object)go == (Object)null) { return; } ValuableCar componentInChildren = go.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { ReleaseGrabState(go); try { ((Trap)componentInChildren).TrapStart(); } catch (Exception ex) { ModLog.Debug("ActivateToyCar TrapStart failed: " + ex.Message); } ToyCarDriveBehavior toyCarDriveBehavior = go.GetComponent() ?? go.AddComponent(); toyCarDriveBehavior.Configure(componentInChildren, aggressive); } } private static void ActivateChompBook(GameObject? go) { if (!((Object)(object)go == (Object)null)) { ReleaseGrabState(go); EffectTimerHost.Instance.RunRoutine(ActivateChompBookRoutine(go)); } } private static IEnumerator ActivateChompBookRoutine(GameObject go) { yield return null; if (!((Object)(object)go == (Object)null)) { ReleaseGrabState(go); ItemPostSpawnHelper.EnsureUsablePublic(go); TryStartChompTrap(go); yield return (object)new WaitForSeconds(0.25f); if (!((Object)(object)go == (Object)null)) { ReleaseGrabState(go); TryStartChompTrap(go); } } } private static void TryStartChompTrap(GameObject go) { ChompBookTrap componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { ModLog.Warn("Chomp Book spawned without ChompBookTrap"); return; } ((Trap)componentInChildren).isLocal = true; ((Trap)componentInChildren).trapTriggered = false; ((Trap)componentInChildren).trapStart = true; if (componentInChildren.biteAmount < 8) { componentInChildren.biteAmount = 12; } try { componentInChildren.TrapActivate(); } catch { TryInvokeNamed(componentInChildren, "TrapActivate"); } ChompBookHuntBehavior chompBookHuntBehavior = go.GetComponent() ?? go.AddComponent(); chompBookHuntBehavior.Configure(componentInChildren); ModLog.Info("Chomp Book trap armed (chase/bite)"); } private static void TryInvokeNamed(object target, string methodName) { try { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(method == null) && method.GetParameters().Length == 0) { method.Invoke(target, null); } } catch { } } private static void ReleaseGrabState(GameObject go) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) Rigidbody[] componentsInChildren = go.GetComponentsInChildren(true); foreach (Rigidbody val in componentsInChildren) { val.isKinematic = false; val.WakeUp(); val.velocity = Vector3.zero; val.angularVelocity = Vector3.zero; } PhysGrabObject[] componentsInChildren2 = go.GetComponentsInChildren(true); foreach (PhysGrabObject val2 in componentsInChildren2) { try { ((Behaviour)val2).enabled = true; } catch { } } } public static bool SpawnToyPlanesAroundPlayer(int count = 5) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return false; } Vector3 position = ((Component)localPlayer).transform.position; int num = 0; for (int i = 0; i < Mathf.Max(1, count); i++) { float num2 = 360f / (float)Mathf.Max(1, count) * (float)i * (MathF.PI / 180f); Vector3 horizontalOffset = new Vector3(Mathf.Cos(num2), 0f, Mathf.Sin(num2)) * 0.65f; if (TrySpawnToyPlane(position, horizontalOffset, out GameObject spawned)) { ActivateToyPlane(spawned); num++; } } return num > 0; } private static bool TrySpawnToyPlane(Vector3 nearPlayer, Vector3 horizontalOffset, out GameObject? spawned) { //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_014c: Unknown result type (might be due to invalid IL or missing references) //IL_014d: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) spawned = null; Vector3 val = nearPlayer + Vector3.up * 1.55f; Vector3 val2 = val + horizontalOffset; try { IReadOnlyList allValuables = Valuables.AllValuables; if (allValuables != null) { foreach (PrefabRef item in allValuables.Where((PrefabRef v) => ((PrefabRef)(object)v)?.IsValid() ?? false)) { GameObject prefab = ((PrefabRef)(object)item).Prefab; if (!((Object)(object)prefab == (Object)null) && !((Object)(object)prefab.GetComponentInChildren(true) == (Object)null)) { spawned = Valuables.SpawnValuable(item, val2, Quaternion.identity); if ((Object)(object)spawned != (Object)null) { ModLog.Info("Spawned toy plane via REPOLib: " + ((PrefabRef)(object)item).PrefabName); return true; } } } } } catch (Exception ex) { ModLog.Debug("Toy plane REPOLib search failed: " + ex.Message); } GameObject[] array = Resources.LoadAll("Valuables"); foreach (GameObject val3 in array) { if (!((Object)(object)val3 == (Object)null) && !((Object)(object)val3.GetComponentInChildren(true) == (Object)null)) { spawned = Object.Instantiate(val3, val2, Quaternion.identity); if ((Object)(object)spawned != (Object)null) { return true; } } } if (ValuableSpawnHelper.TrySpawn("Toy Plane", val2, Quaternion.identity, out string _, out spawned)) { return (Object)(object)spawned != (Object)null; } return false; } private static void ActivateToyPlane(GameObject? go) { if (!((Object)(object)go == (Object)null)) { ValuablePlane componentInChildren = go.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { ReleaseGrabState(go); ToyPlaneDriveBehavior toyPlaneDriveBehavior = go.GetComponent() ?? go.AddComponent(); toyPlaneDriveBehavior.Configure(componentInChildren); } } } public static bool SpawnItemsAroundPlayer(string itemId, float heightOffset, float radius, int count) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return false; } Vector3 val = ((Component)localPlayer).transform.position + Vector3.up * heightOffset; Vector3 forward = ((Component)localPlayer).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.forward; } else { ((Vector3)(ref forward)).Normalize(); } float num = 360f / (float)Mathf.Max(1, count); int num2 = 0; for (int i = 0; i < Mathf.Max(1, count); i++) { Vector3 val2 = Quaternion.AngleAxis(num * (float)i, Vector3.up) * forward * radius; Vector3 pos = SpawnHelper.ResolveInMapPosition(val + val2, 0.35f, i); GameObject val3 = TrySpawnGameObject(itemId, pos); if ((Object)(object)val3 != (Object)null) { ApplySpawnBehavior(val3, itemId); num2++; } } return num2 > 0; } public static bool SpawnChompBookNearPlayer() { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00ff: Unknown result type (might be due to invalid IL or missing references) //IL_0104: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { return false; } Vector3 forward = ((Component)localPlayer).transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.forward; } else { ((Vector3)(ref forward)).Normalize(); } Vector3 candidate = ((Component)localPlayer).transform.position + forward * 1.45f + Vector3.up * 0.35f; Vector3 pos = SpawnHelper.ResolveInMapPosition(candidate, 0.35f); GameObject val = TrySpawnGameObject("Valuable_Manor_Chomp_Book", pos); if ((Object)(object)val == (Object)null) { val = TrySpawnGameObject("Valuable_Wizard_Chomp_Book", pos); } if ((Object)(object)val == (Object)null) { ModLog.Warn("Chomp Book spawn failed (no prefab)"); return false; } Vector3 val2 = ((Component)localPlayer).transform.position - val.transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.01f) { val.transform.rotation = Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up); } ActivateChompBook(val); ModLog.Info("Chomp Book spawned (1 per trigger)"); return true; } public static bool SpawnItemsFromPlayer(string itemId, float durationSec, float periodSec, float height, float backOffset, float forcePower) { if (string.IsNullOrWhiteSpace(itemId)) { return false; } string key = "poop:" + itemId.Trim().ToLowerInvariant(); int num = Mathf.Max(1, EventContext.StackCount); float num2 = Mathf.Max(0.5f, durationSec) * (float)num; float num3 = Mathf.Max(0.05f, periodSec); if (_poopRemaining.TryGetValue(key, out var value) && value > 0.05f) { _poopRemaining[key] = value + num2; ModLog.Info($"Poop '{itemId}' extended +{num2:0.#}s ×{num} → {_poopRemaining[key]:0.#}s"); return true; } _poopRemaining[key] = num2; EffectTimerHost.Instance.RunRoutine(PeriodicEjectRoutine(key, itemId.Trim(), num3, height, backOffset, forcePower)); ModLog.Info($"Poop '{itemId}' started {num2:0.#}s (stacks={num}, period={num3:0.##}s)"); return true; } private static IEnumerator PeriodicEjectRoutine(string key, string itemOrGroup, float periodSec, float height, float backOffset, float forcePower) { float value; while (_poopRemaining.TryGetValue(key, out value) && value > 0.05f) { if (!RunGate.IsReadyForGameEvents()) { _poopRemaining.Remove(key); yield break; } PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null) { _poopRemaining.Remove(key); yield break; } Transform transform = ((Component)localPlayer).transform; Vector3 forward = transform.forward; forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.01f) { forward = Vector3.forward; } else { ((Vector3)(ref forward)).Normalize(); } string itemId = itemOrGroup; if (DropGroupCatalog.IsSimpleGroup(itemOrGroup)) { itemId = DropGroupCatalog.PickRandom(itemOrGroup) ?? itemOrGroup; } Vector3 pos = transform.position + Vector3.up * height - forward * backOffset; GameObject val = TrySpawnGameObject(itemId, pos); if ((Object)(object)val != (Object)null) { ApplySpawnBehavior(val, itemId); ActivateEjectedItem(val, itemId); MakeImpactDestructible(val); EffectTimerHost.Instance.RunRoutine(EjectForceBurst(val, -forward, forcePower)); } yield return (object)new WaitForSeconds(periodSec); if (_poopRemaining.TryGetValue(key, out var value2)) { value2 -= periodSec; if (value2 <= 0.05f) { _poopRemaining.Remove(key); } else { _poopRemaining[key] = value2; } } } _poopRemaining.Remove(key); } private static IEnumerator EjectForceBurst(GameObject go, Vector3 direction, float forcePower) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) yield return null; if ((Object)(object)go == (Object)null) { yield break; } Rigidbody rb = go.GetComponentInChildren(); if ((Object)(object)rb == (Object)null) { yield break; } rb.isKinematic = false; rb.WakeUp(); Vector3 val = direction; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.back; } else { ((Vector3)(ref val)).Normalize(); } float num = forcePower; if (forcePower >= 50f) { num = forcePower * 1.35f; } Vector3 push = val * num; for (int i = 0; i < 3; i++) { if ((Object)(object)go == (Object)null) { break; } if ((Object)(object)rb == (Object)null) { break; } rb.AddForce(push, (ForceMode)1); rb.AddTorque(Random.insideUnitSphere * 2f, (ForceMode)1); yield return (object)new WaitForSeconds(0.2f); } } private static void ActivateEjectedItem(GameObject go, string itemId) { if ((Object)(object)go == (Object)null) { return; } string text = (itemId ?? ((Object)go).name).ToLowerInvariant(); try { ItemToggle componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { EffectTimerHost.Instance.RunRoutine(DelayedToggle(componentInChildren)); } } catch { } if (!text.Contains("mine") && !text.Contains("grenade") && !text.Contains("nade")) { return; } try { ThrowableHelper.ArmWithFuse(go, 3f, immediate: true); } catch { } } private static IEnumerator DelayedToggle(ItemToggle toggle) { yield return null; if ((Object)(object)toggle == (Object)null) { yield break; } try { toggle.ToggleItem(true, -1); } catch { try { toggle.ToggleItem(true, -1); } catch { } } } private static void MakeImpactDestructible(GameObject go) { if ((Object)(object)go == (Object)null) { return; } try { PhysGrabObjectImpactDetector componentInChildren = go.GetComponentInChildren(true); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.destroyDisable = false; SetBoolField(componentInChildren, "isIndestructible", value: false); SetFloatField(componentInChildren, "indestructibleSpawnTimer", 0f); SetBoolField(componentInChildren, "destroyDisableTeleport", value: false); SetBoolField(componentInChildren, "indestructibleBreakEffects", value: false); } } catch (Exception ex) { ModLog.Debug("MakeImpactDestructible: " + ex.Message); } } private static void SetBoolField(object target, string name, bool value) { FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(target, value); } } private static void SetFloatField(object target, string name, float value) { FieldInfo field = target.GetType().GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { field.SetValue(target, value); } } public static bool SpawnPrimedActiveNade(string kind) { return SpawnPrimedActiveNades(kind, 1); } public static bool SpawnPrimedActiveNades(string kind, int count) { kind = (kind ?? "").Trim().ToLowerInvariant(); count = Mathf.Clamp(count, 1, 100); if (count <= 1) { return SpawnOnePrimedActiveNade(kind, 0); } EffectTimerHost.Instance.RunRoutine(SpawnPrimedActiveNadeWaveRoutine(kind, count)); return true; } private static IEnumerator SpawnPrimedActiveNadeWaveRoutine(string kind, int count) { int remaining = count; int seq = 0; int spawned = 0; PlayerAvatar subject = EventContext.SoloTarget(); while (remaining > 0) { if (!RunGate.IsReadyForGameEvents()) { yield break; } EventContext.SetTarget(subject); int batch = Mathf.Min(5, remaining); for (int i = 0; i < batch; i++) { if (SpawnOnePrimedActiveNade(kind, seq++)) { spawned++; } yield return null; } remaining -= batch; if (remaining > 0) { yield return (object)new WaitForSeconds(0.06f); } } ModLog.Info($"tok_active_nade '{kind}' wave-spawned x{spawned}"); } private static bool SpawnOnePrimedActiveNade(string kind, int scatterIndex, Vector3? overridePos = null) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Unknown result type (might be due to invalid IL or missing references) //IL_0114: Unknown result type (might be due to invalid IL or missing references) kind = (kind ?? "").Trim().ToLowerInvariant(); Vector3 val = (Vector3)(((??)overridePos) ?? SpawnHelper.GetGrenadeSpreadPosition(scatterIndex)); GameObject val2 = null; string label = null; switch (kind) { case "duck": val2 = SpawnActiveItemByTerms(val, ExpandActiveTerms("active_nade_duck", "Item_Rubber_Duck"), out label, armGrenade: false); if ((Object)(object)val2 != (Object)null) { val2.transform.position = val; ThrowableHelper.ApplyStrongBounce(val2, 30f); } break; case "stun": case "shock": case "expl": { string text = ((kind == "stun") ? "Item_Grenade_Stun" : ((!(kind == "shock")) ? "Item_Grenade_Explosive" : "Item_Grenade_Shockwave")); string fallback = text; string eventId = "active_nade_" + kind; val2 = SpawnActiveItemByTerms(val, ExpandActiveTerms(eventId, fallback), out label, armGrenade: true); if ((Object)(object)val2 != (Object)null) { val2.transform.position = val; ThrowableHelper.ArmWithFuse(val2, 3f, immediate: true); } break; } default: return false; } if ((Object)(object)val2 == (Object)null) { ModLog.Warn("tok_active_nade '" + kind + "' spawn failed"); return false; } ModLog.Info("tok_active_nade '" + kind + "' spawned (" + label + ")"); return true; } public static bool AllPlayersSpeak() { List list = PlayerTargeting.AlivePlayers(); PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer == (Object)null && list.Count == 0) { return false; } string text = RandomSpeakLines[Random.Range(0, RandomSpeakLines.Length)]; SpeakHelper.SpeakOnAllPlayers(text); ModLog.Info($"All players speak: {text} ({Mathf.Max(list.Count, 1)} voices)"); return true; } public static bool RandomPlayerSpeak() { return AllPlayersSpeak(); } public static bool SpawnNadesFromAllPlayers(string kind = "expl", int perPlayer = 1) { kind = (kind ?? "expl").Trim().ToLowerInvariant(); bool flag; switch (kind) { case "stun": case "shock": case "expl": case "duck": flag = true; break; default: flag = false; break; } if (!flag) { kind = "expl"; } perPlayer = Mathf.Clamp(perPlayer, 1, 5); List list = PlayerTargeting.AlivePlayers(); if (list.Count == 0) { return false; } EffectTimerHost.Instance.RunRoutine(SpawnNadesFromAllPlayersRoutine(kind, perPlayer, list)); return true; } private static IEnumerator SpawnNadesFromAllPlayersRoutine(string kind, int perPlayer, List players) { int spawned = 0; int seq = 0; foreach (PlayerAvatar player in players) { if ((Object)(object)player == (Object)null) { continue; } if (!RunGate.IsReadyForGameEvents()) { yield break; } for (int i = 0; i < perPlayer; i++) { Vector3 val = Random.insideUnitSphere * 0.45f; val.y = Mathf.Abs(val.y) + 1.1f; Vector3 value = ((Component)player).transform.position + val; if (SpawnOnePrimedActiveNade(kind, seq++, value)) { spawned++; } yield return null; } yield return (object)new WaitForSeconds(0.04f); } ModLog.Info($"nade_from_all_players '{kind}' spawned x{spawned} across {players.Count} players"); } private static string[] ExpandActiveTerms(string eventId, string fallback) { if (RepoEventMap.TryGetActiveItem(eventId, out string itemId)) { return RepoEventMap.ExpandItemSearchIds(itemId).Distinct().ToArray(); } return RepoEventMap.ExpandItemSearchIds(fallback).Distinct().ToArray(); } private static GameObject? SpawnActiveItemByTerms(Vector3 pos, string[] terms, out string? label, bool armGrenade) { //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) label = ((terms.Length != 0) ? terms[0] : null); foreach (string text in terms) { string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn(text, pos, Quaternion.identity, out spawnedLabel, 0, holdInPlace: true, armGrenade); if (!((Object)(object)val == (Object)null)) { label = spawnedLabel ?? text; return val; } } return null; } public static bool TeleportPlayerRandomPoint(bool startRoom, bool allPlayers) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Unknown result type (might be due to invalid IL or missing references) //IL_015c: Unknown result type (might be due to invalid IL or missing references) List list = GetPlayerTargets(allPlayers).ToList(); if (list.Count == 0) { return false; } bool result = false; foreach (PlayerAvatar player in list) { bool flag = ArenaHelper.IsContestMap(); Vector3? val = (flag ? ArenaHelper.GetContestTeleportPosition(((Component)player).transform.position, ((Component)player).transform.forward) : ((!startRoom) ? GetRandomTeleportPoint(startRoom: false, ((Component)player).transform.position) : (ArenaHelper.GetRandomSpawnPosition(((Component)player).transform.position) ?? GetRandomTeleportPoint(startRoom: true, ((Component)player).transform.position)))); if (!val.HasValue) { if (flag && (Object)(object)ArenaRace.instance != (Object)null && StumblePlayer(player)) { ModLog.Info("Scout Race teleport fallback: stumble '" + ((Object)player).name + "'"); result = true; } else { ModLog.Warn("Teleport skipped for '" + ((Object)player).name + "': no contest spawn / room point"); } } else if (TeleportPlayer(player, val.Value, !flag)) { result = true; if (flag) { Vector3 dest = val.Value; MainThreadDispatcher.EnqueueDelayed(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) TeleportPlayer(player, dest, snapLikeItem: false); }, 0.08f); MainThreadDispatcher.EnqueueDelayed(delegate { //IL_0007: Unknown result type (might be due to invalid IL or missing references) TeleportPlayer(player, dest, snapLikeItem: false); }, 0.22f); } } else if (flag && (Object)(object)ArenaRace.instance != (Object)null && StumblePlayer(player)) { ModLog.Info("Scout Race teleport failed — stumble '" + ((Object)player).name + "'"); result = true; } } return result; } public static bool TeleportShufflePlayers() { //IL_0086: Unknown result type (might be due to invalid IL or missing references) //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) List list = (from p in Object.FindObjectsOfType() where (Object)(object)p != (Object)null && ((Behaviour)p).isActiveAndEnabled select p).ToList(); if (list.Count < 2) { return false; } List list2 = list.Select((PlayerAvatar p) => ((Component)p).transform.position).ToList(); for (int num = list2.Count - 1; num > 0; num--) { int num2 = Random.Range(0, num + 1); List list3 = list2; int index = num; int index2 = num2; Vector3 value = list2[num2]; Vector3 value2 = list2[num]; list3[index] = value; list2[index2] = value2; } for (int num3 = 0; num3 < list.Count; num3++) { TeleportPlayer(list[num3], list2[num3]); } return true; } public static bool ResurrectPlayers(bool allPlayers, bool randomOnly) { List deadEventTargets = PlayerTargeting.GetDeadEventTargets(allPlayers); if (deadEventTargets.Count == 0) { ModLog.Info("ResurrectPlayers: all players are alive"); return false; } IEnumerable source = deadEventTargets; if (randomOnly) { int num = Mathf.Clamp(EventContext.StackCount, 1, deadEventTargets.Count); source = deadEventTargets.OrderBy((PlayerAvatar _) => Random.value).Take(num).ToList(); ModLog.Info($"ResurrectPlayers: random revive count={num} of {deadEventTargets.Count} dead"); } int num2 = 0; List list = source.ToList(); for (int num3 = 0; num3 < list.Count; num3++) { PlayerAvatar player = list[num3]; if (num3 == 0) { if (TryRevivePlayer(player)) { num2++; } continue; } float delaySeconds = (float)num3 * 0.25f; MainThreadDispatcher.EnqueueDelayed(delegate { try { TryRevivePlayer(player); } catch (Exception ex) { ModLog.Warn("Stagger revive failed: " + ex.Message); } }, delaySeconds); num2++; } ModLog.Info($"ResurrectPlayers: try to resurrect player — revived {num2}/{deadEventTargets.Count}"); return num2 > 0; } public static bool ResurrectClosestDeadPlayer() { //IL_0042: 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_0047: Unknown result type (might be due to invalid IL or missing references) List list = PlayerTargeting.DeadPlayers(); if (list.Count == 0) { ModLog.Info("ResurrectClosestDeadPlayer: all players are alive"); return false; } PlayerAvatar? localOrOwnedAvatar = GetLocalOrOwnedAvatar(); Vector3 anchor = ((localOrOwnedAvatar != null) ? ((Component)localOrOwnedAvatar).transform.position : ((Component)list[0]).transform.position); PlayerAvatar player = list.OrderBy((PlayerAvatar p) => Vector3.SqrMagnitude(((Component)p).transform.position - anchor)).First(); return TryRevivePlayer(player); } internal static List GetAllPlayerAvatars() { try { List list = SemiFunc.PlayerGetList(); if (list != null && list.Count > 0) { return list.Where((PlayerAvatar p) => (Object)(object)p != (Object)null).ToList(); } } catch (Exception ex) { ModLog.Debug("PlayerGetList failed: " + ex.Message); } return (from p in Object.FindObjectsOfType() where (Object)(object)p != (Object)null select p).ToList(); } private static PlayerAvatar? GetLocalOrOwnedAvatar() { PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer != (Object)null) { return localPlayer; } return ((IEnumerable)GetAllPlayerAvatars()).FirstOrDefault((Func)((PlayerAvatar p) => (Object)(object)p.photonView != (Object)null && p.photonView.IsMine)); } private static bool NeedsRevive(PlayerAvatar player) { return PlayerTargeting.IsPlayerDead(player); } private static bool IsPlayerDead(PlayerAvatar player) { return PlayerTargeting.IsPlayerDead(player); } public static bool ShufflePlayersHp() { List list = (from p in PlayerTargeting.AlivePlayers() where (Object)(object)p?.playerHealth != (Object)null select p).ToList(); if (list.Count < 2) { return false; } List list2 = list.Select((PlayerAvatar p) => p.playerHealth.health).ToList(); for (int num = list2.Count - 1; num > 0; num--) { int num2 = Random.Range(0, num + 1); List list3 = list2; int index = num; int index2 = num2; int value = list2[num2]; int value2 = list2[num]; list3[index] = value; list2[index2] = value2; } for (int num3 = 0; num3 < list.Count; num3++) { ApplyHealth(list[num3], list2[num3]); } return true; } public static bool AveragePlayersHp() { List list = (from p in PlayerTargeting.AlivePlayers() where (Object)(object)p?.playerHealth != (Object)null select p).ToList(); if (list.Count == 0) { return false; } int targetHealth = Mathf.RoundToInt((float)list.Average((PlayerAvatar p) => p.playerHealth.health)); foreach (PlayerAvatar item in list) { ApplyHealth(item, targetHealth); } return true; } public static bool ExplodeClosestItem(float rangeX, float rangeY, float damage) { ModLog.Info("Detonate Item was removed"); return false; } public static void ActivateSpawnedActiveItem(GameObject go) { if ((Object)(object)go == (Object)null) { return; } ApplySpawnBehavior(go, ((Object)go).name); try { ItemRubberDuck componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { ThrowableHelper.ApplyStrongBounce(go, 30f); } } catch { } try { ItemToggle componentInChildren2 = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren2 != (Object)null) { EffectTimerHost.Instance.RunRoutine(DelayedToggle(componentInChildren2)); } } catch { } try { ThrowableHelper.ArmWithFuse(go, 3f, immediate: true); } catch { } } public static bool ChangeExtractGoalPercent(float multiplier) { RoundDirector instance = RoundDirector.instance; if ((Object)(object)instance == (Object)null) { return false; } ExtractionPoint extractionPointCurrent = instance.extractionPointCurrent; if ((Object)(object)extractionPointCurrent == (Object)null) { return false; } int num = instance.extractionHaulGoal; if (num <= 0) { num = extractionPointCurrent.haulGoal; } if (num <= 0) { return false; } int num2 = Mathf.Max(1, Mathf.RoundToInt((float)num * multiplier)); extractionPointCurrent.HaulGoalSet(num2); ModLog.Info($"Loot goal changed: {num} -> {num2} (x{multiplier:0.##})"); return true; } public static bool ShakeCartItems(float minDelay, float maxDelay, float minForce, float maxForce) { PhysGrabCart[] allCarts = CartHelper.GetAllCarts(); if (allCarts.Length == 0) { return false; } CartHelper.ShakeItemsInAllCarts(minForce, maxForce, minDelay, maxDelay); return true; } public static bool TeleportCarts(bool toStart) { return CartHelper.TeleportAllCarts(toStart); } public static bool StunEnemies(float seconds) { List list = (from e in Object.FindObjectsOfType() where (Object)(object)e != (Object)null && ((Behaviour)e).isActiveAndEnabled select e).ToList(); if (list.Count == 0) { return false; } foreach (Enemy item in list) { TryStunEnemy(item, seconds); } return true; } public static bool ExplodeRandomPlayer() { List list = PlayerTargeting.AlivePlayers(); if (list.Count == 0) { return false; } list[Random.Range(0, list.Count)].PlayerDeath(-1); return true; } private static IEnumerator SpawnFromPlayerRoutine(string itemId, int count, float interval, float spread, float force, float angleDeg, bool armFuse) { PlayerAvatar player = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)player == (Object)null) { yield break; } for (int i = 0; i < Mathf.Max(1, count); i++) { Vector3 rearSpawnPosition = GetRearSpawnPosition(player, spread); GameObject val = TrySpawnGameObject(itemId, rearSpawnPosition); if ((Object)(object)val != (Object)null) { if (IsDiamondItem(itemId)) { ImpactLaunchHelper.PrepareForImpactBreak(val); ImpactLaunchHelper.LaunchBackwardBurst(val, player, force); } else { LaunchFromPlayer(val, player, force, angleDeg); } if (armFuse) { ThrowableHelper.ArmWithFuse(val); } } if (interval > 0f && i < count - 1) { yield return (object)new WaitForSeconds(interval); } } } private static IEnumerator PoopRandomNadesRoutine(int count, float interval, float spread, float force, float angleDeg) { for (int i = 0; i < Mathf.Max(1, count); i++) { string text = RandomNadeKinds[Random.Range(0, RandomNadeKinds.Length)]; PlayerAvatar localPlayer = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)localPlayer != (Object)null) { Vector3 rearSpawnPosition = GetRearSpawnPosition(localPlayer, spread); string[] array = ((text == "stun") ? new string[1] { "Item_Grenade_Stun" } : ((!(text == "shock")) ? new string[1] { "Item_Grenade_Explosive" } : new string[1] { "Item_Grenade_Shockwave" })); string[] array2 = array; string[] array3 = array2; foreach (string query in array3) { string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn(query, rearSpawnPosition, Quaternion.identity, out spawnedLabel); if ((Object)(object)val != (Object)null) { LaunchFromPlayer(val, localPlayer, force, angleDeg); ThrowableHelper.ArmWithFuse(val); break; } } } if (interval > 0f && i < count - 1) { yield return (object)new WaitForSeconds(interval); } } } private static IEnumerator PoopMinesRoutine(int count, float interval) { PlayerAvatar player = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)player == (Object)null) { yield break; } for (int i = 0; i < count; i++) { Vector3 rearSpawnPosition = GetRearSpawnPosition(player, 0.35f); string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn("Item_Mine_Explosive", rearSpawnPosition, Quaternion.identity, out spawnedLabel); if ((Object)(object)val != (Object)null) { LaunchFromPlayer(val, player, 6f, 30f); ThrowableHelper.ArmWithFuse(val); } if (i < count - 1) { yield return (object)new WaitForSeconds(interval); } } } private static IEnumerator PoopShockMinesRoutine(int count, float interval) { PlayerAvatar player = PlayerEffectHelper.GetLocalPlayer(); if ((Object)(object)player == (Object)null) { yield break; } for (int i = 0; i < count; i++) { Vector3 rearSpawnPosition = GetRearSpawnPosition(player, 0.35f); string spawnedLabel; GameObject val = ItemSpawnHelper.TrySpawn("Item_Mine_Shockwave", rearSpawnPosition, Quaternion.identity, out spawnedLabel); if ((Object)(object)val != (Object)null) { LaunchFromPlayer(val, player, 6f, 30f); ThrowableHelper.ArmWithFuse(val); } if (i < count - 1) { yield return (object)new WaitForSeconds(interval); } } } private static GameObject? TrySpawnGameObject(string itemId, Vector3 pos) { //IL_0025: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) string spawnedLabel; if (itemId.StartsWith("Valuable_", StringComparison.OrdinalIgnoreCase)) { if (!ValuableSpawnHelper.TrySpawn(itemId, pos, Quaternion.identity, out spawnedLabel, out GameObject spawnedObject)) { return null; } return spawnedObject; } return ItemSpawnHelper.TrySpawn(itemId, pos, Quaternion.identity, out spawnedLabel); } private static void ApplySpawnBehavior(GameObject go, string itemId) { string text = itemId.ToLowerInvariant(); if (text.Contains("frog")) { FrogHopBehavior frogHopBehavior = go.GetComponent() ?? go.AddComponent(); frogHopBehavior.Configure(); } else if (text.Contains("car") && !text.Contains("cart")) { ActivateToyCar(go, aggressive: false); } else if (text.Contains("chomp")) { ActivateChompBook(go); } } private static bool IsDiamondItem(string itemId) { return itemId.IndexOf("diamond", StringComparison.OrdinalIgnoreCase) >= 0; } private static void LaunchFromPlayer(GameObject go, PlayerAvatar player, float force, float angleDeg) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003b: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInChildren = go.GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); componentInChildren.velocity = Vector3.zero; componentInChildren.angularVelocity = Vector3.zero; componentInChildren.position = GetRearSpawnPosition(player, 0f); Vector3 val = -((Component)player).transform.forward; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = ((Component)player).transform.forward * -1f; } ((Vector3)(ref val)).Normalize(); Vector3 val2 = val + Vector3.up * Mathf.Tan(angleDeg * (MathF.PI / 180f)); Vector3 normalized = ((Vector3)(ref val2)).normalized; componentInChildren.AddForce(normalized * force, (ForceMode)2); componentInChildren.AddTorque(Random.insideUnitSphere * 8f, (ForceMode)1); } } private static Vector3 GetRearSpawnPosition(PlayerAvatar player, float spread) { //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_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) Vector3 forward = ((Component)player).transform.forward; Vector3 val = -((Vector3)(ref forward)).normalized; Vector3 val2 = ((Component)player).transform.right * Random.Range(0f - spread, spread); Vector3 candidate = ((Component)player).transform.position + val * 0.55f + val2 + Vector3.up * 0.75f; return SpawnHelper.ResolveInMapPosition(candidate, 0.35f); } private static IEnumerable GetPlayerTargets(bool massEffect) { return PlayerTargeting.GetAliveEventTargets(massEffect); } private static Vector3? GetRandomTeleportPoint(bool startRoom, Vector3 near) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) try { if (startRoom || ArenaHelper.IsContestMap()) { return ArenaHelper.GetRandomSpawnPosition(near); } List list = SemiFunc.LevelPointsGetAll(); if (list != null && list.Count > 0) { List playerRooms = SemiFunc.LevelPointsGetInPlayerRooms() ?? new List(); List list2 = list.Where((LevelPoint p) => (Object)(object)p != (Object)null && !playerRooms.Contains(p)).ToList(); if (list2.Count == 0) { list2 = list.Where((LevelPoint p) => (Object)(object)p != (Object)null).ToList(); } if (list2.Count > 0) { LevelPoint val = list2[Random.Range(0, list2.Count)]; return SpawnHelper.ResolveInMapPosition(((Component)val).transform.position, 0.35f); } } } catch (Exception ex) { ModLog.Debug("GetRandomTeleportPoint failed: " + ex.Message); } return ArenaHelper.GetRandomSpawnPosition(near) ?? SpawnHelper.TryGetNearbyLevelPointSpawn(Random.Range(0, 12)) ?? SpawnHelper.TryGetStartRoomLevelPoint(0); } private static bool IsLocalAvatar(PlayerAvatar player) { try { PlayerAvatar val = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val != (Object)null && val == player) { return true; } } catch { } try { return (Object)(object)player.photonView != (Object)null && player.photonView.IsMine; } catch { return false; } } private static bool StumblePlayer(PlayerAvatar player) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player?.tumble == (Object)null) { return false; } Vector3 val = -((Component)player).transform.forward * 14f + Vector3.up * 5f; try { player.tumble.TumbleForce(val); player.tumble.TumbleTorque(((Component)player.tumble).transform.right * 10f); return true; } catch (Exception ex) { ModLog.Debug("StumblePlayer failed: " + ex.Message); return false; } } private static bool TeleportPlayer(PlayerAvatar player, Vector3 position, bool snapLikeItem = true) { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_021d: 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_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_01e7: Unknown result type (might be due to invalid IL or missing references) //IL_01f0: Unknown result type (might be due to invalid IL or missing references) //IL_024f: Unknown result type (might be due to invalid IL or missing references) //IL_01a9: Unknown result type (might be due to invalid IL or missing references) //IL_01aa: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) //IL_014b: Unknown result type (might be due to invalid IL or missing references) //IL_0158: Unknown result type (might be due to invalid IL or missing references) //IL_0165: Unknown result type (might be due to invalid IL or missing references) //IL_0172: Unknown result type (might be due to invalid IL or missing references) //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_018c: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { return false; } Vector3 position2 = ((Component)player).transform.position; Vector3 val = (snapLikeItem ? SpawnHelper.SnapToFloor(position, 0.45f) : ArenaHelper.KeepOnSurface(position, position2)); Quaternion rotation = ((Component)player).transform.rotation; try { PhysGrabber physGrabber = player.physGrabber; if (physGrabber != null) { physGrabber.ReleaseObject(-1, 0.2f); } } catch { } TeleportRideablesWithPlayer(player, val, rotation); ((Component)player).transform.position = val; ((Component)player).transform.rotation = rotation; if ((Object)(object)player.playerAvatarVisuals != (Object)null) { ((Component)player.playerAvatarVisuals).transform.position = val; TrySetVector3(player.playerAvatarVisuals, "visualPosition", val); } if (IsLocalAvatar(player) && (Object)(object)PlayerController.instance != (Object)null) { PlayerController instance = PlayerController.instance; PlayerCollisionController collisionController = instance.CollisionController; if (collisionController != null) { collisionController.ResetFalling(); } instance.VelocityRelative = Vector3.zero; instance.Velocity = Vector3.zero; object? obj2 = ReadField(instance, "rb"); Rigidbody val2 = (Rigidbody)((obj2 is Rigidbody) ? obj2 : null); if (val2 != null) { val2.velocity = Vector3.zero; val2.angularVelocity = Vector3.zero; val2.position = val; val2.rotation = rotation; } TrySetVector3(instance, "clientPosition", val); TrySetVector3(instance, "clientPositionCurrent", val); TrySetQuaternion(instance, "clientRotation", rotation); TrySetQuaternion(instance, "clientRotationCurrent", rotation); TrySetVector3(instance, "spawnPosition", val); TrySetQuaternion(instance, "spawnRotation", rotation); TrySetVector3(instance, "rbVelocityRaw", Vector3.zero); TrySetFloat(instance, "MoveForceAmount", 0f); } try { player.Spawn(val, rotation); } catch (Exception ex) { ModLog.Debug("Player.Spawn failed: " + ex.Message); } try { PhotonView photonView = player.photonView; if (photonView != null) { photonView.RPC("SpawnRPC", (RpcTarget)0, new object[2] { val, rotation }); } } catch { } try { PlayerHealth playerHealth = player.playerHealth; if (playerHealth != null) { playerHealth.InvincibleSet(0.35f); } } catch { } float num = HorizontalDistance(position2, ((Component)player).transform.position); if (num < 3.5f && (Object)(object)ArenaRace.instance != (Object)null) { ModLog.Warn($"Scout Race teleport stayed near origin ({num:F1}m) — dest {val}"); return false; } return true; } private static float HorizontalDistance(Vector3 a, Vector3 b) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) float num = a.x - b.x; float num2 = a.z - b.z; return Mathf.Sqrt(num * num + num2 * num2); } private static void TeleportRideablesWithPlayer(PlayerAvatar player, Vector3 dest, Quaternion rot) { //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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) //IL_0110: Unknown result type (might be due to invalid IL or missing references) try { TeleportPhysObject(FindGrabbedPhysObject(player), dest, rot); } catch { } try { Transform parent = ((Component)player).transform.parent; if ((Object)(object)parent != (Object)null && (Object)(object)((Component)parent).GetComponent() == (Object)null) { TeleportTransformRigidbody(parent, dest, rot); PhysGrabCart componentInParent = ((Component)parent).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { CartHelper.TeleportCart(componentInParent, dest); } PhysGrabObject componentInParent2 = ((Component)parent).GetComponentInParent(); TeleportPhysObject(componentInParent2, dest, rot); } } catch { } try { Vector3 position = ((Component)player).transform.position; Component val = null; float num = 10.24f; Collider[] array = Physics.OverlapSphere(position, 3.2f); if (array == null) { return; } Collider[] array2 = array; foreach (Collider val2 in array2) { if (!((Object)(object)val2 == (Object)null) && LooksLikeRideable(((Component)val2).transform)) { float num2 = HorizontalDistance(((Component)val2).transform.position, position); if (!(num2 >= num)) { num = num2; val = (Component)(object)val2; } } } if (!((Object)(object)val == (Object)null)) { PhysGrabCart componentInParent3 = val.GetComponentInParent(); if ((Object)(object)componentInParent3 != (Object)null) { CartHelper.TeleportCart(componentInParent3, dest); return; } PhysGrabObject componentInParent4 = val.GetComponentInParent(); TeleportPhysObject(componentInParent4, dest, rot); TeleportTransformRigidbody(val.transform, dest, rot); } } catch (Exception ex) { ModLog.Debug("TeleportRideablesWithPlayer: " + ex.Message); } } private static PhysGrabObject? FindGrabbedPhysObject(PlayerAvatar player) { PhysGrabber physGrabber = player.physGrabber; if ((Object)(object)physGrabber == (Object)null) { return null; } string[] array = new string[4] { "grabbedPhysGrabObject", "grabbedObject", "physGrabObject", "GrabbedPhysGrabObject" }; foreach (string fieldName in array) { object? obj = ReadField(physGrabber, fieldName); PhysGrabObject val = (PhysGrabObject)((obj is PhysGrabObject) ? obj : null); if (val != null && (Object)(object)val != (Object)null) { return val; } } try { return ((Component)physGrabber).GetComponentInChildren(true); } catch { return null; } } private static void TeleportPhysObject(PhysGrabObject? phys, Vector3 dest, Quaternion rot) { //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)phys == (Object)null) { return; } try { phys.Teleport(dest, rot); } catch { TeleportTransformRigidbody(((Component)phys).transform, dest, rot); } } private static void TeleportTransformRigidbody(Transform? tr, Vector3 dest, Quaternion rot) { //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)tr == (Object)null)) { Rigidbody componentInParent = ((Component)tr).GetComponentInParent(); if ((Object)(object)componentInParent != (Object)null) { componentInParent.velocity = Vector3.zero; componentInParent.angularVelocity = Vector3.zero; componentInParent.position = dest; componentInParent.rotation = rot; } Transform val = (Transform)(((Object)(object)componentInParent != (Object)null) ? ((object)((Component)componentInParent).transform) : ((object)tr)); val.position = dest; val.rotation = rot; } } private static bool LooksLikeRideable(Transform tr) { Transform val = tr; for (int i = 0; i < 6; i++) { if (!((Object)(object)val != (Object)null)) { break; } if ((Object)(object)((Component)val).GetComponent() != (Object)null) { return false; } string text = ((Object)val).name.ToLowerInvariant(); if (text.Contains("vehicle") || text.Contains("scooter") || text.Contains("cart") || text.Contains("buggy") || text.Contains("truck") || text.Contains("semiscooter")) { return true; } val = val.parent; } return false; } private static bool TryRevivePlayer(PlayerAvatar player) { if ((Object)(object)player == (Object)null) { return false; } if (!NeedsRevive(player)) { return false; } if (SemiFunc.IsMultiplayer() && !SemiFunc.IsMasterClientOrSingleplayer()) { ModLog.Warn("Revive skipped: not lobby host"); return false; } if ((Object)(object)player.playerDeathHead == (Object)null) { ModLog.Warn("Revive failed for '" + ((Object)player).name + "': missing death head"); return false; } try { ModLog.Info("Reviving '" + ((Object)player).name + "' via PlayerAvatar.Revive"); player.Revive(false); } catch (Exception ex) { ModLog.Warn("Revive threw: " + ex.Message); return false; } bool flag = !player.isDisabled && !NeedsRevive(player); if (!flag) { flag = !player.isDisabled; } ModLog.Info($"Revive result for '{((Object)player).name}': disabled={player.isDisabled} ok={flag}"); if (!flag) { return !player.isDisabled; } return true; } private static void ApplyHealth(PlayerAvatar player, int targetHealth) { //IL_0056: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)player?.playerHealth == (Object)null)) { int maxHealth = player.playerHealth.maxHealth; int num = Mathf.Clamp(targetHealth, 1, maxHealth); int num2 = num - player.playerHealth.health; if (num2 > 0) { player.playerHealth.HealOther(num2, true); } else if (num2 < 0) { player.playerHealth.HurtOther(-num2, Vector3.zero, false, -1, false); } } } private static void TryStunEnemy(Enemy enemy, float seconds) { if (TryInvoke(enemy, "Stun", seconds) || TryInvoke(enemy, "EnemyStun", seconds) || TryInvoke(enemy, "Freeze", seconds) || TryInvoke(enemy, "Stunned", seconds)) { return; } TrySetBool(enemy, "stunned", value: true); TrySetBool(enemy, "frozen", value: true); TrySetFloat(enemy, "stunTimer", seconds); TrySetFloat(enemy, "freezeTimer", seconds); EffectTimerHost.Instance.RunForSeconds($"stun_{((Object)enemy).GetInstanceID()}", seconds, delegate { }, delegate { if (!((Object)(object)enemy == (Object)null)) { TrySetBool(enemy, "stunned", value: false); TrySetBool(enemy, "frozen", value: false); } }); } private static bool TryInvoke(object target, string methodName, float arg) { try { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return false; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float)) { method.Invoke(target, new object[1] { arg }); return true; } } catch (Exception ex) { ModLog.Debug("Invoke " + methodName + " failed: " + ex.Message); } return false; } private static bool TryInvoke(object target, string methodName) { try { MethodInfo method = target.GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null || method.GetParameters().Length != 0) { return false; } method.Invoke(target, null); return true; } catch { return false; } } private static bool TryReadBool(object target, string fieldName) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); return field != null && field.FieldType == typeof(bool) && (bool)field.GetValue(target); } catch { return false; } } private static void TrySetFloat(object target, string fieldName, float value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(float)) { field.SetValue(target, value); } } catch { } } private static void TrySetBool(object target, string fieldName, bool value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(target, value); } } catch { } } private static void TrySetVector3(object target, string fieldName, Vector3 value) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(Vector3)) { field.SetValue(target, value); } } catch { } } private static void TrySetQuaternion(object target, string fieldName, Quaternion value) { //IL_0031: Unknown result type (might be due to invalid IL or missing references) try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(Quaternion)) { field.SetValue(target, value); } } catch { } } private static object? ReadField(object target, string fieldName) { try { return target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(target); } catch { return null; } } } internal static class StreamEventRunner { public static CommandResult Execute(string eventId, string user, int count = 1, PlayerAvatar? targetPlayer = null, string? namedPlayer = null) { eventId = Normalize(eventId); if (string.IsNullOrEmpty(eventId)) { return CommandResult.Fail("empty_effect"); } if (SpawnBlocklist.IsBlockedEventId(eventId)) { ModLog.Warn("Event temporarily disabled: " + eventId); return CommandResult.Fail("spawn_disabled_temp"); } count = Math.Max(1, Math.Min(count, 100)); if (!MainThreadDispatcher.IsReady) { return CommandResult.Fail("game_not_ready"); } if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (!EventCommandCatalog.TryGetCommandLine(eventId, out string commandLine)) { return CommandResult.Fail("unknown_event:" + eventId); } PlayerAvatar val = PlayerTargeting.FindAliveByName(namedPlayer); if (RequiresNamedPlayer(eventId) && string.IsNullOrWhiteSpace(namedPlayer)) { List list = PlayerTargeting.AlivePlayers(); if (list.Count != 1) { ModLog.Warn("Named kill '" + eventId + "' missing targetPlayer"); return CommandResult.Fail("named_player_required"); } val = list[0]; namedPlayer = PlayerTargeting.GetPlayerName(val); ModLog.Info("Named kill: only one player left — auto targeting '" + namedPlayer + "'"); } bool flag = !SemiFunc.IsMasterClientOrSingleplayer() && SemiFunc.IsMultiplayer(); if (!string.IsNullOrWhiteSpace(namedPlayer) && (Object)(object)val == (Object)null && RequiresNamedPlayer(eventId) && !flag) { ModLog.Warn("Named kill: no alive player matching '" + namedPlayer + "' | roster: " + PlayerTargeting.FormatAliveRoster()); return CommandResult.Fail("player_not_found"); } if ((Object)(object)val != (Object)null && IsNamedKillEvent(eventId)) { commandLine = "explode_player"; } PlayerAvatar val2 = val ?? targetPlayer ?? SemiFunc.PlayerAvatarLocal(); bool flag2 = HostEventPolicy.MustRunFromHost(eventId) || RequiresNamedPlayer(eventId) || ((Object)(object)val != (Object)null && IsNamedKillEvent(eventId)); if (flag && flag2) { int playerViewId = 0; try { playerViewId = (((Object)(object)val2?.photonView != (Object)null) ? val2.photonView.ViewID : 0); } catch { } return EffectRelay.RelayKnownEvent(eventId, user, count, playerViewId, namedPlayer); } return ExecuteLocal(eventId, commandLine, user, count, val2); } private static bool RequiresNamedPlayer(string eventId) { switch (eventId) { case "solo_debuff_kill_named": case "all_debuff_kill_named": case "explode_named_player": return true; default: return false; } } private static bool IsNamedKillEvent(string eventId) { switch (eventId) { case "solo_debuff_kill_named": case "all_debuff_kill_named": case "solo_debuff_kill": case "all_debuff_kill_rand": case "explode_named_player": case "explode_player": return true; default: return false; } } public static CommandResult ExecuteLocal(string eventId, string commandLine, string user, int count, PlayerAvatar? targetPlayer = null) { eventId = Normalize(eventId); count = Math.Max(1, Math.Min(count, 100)); if (!RunGate.IsReadyForGameEvents()) { return CommandResult.Fail("game_not_ready"); } if (string.IsNullOrWhiteSpace(commandLine) && !EventCommandCatalog.TryGetCommandLine(eventId, out commandLine)) { return CommandResult.Fail("unknown_event:" + eventId); } EventContext.SetTarget(targetPlayer ?? SemiFunc.PlayerAvatarLocal()); EventContext.SetStackCount(count); try { bool flag = false; if (IsActionStaggerCommand(commandLine) && count > 1) { for (int i = 0; i < count; i++) { float num = (float)i * 0.2f; string line = commandLine; if (num <= 0.001f) { if (EffectCommandExecutor.TryExecuteLine(line)) { flag = true; } continue; } PlayerAvatar subject = EventContext.SoloTarget(); MainThreadDispatcher.EnqueueDelayed(delegate { EventContext.SetTarget(subject); try { EffectCommandExecutor.TryExecuteLine(line); } catch (Exception ex) { ModLog.Warn("Stagger action failed: " + ex.Message); } }, num); flag = true; } } else { int num2 = (IsDurationStackCommand(commandLine) ? 1 : ((!NeedsCountLoop(commandLine)) ? 1 : count)); for (int num3 = 0; num3 < num2; num3++) { if (EffectCommandExecutor.TryExecuteLine(commandLine)) { flag = true; } } } if (!flag) { if (eventId.Contains("resurrect", StringComparison.Ordinal)) { ModLog.Info("Event '" + eventId + "' — no dead players to revive"); GameNotifier.AnnounceEvent(user, eventId); return CommandResult.Fail("no_dead_players"); } ModLog.Warn("Event '" + eventId + "' command failed: " + commandLine); GameNotifier.AnnounceEvent(user, eventId); return CommandResult.Fail("effect_failed:" + eventId); } ModLog.Info($"Event '{eventId}' applied for @{user} (count={count})"); GameNotifier.AnnounceEvent(user, eventId); return CommandResult.Ok("effect_applied", eventId); } finally { EventContext.Clear(); } } private static bool NeedsCountLoop(string commandLine) { switch (CommandHead(commandLine)) { case "spawn_item": case "spawn_enemy": case "spawn_active_item": case "spawn_simple_item_group": return true; default: return false; } } private static bool IsActionStaggerCommand(string commandLine) { switch (CommandHead(commandLine)) { case "heal_player_amount": case "hurt_player_amount": case "drop_inventory": case "explode_player": case "slap_all_room": case "explode_random_player": case "force_crouch": case "knockdown_player": return true; default: return false; } } private static bool IsDurationStackCommand(string commandLine) { switch (CommandHead(commandLine)) { case "infinite_player_stamina": case "spawn_items_from_player": case "shuffle_player_movement": case "disable_player_movement": case "set_player_jump_power": case "set_player_speed_mult": case "disable_player_aiming": case "invincible_player": case "drain_player_stamina": case "enable_anti_gravity": case "set_player_gravity": case "disable_input": case "hold_input": case "knockdown_player": case "force_rb": return true; default: return false; } } private static string CommandHead(string commandLine) { string text = (commandLine ?? "").Trim(); int num = text.IndexOf(' '); return ((num > 0) ? text.Substring(0, num) : text).ToLowerInvariant(); } private static string Normalize(string value) { value = (value ?? "").Trim().ToLowerInvariant().Replace(' ', '_'); while (value.StartsWith("repo_", StringComparison.Ordinal)) { value = value.Substring(5); } return value; } } internal static class ThrowableHelper { public const float DefaultSoloGrenadeFuseSeconds = 3f; public static Vector3 GetThrowOrigin() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) Vector3 playerPosition = SpawnHelper.GetPlayerPosition(); Vector3 playerForward = SpawnHelper.GetPlayerForward(); return playerPosition + ((Vector3)(ref playerForward)).normalized * 1.2f + Vector3.up * 1.35f; } public static void ThrowForward(GameObject go, float speed) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInChildren = go.GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); Vector3 playerForward = SpawnHelper.GetPlayerForward(); playerForward.y += 0.15f; componentInChildren.velocity = ((Vector3)(ref playerForward)).normalized * speed; componentInChildren.angularVelocity = Random.insideUnitSphere * 6f; } } public static void PrepareDormantGrenade(GameObject go) { ItemGrenade[] componentsInChildren = go.GetComponentsInChildren(true); foreach (ItemGrenade val in componentsInChildren) { ((Behaviour)val).enabled = false; val.isActive = false; val.isSpawnedGrenade = false; val.grenadeTimer = 0f; } ItemToggle[] componentsInChildren2 = go.GetComponentsInChildren(true); foreach (ItemToggle val2 in componentsInChildren2) { ((Behaviour)val2).enabled = false; } } public static void PreparePickupGrenade(GameObject go) { ItemGrenade[] componentsInChildren = go.GetComponentsInChildren(true); foreach (ItemGrenade val in componentsInChildren) { ((Behaviour)val).enabled = true; val.isActive = false; val.isSpawnedGrenade = true; val.grenadeTimer = 0f; } ItemToggle[] componentsInChildren2 = go.GetComponentsInChildren(true); foreach (ItemToggle val2 in componentsInChildren2) { ((Behaviour)val2).enabled = true; } } public static void ArmWithFuse(GameObject go, float fuseSeconds = -1f, bool immediate = false) { FusedGrenadeActivator component = go.GetComponent(); if ((Object)(object)component != (Object)null) { Object.Destroy((Object)(object)component); } if (!immediate) { PrepareDormantGrenade(go); } EffectTimerHost.Instance.RunRoutine(ArmSpawnedGrenadeRoutine(go, fuseSeconds, immediate)); } private static IEnumerator ArmSpawnedGrenadeRoutine(GameObject go, float fuseSeconds, bool immediate) { if ((Object)(object)go == (Object)null) { yield break; } yield return null; yield return null; ItemGrenade componentInChildren = go.GetComponentInChildren(true); ItemToggle componentInChildren2 = go.GetComponentInChildren(true); PhysGrabObject physGrab = go.GetComponentInChildren(true); Rigidbody rb = go.GetComponentInChildren(true); float fuse = ((fuseSeconds > 0f) ? fuseSeconds : 3f); if (!immediate) { Vector3 position = SpawnHelper.SnapToFloor(go.transform.position, 0.35f); go.transform.position = position; } ItemPostSpawnHelper.ReleaseHold(go); if ((Object)(object)rb != (Object)null) { rb.isKinematic = false; rb.WakeUp(); rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } if ((Object)(object)componentInChildren != (Object)null) { ((Behaviour)componentInChildren).enabled = true; componentInChildren.isSpawnedGrenade = true; } if ((Object)(object)componentInChildren2 != (Object)null) { ((Behaviour)componentInChildren2).enabled = true; } EnsurePhysGrabSpawned(physGrab); float deadline = Time.time + 1.5f; while (Time.time < deadline && (Object)(object)go != (Object)null) { EnsurePhysGrabSpawned(physGrab); if ((Object)(object)physGrab == (Object)null || physGrab.spawned) { break; } if ((Object)(object)rb != (Object)null) { rb.isKinematic = false; rb.WakeUp(); } yield return null; } yield return null; if ((Object)(object)go != (Object)null && TryActivateGrenadeComponents(go, fuse)) { ModLog.Debug($"Grenade armed at {go.transform.position}"); } else if ((Object)(object)go != (Object)null) { ModLog.Warn("Grenade arm fallback: ForceDetonateGrenade"); ForceDetonateGrenade(go); } } private static bool TryActivateGrenadeComponents(GameObject go, float fuseSeconds) { ItemGrenade componentInChildren = go.GetComponentInChildren(true); ItemToggle componentInChildren2 = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return ArmGrenade(go); } ((Behaviour)componentInChildren).enabled = true; componentInChildren.isSpawnedGrenade = true; if ((Object)(object)componentInChildren2 != (Object)null) { ((Behaviour)componentInChildren2).enabled = true; float num = ((componentInChildren.tickTime > 0.05f) ? componentInChildren.tickTime : 1f); int num2 = Mathf.Max(1, Mathf.RoundToInt(fuseSeconds / num)); componentInChildren.tickTime = num; try { componentInChildren2.ToggleItem(true, num2); return true; } catch (Exception ex) { ModLog.Debug($"Grenade ToggleItem({num2}): {ex.Message}"); } try { componentInChildren2.ToggleItem(true, -1); return true; } catch (Exception ex2) { ModLog.Debug("Grenade ToggleItem(-1): " + ex2.Message); } } componentInChildren.isActive = true; try { componentInChildren.TickStart(); return true; } catch (Exception ex3) { ModLog.Debug("Grenade TickStart: " + ex3.Message); } return ArmGrenade(go); } private static void EnsurePhysGrabSpawned(PhysGrabObject? physGrab) { if ((Object)(object)physGrab == (Object)null) { return; } try { FieldInfo field = typeof(PhysGrabObject).GetField("spawned", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field != null && field.FieldType == typeof(bool)) { field.SetValue(physGrab, true); } } catch { } } public static void ScatterOnGround(GameObject go) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_005d: 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_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Unknown result type (might be due to invalid IL or missing references) //IL_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) Rigidbody componentInChildren = go.GetComponentInChildren(); if (!((Object)(object)componentInChildren == (Object)null)) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); Vector3 val = go.transform.position - SpawnHelper.GetPlayerBodyPosition(); val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = SpawnHelper.GetPlayerBodyForward(); } val = ((Vector3)(ref val)).normalized; componentInChildren.velocity = val * Random.Range(1.8f, 3.2f) + Vector3.up * 0.35f; componentInChildren.angularVelocity = Random.insideUnitSphere * 2f; } } public static float ResolveGrenadeFuseSeconds(GameObject go) { ItemGrenade componentInChildren = go.GetComponentInChildren(true); float num = (((Object)(object)componentInChildren != (Object)null && componentInChildren.tickTime > 0.05f) ? componentInChildren.tickTime : 1f); string text = (((Object)go).name + " " + ((componentInChildren != null) ? ((Object)componentInChildren).name : null)).ToLowerInvariant(); if (text.Contains("stun")) { return 5f * num; } if (text.Contains("shock")) { return 5f * num; } if (text.Contains("expl")) { return 5f * num; } if (text.Contains("mine")) { return 2.5f * num; } return 5f * num; } public static void ArmAndDetonateInPlace(GameObject go) { ArmWithFuse(go); } public static void ForceDetonateGrenade(GameObject go) { ItemGrenade componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.grenadeTimer = 0f; try { componentInChildren.TickEnd(); } catch { } try { UnityEvent onDetonate = componentInChildren.onDetonate; if (onDetonate != null) { onDetonate.Invoke(); } } catch { } } MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren(true); foreach (MonoBehaviour comp in componentsInChildren) { if (TryInvoke(comp, "Explode") || TryInvoke(comp, "Detonate") || TryInvoke(comp, "TriggerExplosion") || TryInvoke(comp, "FuseEnd") || TryInvoke(comp, "OnExplode") || TryInvoke(comp, "GrenadeExplode") || TryInvoke(comp, "Explosion")) { return; } TrySetFloatField(comp, "fuseTimer", 0f); TrySetFloatField(comp, "fuse", 0f); TrySetFloatField(comp, "timer", 0f); TrySetFloatField(comp, "explodeTimer", 0f); } ArmGrenade(go); } private static bool TrySetFloatField(MonoBehaviour comp, string fieldName, float value) { try { FieldInfo field = ((object)comp).GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != typeof(float)) { return false; } field.SetValue(comp, value); return true; } catch { return false; } } public static void ArmGrenadeDelayed(GameObject go, float throwSpeed) { DelayedGrenadeArm delayedGrenadeArm = go.GetComponent() ?? go.AddComponent(); delayedGrenadeArm.Configure(throwSpeed); } public static bool ArmGrenade(GameObject go) { bool result = false; MonoBehaviour[] componentsInChildren = go.GetComponentsInChildren(true); foreach (MonoBehaviour val in componentsInChildren) { Type type = ((object)val).GetType(); if (TryInvoke(val, "ToggleItem") || TryInvoke(val, "Toggle") || TryInvoke(val, "Arm") || TryInvoke(val, "StartFuse") || TryInvoke(val, "FuseStart") || TryInvoke(val, "OnActivate") || TryInvoke(val, "Spawned") || TryInvoke(val, "ActivateGrenade")) { result = true; } if (TrySetBoolField(val, "armed") || TrySetBoolField(val, "activated") || TrySetBoolField(val, "fused") || TrySetBoolField(val, "lit") || TrySetBoolField(val, "thrown") || TrySetBoolField(val, "toggleState")) { result = true; } } return result; } public static void ApplyStrongBounce(GameObject go, float durationSeconds) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00f2: Expected O, but got Unknown Rigidbody componentInChildren = go.GetComponentInChildren(); if ((Object)(object)componentInChildren != (Object)null) { componentInChildren.isKinematic = false; componentInChildren.WakeUp(); componentInChildren.mass = Mathf.Max(componentInChildren.mass, 0.75f); componentInChildren.drag = 0.05f; componentInChildren.angularDrag = 0.05f; Vector3 playerForward = SpawnHelper.GetPlayerForward(); playerForward.y = 0.55f; componentInChildren.velocity = ((Vector3)(ref playerForward)).normalized * Random.Range(16f, 22f); componentInChildren.angularVelocity = Random.insideUnitSphere * 18f; Collider[] componentsInChildren = go.GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if ((Object)(object)val.material == (Object)null) { val.material = new PhysicMaterial("TokControlBounce") { bounciness = 0.95f, bounceCombine = (PhysicMaterialCombine)3, dynamicFriction = 0.15f, staticFriction = 0.15f }; } else { val.material.bounciness = Mathf.Max(val.material.bounciness, 0.95f); val.material.bounceCombine = (PhysicMaterialCombine)3; } } } RubberDuckBounce rubberDuckBounce = go.GetComponent() ?? go.AddComponent(); rubberDuckBounce.Configure(durationSeconds); } private static bool TryInvoke(MonoBehaviour comp, string methodName) { try { MethodInfo method = ((object)comp).GetType().GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (method == null) { return false; } ParameterInfo[] parameters = method.GetParameters(); if (parameters.Length == 0) { method.Invoke(comp, null); return true; } if (parameters.Length == 1 && parameters[0].ParameterType == typeof(bool)) { method.Invoke(comp, new object[1] { true }); return true; } } catch (Exception ex) { ModLog.Debug("Arm invoke " + methodName + " failed: " + ex.Message); } return false; } private static bool TrySetBoolField(MonoBehaviour comp, string fieldName) { try { FieldInfo field = ((object)comp).GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (field == null || field.FieldType != typeof(bool)) { return false; } field.SetValue(comp, true); return true; } catch { return false; } } } internal sealed class RubberDuckBounce : MonoBehaviour { private enum Phase { Bounce, Done } private const float TargetHitChance = 0.55f; private const float ValuableSearchRadius = 28f; private float _duration = 20f; private float _elapsed; private Rigidbody? _rb; private float _nextImpulse; private Phase _phase; public void Configure(float durationSeconds) { _duration = Mathf.Max(1f, durationSeconds); _rb = ((Component)this).GetComponentInChildren(); _nextImpulse = 0.2f; _phase = Phase.Bounce; _elapsed = 0f; } private void FixedUpdate() { //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Unknown result type (might be due to invalid IL or missing references) //IL_00e5: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rb == (Object)null || _phase == Phase.Done) { return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { _phase = Phase.Done; StopBouncePhysics(); return; } _nextImpulse -= Time.fixedDeltaTime; if (!(_nextImpulse > 0f)) { _nextImpulse = Random.Range(0.45f, 0.95f); if (!(Random.value < 0.55f) || !TryLaunchAtRandomTarget()) { Vector3 onUnitSphere = Random.onUnitSphere; onUnitSphere.y = Mathf.Abs(onUnitSphere.y) + 0.45f; _rb.AddForce(((Vector3)(ref onUnitSphere)).normalized * Random.Range(9f, 14f), (ForceMode)1); _rb.AddTorque(Random.insideUnitSphere * 8f, (ForceMode)1); } } } private bool TryLaunchAtRandomTarget() { //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_010d: Unknown result type (might be due to invalid IL or missing references) //IL_010e: 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_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00d9: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0149: Unknown result type (might be due to invalid IL or missing references) //IL_015d: Unknown result type (might be due to invalid IL or missing references) //IL_016d: Unknown result type (might be due to invalid IL or missing references) //IL_0177: Unknown result type (might be due to invalid IL or missing references) //IL_0124: Unknown result type (might be due to invalid IL or missing references) //IL_0129: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rb == (Object)null) { return false; } Vector3 position = ((Component)this).transform.position; List list = new List(16); foreach (PlayerAvatar item in PlayerTargeting.AlivePlayers()) { if (!((Object)(object)item == (Object)null)) { list.Add(((Component)item).transform.position + Vector3.up * 1.1f); } } ValuableObject[] array = Object.FindObjectsOfType(); foreach (ValuableObject val in array) { if (!((Object)(object)val == (Object)null)) { Vector3 position2 = ((Component)val).transform.position; Vector3 val2 = position2 - position; if (!(((Vector3)(ref val2)).sqrMagnitude > 784f)) { list.Add(position2 + Vector3.up * 0.35f); } } } if (list.Count == 0) { return false; } Vector3 val3 = list[Random.Range(0, list.Count)]; Vector3 val4 = val3 - position; if (((Vector3)(ref val4)).sqrMagnitude < 0.01f) { val4 = SpawnHelper.GetPlayerForward(); } val4.y = Mathf.Max(val4.y, 0.35f); _rb.velocity = ((Vector3)(ref val4)).normalized * Random.Range(14f, 21f); _rb.angularVelocity = Random.insideUnitSphere * 14f; return true; } private void StopBouncePhysics() { DrainDuckBattery(); RestoreNormalPhysics(); Object.Destroy((Object)(object)this); } private void DrainDuckBattery() { ItemBattery componentInChildren = ((Component)this).GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null) { return; } try { componentInChildren.BatteryFullPercentChange(0, true); } catch { try { componentInChildren.SetBatteryLife(0); } catch { } } ItemRubberDuck[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (ItemRubberDuck obj3 in componentsInChildren) { try { typeof(ItemRubberDuck).GetField("playDuckLoop", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.SetValue(obj3, false); } catch { } } } private void RestoreNormalPhysics() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0025: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_rb == (Object)null) { return; } _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; _rb.isKinematic = false; _rb.useGravity = true; _rb.drag = 0f; _rb.angularDrag = 0.05f; _rb.WakeUp(); Collider[] componentsInChildren = ((Component)this).GetComponentsInChildren(true); foreach (Collider val in componentsInChildren) { if (!((Object)(object)val.material == (Object)null)) { val.material.bounciness = 0f; val.material.bounceCombine = (PhysicMaterialCombine)0; val.material.dynamicFriction = 0.6f; val.material.staticFriction = 0.6f; } } ItemPostSpawnHelper.ReleaseHold(((Component)this).gameObject); ItemPostSpawnHelper.EnsureUsablePublic(((Component)this).gameObject); } } internal sealed class DelayedGrenadeArm : MonoBehaviour { private float _throwSpeed = 9f; private int _frames; public void Configure(float throwSpeed) { _throwSpeed = throwSpeed; _frames = 0; } private void Update() { if (++_frames >= 2) { ThrowableHelper.ThrowForward(((Component)this).gameObject, _throwSpeed); if (!ThrowableHelper.ArmGrenade(((Component)this).gameObject)) { ThrowableHelper.ArmGrenade(((Component)this).gameObject); } Object.Destroy((Object)(object)this); } } } internal sealed class FusedGrenadeActivator : MonoBehaviour { public const float DefaultFuseSeconds = -1f; private const float SpawnSettleSeconds = 0.12f; private const float MaxSpawnWaitSeconds = 2f; private float _fuseSeconds = -1f; private bool _immediate; public void Configure(float fuseSeconds, bool immediate = false) { _fuseSeconds = fuseSeconds; _immediate = immediate; } private void Start() { ((MonoBehaviour)this).StartCoroutine(FuseRoutine()); } private IEnumerator FuseRoutine() { yield return null; ItemGrenade grenade = ((Component)this).GetComponentInChildren(true); ItemToggle toggle = ((Component)this).GetComponentInChildren(true); PhysGrabObject physGrab = ((Component)this).GetComponentInChildren(true); Rigidbody rb = ((Component)this).GetComponentInChildren(true); float fuseSeconds = ((_fuseSeconds > 0f) ? _fuseSeconds : 3f); if (!_immediate) { Vector3 position = SpawnHelper.SnapToFloor(((Component)this).transform.position, 0.35f); ((Component)this).transform.position = position; } ItemPostSpawnHelper.HoldInPlace(((Component)this).gameObject); yield return (object)new WaitForSeconds(_immediate ? 0.02f : 0.12f); ItemPostSpawnHelper.ReleaseHold(((Component)this).gameObject); if ((Object)(object)rb != (Object)null) { rb.isKinematic = false; rb.WakeUp(); rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } float waitDeadline = Time.time + 2f; while (Time.time < waitDeadline && (Object)(object)((Component)this).gameObject != (Object)null && (!((Object)(object)physGrab != (Object)null) || !physGrab.spawned)) { if ((Object)(object)rb != (Object)null) { rb.isKinematic = false; rb.WakeUp(); } yield return null; } if ((Object)(object)rb != (Object)null) { rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } if ((Object)(object)toggle != (Object)null && (Object)(object)grenade != (Object)null) { ((Behaviour)grenade).enabled = true; ((Behaviour)toggle).enabled = true; grenade.isSpawnedGrenade = true; float num = ((grenade.tickTime > 0.05f) ? grenade.tickTime : 1f); int num2 = Mathf.Max(1, Mathf.RoundToInt(fuseSeconds / num)); grenade.tickTime = num; try { toggle.ToggleItem(true, num2); } catch (Exception ex) { ModLog.Debug("Grenade ToggleItem: " + ex.Message); try { toggle.ToggleItem(true, -1); } catch { } } Object.Destroy((Object)(object)this); } else { yield return (object)new WaitForSeconds(fuseSeconds); if ((Object)(object)((Component)this).gameObject != (Object)null) { ThrowableHelper.ForceDetonateGrenade(((Component)this).gameObject); } Object.Destroy((Object)(object)this); } } } internal sealed class ToyCarDriveBehavior : MonoBehaviour { private const float DriveForce = 34f; private const float BoostForce = 55f; private const float AggressiveForce = 62f; private const float MinSpeed = 6f; private const float UnstickImpulse = 16f; private const float PatrolRetargetDistance = 1.4f; private ValuableCar? _car; private Rigidbody? _rb; private Transform? _playerTarget; private Vector3 _patrolTarget; private bool _aggressive; private float _duration = 120f; private float _elapsed; private float _retryTimer; private float _boostTimer; private Vector3 _lastPosition; private float _stuckCheckTimer; private float _patrolRetargetTimer; private bool _hitPlayer; public void Configure(ValuableCar car, bool aggressive, float durationSeconds = 120f) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Unknown result type (might be due to invalid IL or missing references) _car = car; _rb = ((Component)car).GetComponentInChildren(); PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _playerTarget = ((localPlayer != null) ? ((Component)localPlayer).transform : null); _aggressive = aggressive; _duration = Mathf.Max(10f, durationSeconds); _retryTimer = 0.1f; _boostTimer = 3f; _lastPosition = ((Component)car).transform.position; _stuckCheckTimer = 0.35f; _patrolRetargetTimer = 0f; _patrolTarget = PickPatrolTarget(); ClearStuck(); TryDrive(); ApplyLaunchBoost(); } private void FixedUpdate() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_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_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00e4: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_0166: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_car == (Object)null || (Object)(object)_rb == (Object)null) { return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { Object.Destroy((Object)(object)this); return; } ClearStuck(); UpdatePatrolTarget(); Vector3 driveDirection = GetDriveDirection(); ((Component)_car).transform.rotation = Quaternion.Slerp(((Component)_car).transform.rotation, Quaternion.LookRotation(driveDirection, Vector3.up), _aggressive ? 0.38f : 0.24f); float num = Vector3.Dot(_rb.velocity, driveDirection); float num2 = (_aggressive ? 62f : ((_boostTimer > 0f) ? 55f : 34f)); if (num < 6f) { _rb.AddForce(driveDirection * num2, (ForceMode)5); } _boostTimer -= Time.fixedDeltaTime; _retryTimer -= Time.fixedDeltaTime; if (_retryTimer <= 0f) { _retryTimer = 0.2f; if (!IsDriving()) { TryDrive(); } } _stuckCheckTimer -= Time.fixedDeltaTime; if (_stuckCheckTimer <= 0f) { _stuckCheckTimer = 0.3f; CheckAndUnstick(driveDirection); } } private void OnCollisionEnter(Collision collision) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) if (!_aggressive || _hitPlayer) { return; } PlayerAvatar componentInParent = collision.gameObject.GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { _hitPlayer = true; if ((Object)(object)componentInParent.playerHealth != (Object)null) { componentInParent.playerHealth.HurtOther(5, Vector3.zero, false, -1, false); } if ((Object)(object)componentInParent.tumble != (Object)null) { ValuableCar? car = _car; Vector3 val = ((car != null) ? ((Component)car).transform.forward : ((Component)this).transform.forward) * 12f; PlayerEffectHelper.Knockdown(12f, 10f); } } } private void UpdatePatrolTarget() { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) if (!_aggressive) { _patrolRetargetTimer -= Time.fixedDeltaTime; float num = Vector3.Distance(((Component)_car).transform.position, _patrolTarget); if (_patrolRetargetTimer <= 0f || num < 1.4f) { _patrolRetargetTimer = Random.Range(2.5f, 5f); _patrolTarget = PickPatrolTarget(); } } } private Vector3 PickPatrolTarget() { //IL_008f: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a9: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) try { List list = SemiFunc.LevelPointsGetAll(); if (list != null && list.Count > 0) { List list2 = list.Where((LevelPoint p) => (Object)(object)p != (Object)null).ToList(); if (list2.Count > 0) { return ((Component)list2[Random.Range(0, list2.Count)]).transform.position; } } } catch { } if (!((Object)(object)_car != (Object)null)) { return ((Component)this).transform.position; } return ((Component)_car).transform.position + ((Component)_car).transform.forward * 6f; } private Vector3 GetDriveDirection() { //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_00ca: Unknown result type (might be due to invalid IL or missing references) //IL_00c2: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) if (_aggressive && (Object)(object)_playerTarget != (Object)null) { Vector3 val = _playerTarget.position - ((Component)_car).transform.position; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude > 0.04f) { return ((Vector3)(ref val)).normalized; } } Vector3 val2 = _patrolTarget - ((Component)_car).transform.position; val2.y = 0f; if (((Vector3)(ref val2)).sqrMagnitude > 0.04f) { return ((Vector3)(ref val2)).normalized; } Vector3 forward = ((Component)_car).transform.forward; forward.y = 0f; if (!(((Vector3)(ref forward)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private void CheckAndUnstick(Vector3 forward) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0070: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_car == (Object)null) && !((Object)(object)_rb == (Object)null)) { float num = Vector3.Distance(((Component)_car).transform.position, _lastPosition); _lastPosition = ((Component)_car).transform.position; if (!(num > 0.08f)) { ClearStuck(); Rigidbody? rb = _rb; Vector3 velocity = _rb.velocity; rb.velocity = forward * Mathf.Max(6f, ((Vector3)(ref velocity)).magnitude + 2f); _rb.AddForce(forward * 16f + Vector3.up * 1.5f, (ForceMode)2); _boostTimer = Mathf.Max(_boostTimer, 1.2f); TryDrive(); } } } private void ApplyLaunchBoost() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rb == (Object)null) && !((Object)(object)_car == (Object)null)) { Vector3 driveDirection = GetDriveDirection(); _rb.velocity = driveDirection * (_aggressive ? 8.5f : 7f); _rb.AddForce(driveDirection * (_aggressive ? 12f : 10f) + Vector3.up * 0.8f, (ForceMode)2); } } private bool IsDriving() { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Invalid comparison between Unknown and I4 if ((Object)(object)_car == (Object)null) { return false; } try { if (typeof(ValuableCar).GetField("currentState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(_car) is State val) { return (int)val == 2; } } catch { } return false; } private void TryDrive() { if ((Object)(object)_car == (Object)null) { return; } try { ((Trap)_car).TrapStart(); } catch (Exception ex) { ModLog.Debug("ToyCarDriveBehavior TrapStart failed: " + ex.Message); } try { typeof(ValuableCar).GetMethod("UpdateState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(_car, new object[1] { (object)(State)2 }); } catch (Exception ex2) { ModLog.Debug("ToyCarDriveBehavior UpdateState failed: " + ex2.Message); } } private void ClearStuck() { if (!((Object)(object)_car == (Object)null)) { TrySetField(_car, "stuck", false); TrySetField(_car, "stuckTime", 0f); } } private static void TrySetField(object target, string fieldName, object value) { try { FieldInfo field = target.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (!(field == null)) { field.SetValue(target, value); } } catch { } } } internal sealed class ToyPlaneDriveBehavior : MonoBehaviour { private enum FlightPhase { Launch, Patrol, Dive } private readonly struct FlightBounds { public float FloorY { get; init; } public float CeilingY { get; init; } public bool HasCeiling { get; init; } public float PatrolY { get { float num = FloorY + 5f; float num2 = FloorY + 3f; if (!HasCeiling) { return Mathf.Max(num, num2); } float num3 = CeilingY - 1.15f; if (num3 <= num2) { return Mathf.Max(FloorY + 1.8f, (FloorY + CeilingY) * 0.5f); } return Mathf.Clamp(num, num2, num3); } } } private const float PatrolForce = 7f; private const float DiveForce = 14f; private const float PatrolMaxSpeed = 5.5f; private const float DiveMaxSpeed = 10f; private const float IdealPatrolHeight = 5f; private const float MinPatrolHeight = 3f; private const float CeilingClearance = 1.15f; private const float FloorClearance = 1.8f; private const float DiveChance = 0.3f; private const float UnstickImpulse = 5f; private ValuablePlane? _plane; private Rigidbody? _rb; private Transform? _playerTarget; private Vector3 _patrolTarget; private FlightPhase _phase = FlightPhase.Patrol; private bool _hitPlayer; private float _duration = 120f; private float _elapsed; private float _retryTimer; private float _patrolRetargetTimer; private float _diveCooldown; private float _diveTimer; private Vector3 _lastPosition; private float _launchTimer; private float _launchTargetY; private float _stuckCheckTimer; public void Configure(ValuablePlane plane, bool aggressive = false, float durationSeconds = 120f) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) _plane = plane; _rb = ((Component)plane).GetComponentInChildren(); PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _playerTarget = ((localPlayer != null) ? ((Component)localPlayer).transform : null); _duration = Mathf.Max(10f, durationSeconds); _phase = FlightPhase.Launch; _patrolTarget = PickHighPatrolTarget(); _lastPosition = ((Component)plane).transform.position; _retryTimer = 0.1f; _patrolRetargetTimer = 0f; _stuckCheckTimer = 0.35f; _diveCooldown = Random.Range(2.5f, 6f); _diveTimer = 0f; _launchTimer = 3.5f; PlaceAtPlayerHead(); TryActivateFlight(); } private void PlaceAtPlayerHead() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_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_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_plane == (Object)null) && !((Object)(object)_rb == (Object)null)) { Vector3 playerHeadPosition = GetPlayerHeadPosition(); Vector3 val = Random.insideUnitSphere; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.01f) { val = Vector3.right; } ((Vector3)(ref val)).Normalize(); Vector3 position = playerHeadPosition + val * 0.65f; _launchTargetY = GetFlightBounds(position).PatrolY; ((Component)_plane).transform.position = position; _rb.position = position; _rb.velocity = Vector3.zero; _rb.angularVelocity = Vector3.zero; } } private Vector3 GetPlayerHeadPosition() { //IL_0026: 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_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003c: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)_playerTarget != (Object)null) ? _playerTarget.position : ((Component)_plane).transform.position); return val + Vector3.up * 1.55f; } private void FixedUpdate() { //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: 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) if ((Object)(object)_plane == (Object)null || (Object)(object)_rb == (Object)null) { return; } _elapsed += Time.fixedDeltaTime; if (_elapsed >= _duration) { Object.Destroy((Object)(object)this); return; } UpdateFlightPhase(); if (_phase == FlightPhase.Launch) { UpdateLaunchFlight(); return; } UpdatePatrolTarget(); Vector3 driveDirection = GetDriveDirection(); ((Component)_plane).transform.rotation = Quaternion.Slerp(((Component)_plane).transform.rotation, Quaternion.LookRotation(driveDirection, Vector3.up), (_phase == FlightPhase.Dive) ? 0.18f : 0.09f); float num = ((_phase == FlightPhase.Dive) ? 14f : 7f); _rb.AddForce(driveDirection * num, (ForceMode)5); ApplyAltitudeControl(); EnforceMinimumAltitude(); ClampSpeed((_phase == FlightPhase.Dive) ? 10f : 5.5f); _retryTimer -= Time.fixedDeltaTime; if (_retryTimer <= 0f) { _retryTimer = 0.25f; TryActivateFlight(); } _stuckCheckTimer -= Time.fixedDeltaTime; if (_stuckCheckTimer <= 0f) { _stuckCheckTimer = 0.35f; CheckAndUnstick(driveDirection); } } private void ClampSpeed(float maxSpeed) { //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_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_rb == (Object)null)) { Vector3 velocity = _rb.velocity; if (!(((Vector3)(ref velocity)).sqrMagnitude <= maxSpeed * maxSpeed)) { _rb.velocity = ((Vector3)(ref velocity)).normalized * maxSpeed; } } } private void OnCollisionEnter(Collision collision) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) ValuableDamageHelper.ApplyImpactDamage(((Component)this).gameObject, 0.15f, heavy: true); if (ValuableDamageHelper.IsDestroyed(((Component)this).gameObject)) { Object.Destroy((Object)(object)this); } else { if (_phase != FlightPhase.Dive || _hitPlayer) { return; } PlayerAvatar componentInParent = collision.gameObject.GetComponentInParent(); if (!((Object)(object)componentInParent == (Object)null)) { _hitPlayer = true; if ((Object)(object)componentInParent.playerHealth != (Object)null) { componentInParent.playerHealth.HurtOther(5, Vector3.zero, false, -1, false); } if ((Object)(object)componentInParent == (Object)(object)PlayerEffectHelper.GetLocalPlayer()) { PlayerEffectHelper.Knockdown(12f, 10f); } ReturnToPatrol(); } } } private void UpdateLaunchFlight() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00bc: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00d0: Unknown result type (might be due to invalid IL or missing references) //IL_00d3: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00f7: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0106: Unknown result type (might be due to invalid IL or missing references) //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_0127: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_016b: Unknown result type (might be due to invalid IL or missing references) //IL_0170: Unknown result type (might be due to invalid IL or missing references) //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01bf: Unknown result type (might be due to invalid IL or missing references) //IL_01c4: Unknown result type (might be due to invalid IL or missing references) //IL_01e5: Unknown result type (might be due to invalid IL or missing references) //IL_01f2: Unknown result type (might be due to invalid IL or missing references) //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_plane == (Object)null) && !((Object)(object)_rb == (Object)null)) { _launchTimer -= Time.fixedDeltaTime; PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _playerTarget = ((localPlayer != null) ? ((Component)localPlayer).transform : null) ?? _playerTarget; Vector3 playerHeadPosition = GetPlayerHeadPosition(); Vector3 val = ((Component)_plane).transform.position - playerHeadPosition; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.04f) { val = ((Component)_plane).transform.forward; } ((Vector3)(ref val)).Normalize(); Transform transform = ((Component)_plane).transform; Quaternion rotation = ((Component)_plane).transform.rotation; Vector3 val2 = val + Vector3.up * 0.85f; transform.rotation = Quaternion.Slerp(rotation, Quaternion.LookRotation(((Vector3)(ref val2)).normalized, Vector3.up), 0.16f); _rb.AddForce(Vector3.up * 11f + val * 3f, (ForceMode)5); FlightBounds flightBounds = GetFlightBounds(((Component)_plane).transform.position); if (((Component)_plane).transform.position.y >= _launchTargetY - 0.2f || _launchTimer <= 0f) { _phase = FlightPhase.Patrol; _patrolTarget = PickHighPatrolTarget(); _patrolRetargetTimer = 0f; } if (flightBounds.HasCeiling && ((Component)_plane).transform.position.y > flightBounds.CeilingY - 1.15f) { _phase = FlightPhase.Patrol; Vector3 position = ((Component)_plane).transform.position; position.y = flightBounds.CeilingY - 1.15f; ((Component)_plane).transform.position = position; _rb.position = position; _patrolTarget = PickHighPatrolTarget(); } } } private void UpdateFlightPhase() { if (_phase == FlightPhase.Launch) { return; } if (_phase == FlightPhase.Dive) { _diveTimer -= Time.fixedDeltaTime; if (_diveTimer <= 0f || _hitPlayer) { ReturnToPatrol(); } return; } _diveCooldown -= Time.fixedDeltaTime; if (_diveCooldown > 0f) { return; } _diveCooldown = Random.Range(4f, 9f); if (!(Random.value > 0.3f)) { PlayerAvatar? localPlayer = PlayerEffectHelper.GetLocalPlayer(); _playerTarget = ((localPlayer != null) ? ((Component)localPlayer).transform : null); if (!((Object)(object)_playerTarget == (Object)null)) { _phase = FlightPhase.Dive; _diveTimer = Random.Range(4f, 7f); _hitPlayer = false; } } } private void ReturnToPatrol() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) _phase = FlightPhase.Patrol; _diveCooldown = Random.Range(4f, 9f); _patrolTarget = PickHighPatrolTarget(); _patrolRetargetTimer = 0f; } private void EnforceMinimumAltitude() { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) //IL_007b: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_00b2: Unknown result type (might be due to invalid IL or missing references) //IL_00b3: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_plane == (Object)null || (Object)(object)_rb == (Object)null || _phase == FlightPhase.Dive || _phase == FlightPhase.Launch) { return; } FlightBounds flightBounds = GetFlightBounds(((Component)_plane).transform.position); float num = flightBounds.FloorY + 3f; if (!(((Component)_plane).transform.position.y >= num)) { Vector3 position = ((Component)_plane).transform.position; position.y = flightBounds.PatrolY; ((Component)_plane).transform.position = position; _rb.position = position; Vector3 velocity = _rb.velocity; if (velocity.y < 0f) { velocity.y = 0f; _rb.velocity = velocity; } } } private void ApplyAltitudeControl() { //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_00cf: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_plane == (Object)null) && !((Object)(object)_rb == (Object)null) && _phase != FlightPhase.Dive) { FlightBounds flightBounds = GetFlightBounds(((Component)_plane).transform.position); float patrolY = flightBounds.PatrolY; float num = patrolY - ((Component)_plane).transform.position.y; if (num > 0.35f) { _rb.AddForce(Vector3.up * Mathf.Clamp(num * 2f, 1.2f, 5f), (ForceMode)5); } else if (num < -0.45f) { _rb.AddForce(Vector3.up * num * 1.8f, (ForceMode)5); } if (flightBounds.HasCeiling && ((Component)_plane).transform.position.y > flightBounds.CeilingY - 1.15f) { float num2 = ((Component)_plane).transform.position.y - (flightBounds.CeilingY - 1.15f); _rb.AddForce(Vector3.down * Mathf.Clamp(num2 * 3f, 1f, 8f), (ForceMode)5); } } } private void LiftToPatrolAltitude() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_plane == (Object)null) && !((Object)(object)_rb == (Object)null)) { FlightBounds flightBounds = GetFlightBounds(((Component)_plane).transform.position); Vector3 position = ((Component)_plane).transform.position; position.y = flightBounds.PatrolY; ((Component)_plane).transform.position = position; _rb.position = position; _rb.velocity = Vector3.zero; } } private static FlightBounds GetFlightBounds(Vector3 position) { //IL_0000: 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_0026: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) float floorHeight = GetFloorHeight(position); bool hasCeiling = false; float ceilingY = floorHeight + 5f + 8f; Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(position.x, floorHeight + 0.35f, position.z); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.up, ref val2, 24f, -5, (QueryTriggerInteraction)1) && (((RaycastHit)(ref val2)).normal.y < -0.25f || ((RaycastHit)(ref val2)).point.y > floorHeight + 3f + 0.5f)) { ceilingY = ((RaycastHit)(ref val2)).point.y; hasCeiling = true; } return new FlightBounds { FloorY = floorHeight, CeilingY = ceilingY, HasCeiling = hasCeiling }; } private static float GetFloorHeight(Vector3 position) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0085: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0141: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_00fd: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Unknown result type (might be due to invalid IL or missing references) //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0109: Unknown result type (might be due to invalid IL or missing references) //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_0123: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) Vector3 val = default(Vector3); ((Vector3)(ref val))..ctor(position.x, position.y + 40f, position.z); RaycastHit val2 = default(RaycastHit); if (Physics.Raycast(val, Vector3.down, ref val2, 90f, -5, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val2)).normal.y > 0.5f) { return ((RaycastHit)(ref val2)).point.y; } Vector3 val3 = position + Vector3.up * 2f; RaycastHit val4 = default(RaycastHit); if (Physics.Raycast(val3, Vector3.down, ref val4, 40f, -5, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val4)).normal.y > 0.5f) { return ((RaycastHit)(ref val4)).point.y; } try { Vector3 val5 = SpawnHelper.SnapToFloor(position, 0.05f); if (val5.y > position.y - 8f) { return val5.y; } } catch { } PlayerAvatar val6 = SemiFunc.PlayerAvatarLocal(); if ((Object)(object)val6 != (Object)null) { Vector3 val7 = ((Component)val6).transform.position + Vector3.up * 1.5f; RaycastHit val8 = default(RaycastHit); if (Physics.Raycast(val7, Vector3.down, ref val8, 30f, -5, (QueryTriggerInteraction)1) && ((RaycastHit)(ref val8)).normal.y > 0.5f) { return ((RaycastHit)(ref val8)).point.y; } } return position.y; } private void UpdatePatrolTarget() { //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0067: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) if (_phase != FlightPhase.Dive) { _patrolRetargetTimer -= Time.fixedDeltaTime; if (_patrolRetargetTimer <= 0f || Vector3.Distance(((Component)_plane).transform.position, _patrolTarget) < 3f) { _patrolRetargetTimer = Random.Range(4f, 8f); _patrolTarget = PickHighPatrolTarget(); } } } private Vector3 PickHighPatrolTarget() { //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ad: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) Vector3 val = (((Object)(object)_playerTarget != (Object)null) ? _playerTarget.position : (((Object)(object)_plane != (Object)null) ? ((Component)_plane).transform.position : ((Component)this).transform.position)); float num = Random.Range(0f, 360f) * (MathF.PI / 180f); float num2 = Random.Range(4f, 10f); Vector3 val2 = val + new Vector3(Mathf.Cos(num) * num2, 0f, Mathf.Sin(num) * num2); float patrolY = GetFlightBounds(val2).PatrolY; return new Vector3(val2.x, patrolY, val2.z); } private Vector3 GetDriveDirection() { //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00b5: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) if (_phase == FlightPhase.Dive && (Object)(object)_playerTarget != (Object)null) { Vector3 val = _playerTarget.position + Vector3.up * 1.6f; Vector3 val2 = val - ((Component)_plane).transform.position; if (((Vector3)(ref val2)).sqrMagnitude > 0.04f) { return ((Vector3)(ref val2)).normalized; } } Vector3 val3 = _patrolTarget - ((Component)_plane).transform.position; if (((Vector3)(ref val3)).sqrMagnitude > 0.04f) { return ((Vector3)(ref val3)).normalized; } Vector3 forward = ((Component)_plane).transform.forward; if (!(((Vector3)(ref forward)).sqrMagnitude > 0.01f)) { return Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private void CheckAndUnstick(Vector3 forward) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_plane == (Object)null) && !((Object)(object)_rb == (Object)null)) { float num = Vector3.Distance(((Component)_plane).transform.position, _lastPosition); _lastPosition = ((Component)_plane).transform.position; if (!(num > 0.1f)) { _rb.AddForce(forward * 5f + Vector3.up * 2f, (ForceMode)2); } } } private void TryActivateFlight() { if ((Object)(object)_plane == (Object)null) { return; } try { ((Trap)_plane).TrapStart(); } catch (Exception ex) { ModLog.Debug("ToyPlane TrapStart failed: " + ex.Message); } try { typeof(ValuablePlane).GetMethod("UpdateState", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(_plane, new object[1] { (object)(State)4 }); } catch (Exception ex2) { ModLog.Debug("ToyPlane UpdateState failed: " + ex2.Message); } } } internal static class ValuableDamageHelper { public static bool ApplyImpactDamage(GameObject go, float lossFraction = 0.2f, bool heavy = false) { //IL_00ea: Unknown result type (might be due to invalid IL or missing references) //IL_00d6: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)go == (Object)null) { return false; } ValuableObject componentInChildren = go.GetComponentInChildren(true); PhysGrabObjectImpactDetector componentInChildren2 = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren == (Object)null && (Object)(object)componentInChildren2 == (Object)null) { return false; } ImpactLaunchHelper.PrepareForImpactBreak(go); if ((Object)(object)componentInChildren != (Object)null) { float num = componentInChildren.dollarValueCurrent; if (num <= 0f && componentInChildren.dollarValueOriginal > 0f) { num = componentInChildren.dollarValueOriginal; } float num2 = Mathf.Max(new float[3] { num * lossFraction, componentInChildren.dollarValueOriginal * 0.08f, 1f }); componentInChildren.dollarValueCurrent = Mathf.Max(0f, num - num2); try { componentInChildren.DollarValueSetLogic(); } catch (Exception ex) { ModLog.Debug("DollarValueSetLogic failed: " + ex.Message); } if (componentInChildren.dollarValueCurrent <= 0f) { ForceBreak(componentInChildren2, go.transform.position, heavy: true); return true; } } ForceBreak(componentInChildren2, go.transform.position, heavy); if (!((Object)(object)componentInChildren == (Object)null)) { return componentInChildren.dollarValueCurrent > 0f; } return true; } public static bool IsDestroyed(GameObject go) { if ((Object)(object)go == (Object)null) { return true; } ValuableObject componentInChildren = go.GetComponentInChildren(true); if ((Object)(object)componentInChildren != (Object)null && componentInChildren.dollarValueCurrent <= 0f) { return true; } return false; } private static void ForceBreak(PhysGrabObjectImpactDetector? impact, Vector3 point, bool heavy) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_000f: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)impact == (Object)null) { return; } try { if (heavy) { impact.BreakHeavy(point, true, 0f); } else { impact.BreakLight(point, true); } } catch { try { impact.DestroyObject(true); } catch { } } } } internal static class ValuableSpawnHelper { private static readonly Dictionary DisplayToInternal = new Dictionary(StringComparer.OrdinalIgnoreCase) { ["Diamond"] = "Valuable_Wizard_Diamond", ["Emerald Bracelet"] = "Valuable_Wizard_Emerald_Bracelet", ["Goblet"] = "Valuable_Manor_Goblet", ["Ocarina"] = "Valuable_Manor_Ocarina", ["Pocket Watch"] = "Valuable_Manor_Pocket_Watch", ["Uranium Mug"] = "Valuable_Museum_Uranium_Mug", ["Arctic Bonsai"] = "Valuable_Arctic_Bonsai", ["Arctic HDD"] = "Valuable_Arctic_HDD", ["Chomp Book"] = "Valuable_Manor_Chomp_Book", ["Crown"] = "Valuable_Manor_Crown", ["Doll"] = "Valuable_Manor_Scream_Doll", ["Frog"] = "Valuable_Manor_Frog", ["Gem Box"] = "Valuable_Manor_Gem_Box", ["Globe"] = "Valuable_Manor_Globe", ["Love Potion"] = "Valuable_Wizard_Love_Potion", ["Money"] = "Valuable_Manor_Money", ["Music Box"] = "Valuable_Manor_Music_Box", ["Toy Monkey"] = "Valuable_Manor_Toy_Monkey", ["Toy Car"] = "Valuable_Car", ["Valuable Car"] = "Valuable_Car", ["Toy Plane"] = "Valuable_Plane", ["Uranium Plate"] = "Valuable_Museum_Uranium_Plate", ["Vase Small"] = "Valuable_Manor_Vase_Small", ["Arctic 3D Printer"] = "Valuable_Arctic_3D_Printer", ["Arctic Laptop"] = "Valuable_Arctic_Laptop", ["Arctic Propane Tank"] = "Valuable_Arctic_Propane_Tank", ["Arctic Sample"] = "Valuable_Arctic_Sample", ["Arctic Sample Six Pack"] = "Valuable_Arctic_Sample_Six_Pack", ["Bottle"] = "Valuable_Manor_Bottle", ["Clown"] = "Valuable_Manor_Clown", ["Computer"] = "Valuable_Manor_Computer", ["Fan"] = "Valuable_Arctic_Fan", ["Gramophone"] = "Valuable_Manor_Gramophone", ["Marble Table"] = "Valuable_Manor_Marble_Table", ["Radio"] = "Valuable_Manor_Radio", ["Ship in a bottle"] = "Valuable_Manor_Ship_in_a_Bottle", ["Trophy"] = "Valuable_Manor_Trophy", ["Vase"] = "Valuable_Manor_Vase", ["Wizard Goblin Head"] = "Valuable_Wizard_Goblin_Head", ["Wizard Power Crystal"] = "Valuable_Wizard_Power_Crystal", ["Wizard Time Glass"] = "Valuable_Wizard_Time_Glass", ["Arctic Barrel"] = "Valuable_Arctic_Barrel", ["Arctic Big Sample"] = "Valuable_Arctic_Big_Sample", ["Arctic Creature Leg"] = "Valuable_Arctic_Creature_Leg", ["Arctic Flamethrower"] = "Valuable_Arctic_Flamethrower", ["Arctic Guitar"] = "Valuable_Arctic_Guitar", ["Arctic Sample Cooler"] = "Valuable_Arctic_Sample_Cooler", ["Diamond Display"] = "Valuable_Manor_Diamond_Display", ["Ice Saw"] = "Valuable_Arctic_Ice_Saw", ["Scream Doll"] = "Valuable_Manor_Scream_Doll", ["Television"] = "Valuable_Manor_Television", ["Vase Big"] = "Valuable_Manor_Vase_Big", ["Wizard Cube of Knowledge"] = "Valuable_Wizard_Cube_of_Knowledge", ["Wizard Master Potion"] = "Valuable_Wizard_Master_Potion", ["Animal Crate"] = "Valuable_Manor_Animal_Crate", ["Arctic Ice Block"] = "Valuable_Arctic_Ice_Block", ["Dinosaur"] = "Valuable_Manor_Dinosaur", ["Piano"] = "Valuable_Manor_Piano", ["Wizard Griffin Statue"] = "Valuable_Wizard_Griffin_Statue", ["Arctic Science Station"] = "Valuable_Arctic_Science_Station", ["Harp"] = "Valuable_Manor_Harp", ["Painting"] = "Valuable_Manor_Painting", ["Wizard Dumgolfs Staff"] = "Valuable_Wizard_Dumgolfs_Staff", ["Wizard Sword"] = "Valuable_Wizard_Sword", ["Arctic Server Rack"] = "Valuable_Arctic_Server_Rack", ["Golden Statue"] = "Valuable_Manor_Golden_Statue", ["Grandfather Clock"] = "Valuable_Manor_Grandfather_Clock", ["Wizard Broom"] = "Valuable_Wizard_Broom", ["Gold"] = "Valuable_Manor_Money", ["Silver"] = "Valuable_Manor_Money", ["Ruby"] = "Valuable_Wizard_Power_Crystal", ["Uranium Mug Deluxe"] = "Valuable_Museum_Uranium_Mug_Deluxe", ["Baby Head"] = "Valuable_Museum_Baby_Head", ["Gem Burger"] = "Valuable_Museum_Gem_Burger", ["Gumball"] = "Valuable_Museum_Gumball", ["Boombox"] = "Valuable_Museum_Boombox", ["Milk"] = "Valuable_Museum_Milk", ["Golden Swirl"] = "Valuable_Museum_Golden_Swirl", ["Blender"] = "Valuable_Museum_Blender", ["Horse"] = "Valuable_Museum_Horse", ["Traffic Light"] = "Valuable_Museum_Traffic_Light", ["Star Wand"] = "Valuable_Wizard_Star_Wand", ["Levitation Potion"] = "Valuable_Wizard_Levitation_Potion", ["Jackhammer"] = "Valuable_Arctic_Jackhammer", ["Coffin"] = "Valuable_Manor_Coffin", ["Tray"] = "Valuable_Museum_Tray", ["Dragon Skull"] = "Valuable_Wizard_Dragon_Skull" }; public static bool TrySpawn(string query, Vector3 pos, Quaternion rot, out string? spawnedLabel) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) GameObject spawnedObject; return TrySpawn(query, pos, rot, out spawnedLabel, out spawnedObject); } public static bool TrySpawn(string query, Vector3 pos, Quaternion rot, out string? spawnedLabel, out GameObject? spawnedObject) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) spawnedLabel = null; spawnedObject = null; if (string.IsNullOrWhiteSpace(query)) { return false; } string internalName = ResolveInternalName(query); foreach (string item in ExpandSearchTerms(internalName)) { if (TrySpawnViaRepolib(item, pos, rot, out spawnedLabel, out spawnedObject)) { return true; } if (TrySpawnViaResources(item, pos, rot, out spawnedLabel, out spawnedObject)) { return true; } } return false; } public static string ResolveInternalName(string query) { if (RepoEventMap.TryGetLootInternalName(query, out string valuableId)) { return valuableId; } if (DisplayToInternal.TryGetValue(query.Trim(), out string value)) { return value; } if (query.StartsWith("Valuable_", StringComparison.OrdinalIgnoreCase)) { return query; } string text = query.Trim().Replace(' ', '_'); return "Valuable_" + text; } private static IEnumerable ExpandSearchTerms(string internalName) { yield return internalName; yield return internalName.Replace('_', ' '); if (internalName.StartsWith("Valuable_", StringComparison.Ordinal)) { yield return "Valuable " + internalName.Substring(9).Replace('_', ' '); } } private static bool TrySpawnViaRepolib(string candidate, Vector3 pos, Quaternion rot, out string? label, out GameObject? spawnedObject) { //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) label = candidate; spawnedObject = null; try { PrefabRef val = Valuables.AllValuables?.FirstOrDefault((Func)((PrefabRef v) => v != null && (string.Equals(((PrefabRef)(object)v).PrefabName, candidate, StringComparison.OrdinalIgnoreCase) || string.Equals(((PrefabRef)(object)v).PrefabName, candidate.Replace('_', ' '), StringComparison.OrdinalIgnoreCase) || (((PrefabRef)(object)v).PrefabName ?? "").IndexOf(candidate, StringComparison.OrdinalIgnoreCase) >= 0))); if (val == null || !((PrefabRef)(object)val).IsValid()) { return false; } spawnedObject = Valuables.SpawnValuable(val, pos, rot); label = ((PrefabRef)(object)val).PrefabName ?? candidate; ModLog.Info("Spawned valuable via REPOLib: " + label); return (Object)(object)spawnedObject != (Object)null; } catch (Exception ex) { ModLog.Warn("REPOLib valuable spawn failed for '" + candidate + "': " + ex.Message); return false; } } private static bool TrySpawnViaResources(string candidate, Vector3 pos, Quaternion rot, out string? label, out GameObject? spawnedObject) { //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Unknown result type (might be due to invalid IL or missing references) label = candidate; spawnedObject = null; foreach (string resourcePath in GetResourcePaths(candidate)) { GameObject val = Resources.Load(resourcePath); if ((Object)(object)val == (Object)null) { continue; } try { GameObject val2 = Object.Instantiate(val, pos, rot); if ((Object)(object)val2 == (Object)null) { continue; } spawnedObject = val2; label = ((Object)val).name; ModLog.Info("Spawned valuable via Resources: " + resourcePath); return true; } catch (Exception ex) { ModLog.Warn("Resources valuable instantiate failed for " + resourcePath + ": " + ex.Message); } } return false; } private static IEnumerable GetResourcePaths(string term) { yield return "Valuables/" + term; yield return "Valuables/Valuable - " + term.Replace("Valuable_", "").Replace('_', ' '); if (term.StartsWith("Valuable_", StringComparison.Ordinal)) { yield return "Valuables/" + term.Substring(9); } } } }