using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Microsoft.CodeAnalysis; using Photon.Pun; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("")] [assembly: AssemblyCompany("REPOJP")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("zabuMod")] [assembly: AssemblyTitle("zabuMod")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace REPOJP.ArenaRaceMultiplayerSpawnFix { [BepInPlugin("REPOJP.ArenaRaceMultiplayerSpawnFix", "ArenaRaceMultiplayerSpawnFix", "4.0.2")] public class ArenaRaceMultiplayerSpawnFixPlugin : BaseUnityPlugin { private sealed class LayoutPlan { public readonly List Positions = new List(); } [HarmonyPatch(typeof(LevelGenerator), "PlayerSpawn")] private static class LevelGeneratorPlayerSpawnPatch { private static void Postfix() { try { ScheduleLayoutApplyFromPlayerSpawn(); } catch (Exception ex) { LogError("Failure: PlayerSpawn Postfix\n" + ex); } } } [HarmonyPatch(typeof(ArenaRace), "StateSetRPC")] private static class ArenaRaceStateSetRPCPatch { private static void Postfix(ArenaRace __instance, States _state) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Invalid comparison between Unknown and I4 try { if ((int)_state == 2) { ApplyStartBoostOnce(__instance); } } catch (Exception ex) { LogError("Failure: ArenaRace.StateSetRPC Postfix\n" + ex); } } } [CompilerGenerated] private sealed class d__31 : IEnumerator, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; public int scheduleId; private int 5__1; private string 5__2; object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public d__31(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { 5__2 = null; <>1__state = -2; } private bool MoveNext() { switch (<>1__state) { default: return false; case 0: <>1__state = -1; 5__1 = 1; break; case 1: <>1__state = -1; if (scheduleId != layoutScheduleId) { return false; } if (!CanApplyLayoutNow(out 5__2)) { if (5__1 == 45) { LogWarning("Skipped layout apply after retry: " + 5__2 + " | Attempts=" + 5__1 + " | " + BuildContextSummary()); } 5__1++; break; } TryApplyLayout(scheduleId, 5__1); return false; } if (5__1 <= 45) { <>2__current = null; <>1__state = 1; return true; } return false; } bool IEnumerator.MoveNext() { //ILSpy generated this explicit interface implementation from .override directive in MoveNext return this.MoveNext(); } [DebuggerHidden] void IEnumerator.Reset() { throw new NotSupportedException(); } } public const string PluginGuid = "REPOJP.ArenaRaceMultiplayerSpawnFix"; public const string PluginName = "ArenaRaceMultiplayerSpawnFix"; public const string PluginVersion = "4.0.2"; private const float FixedHorizontalSpacing = 0.8f; private const float FixedVerticalSpacing = 3f; private const float FixedHeightOffset = 5f; private const float FixedBackwardOffset = 10f; private static ManualLogSource logSource; private static Harmony harmony; private static ArenaRaceMultiplayerSpawnFixPlugin pluginInstance; private static ConfigEntry enabledConfig; private static ConfigEntry horizontalPlayersConfig; private static ConfigEntry verticalPlayersConfig; private static ConfigEntry startBoostEnabledConfig; private static ConfigEntry startBoostMultiplierConfig; private static FieldInfo arenaRacePlayerVehicleMapField; private static FieldInfo arenaRaceVehiclesField; private static MethodInfo itemVehicleOverrideYawMethod; private static MethodInfo itemVehicleOverridePitchMethod; private static MethodInfo playerAvatarSpawnRPCMethod; private static int lastStartBoostArenaRaceInstanceId; private static int layoutScheduleId; private static bool layoutApplyInProgress; private const int DelayedLayoutMaxAttempts = 45; private void Awake() { //IL_0140: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Expected O, but got Unknown try { ((Component)this).transform.parent = null; ((Object)((Component)this).gameObject).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)((Component)this).gameObject); pluginInstance = this; logSource = ((BaseUnityPlugin)this).Logger; BindConfig(); arenaRacePlayerVehicleMapField = AccessTools.Field(typeof(ArenaRace), "playerVehicleMap"); arenaRaceVehiclesField = AccessTools.Field(typeof(ArenaRace), "vehicles"); itemVehicleOverrideYawMethod = AccessTools.Method(typeof(ItemVehicle), "OverrideYaw", new Type[3] { typeof(Vector3), typeof(float), typeof(int) }, (Type[])null); itemVehicleOverridePitchMethod = AccessTools.Method(typeof(ItemVehicle), "OverridePitch", new Type[2] { typeof(float), typeof(float) }, (Type[])null); playerAvatarSpawnRPCMethod = AccessTools.Method(typeof(PlayerAvatar), "SpawnRPC", new Type[3] { typeof(Vector3), typeof(Quaternion), typeof(PhotonMessageInfo) }, (Type[])null); harmony = new Harmony("REPOJP.ArenaRaceMultiplayerSpawnFix"); harmony.PatchAll(); LogInfo("Loaded ArenaRaceMultiplayerSpawnFix v4.0.2"); LogInfo("Config: Enabled=" + GetConfigBool(enabledConfig, defaultValue: false) + ", HorizontalPlayers=" + GetConfigInt(horizontalPlayersConfig, 10) + ", VerticalPlayers=" + GetConfigInt(verticalPlayersConfig, 2) + ", StartBoostEnabled=" + GetConfigBool(startBoostEnabledConfig, defaultValue: false) + ", StartBoostMultiplier=" + GetConfigFloat(startBoostMultiplierConfig, 10f)); if (arenaRacePlayerVehicleMapField == null) { LogWarning("Warning: ArenaRace.playerVehicleMap field was not found. Start boost will use fallback vehicle list if available."); } if (arenaRaceVehiclesField == null) { LogWarning("Warning: ArenaRace.vehicles field was not found. Start boost fallback vehicle list is unavailable."); } if (itemVehicleOverrideYawMethod == null) { LogWarning("Warning: ItemVehicle.OverrideYaw method was not found. Start boost cannot be applied."); } if (playerAvatarSpawnRPCMethod == null) { LogWarning("Warning: PlayerAvatar.SpawnRPC method was not found. Singleplayer compatibility fallback is unavailable."); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("Failure: Awake\n" + ex)); } } private void OnDestroy() { try { if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { LogError("Failure: OnDestroy\n" + ex); } } private void BindConfig() { //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Expected O, but got Unknown //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown enabledConfig = ((BaseUnityPlugin)this).Config.Bind("General", "Enabled", true, "Enable this mod.このMODを有効にします"); horizontalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind("Spawn Layout", "HorizontalPlayers", 10, new ConfigDescription("Number of players per horizontal row.横1行に並べる人数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); verticalPlayersConfig = ((BaseUnityPlugin)this).Config.Bind("Spawn Layout", "VerticalPlayers", 2, new ConfigDescription("Number of vertical rows.縦方向の行数", (AcceptableValueBase)(object)new AcceptableValueRange(1, 20), Array.Empty())); startBoostEnabledConfig = ((BaseUnityPlugin)this).Config.Bind("Start Boost", "StartBoostEnabled", true, "Apply a temporary level 3 boost after the countdown.321後に一時的なレベル3ブーストを付与します"); startBoostMultiplierConfig = ((BaseUnityPlugin)this).Config.Bind("Start Boost", "StartBoostMultiplier", 10f, new ConfigDescription("Level 3 boost power multiplier.レベル3ブーストの強さ倍率", (AcceptableValueBase)(object)new AcceptableValueRange(0f, 100f), Array.Empty())); } private static void ScheduleLayoutApplyFromPlayerSpawn() { if (!CanScheduleLayoutApply(out var reason)) { LogWarning("Skipped layout schedule: " + reason + " | " + BuildContextSummary()); return; } if ((Object)(object)pluginInstance == (Object)null) { LogWarning("Skipped layout schedule: plugin instance is null | " + BuildContextSummary()); return; } lastStartBoostArenaRaceInstanceId = 0; layoutScheduleId++; int scheduleId = layoutScheduleId; LogInfo("PlayerSpawn detected. Scheduling Arena Race spawn layout. ScheduleId=" + scheduleId + " | " + BuildContextSummary()); ((MonoBehaviour)pluginInstance).StartCoroutine(DelayedApplyLayoutCoroutine(scheduleId)); } [IteratorStateMachine(typeof(d__31))] private static IEnumerator DelayedApplyLayoutCoroutine(int scheduleId) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new d__31(0) { scheduleId = scheduleId }; } private static void TryApplyLayout(int scheduleId, int attempt) { if (layoutApplyInProgress) { LogWarning("Skipped layout apply: another layout apply is already running. ScheduleId=" + scheduleId); return; } layoutApplyInProgress = true; try { List randomizedPlayers = GetRandomizedPlayers(); if (randomizedPlayers.Count == 0) { LogWarning("Skipped layout apply: no valid players found | ScheduleId=" + scheduleId + " | " + BuildContextSummary()); return; } LayoutPlan layoutPlan = BuildLayoutPlan(randomizedPlayers); if (layoutPlan == null || layoutPlan.Positions.Count == 0) { LogWarning("Skipped layout apply: layout plan is empty | ScheduleId=" + scheduleId + " | Players=" + randomizedPlayers.Count); return; } int num = ApplyLayout(randomizedPlayers, layoutPlan); LogInfo("Applied Arena Race spawn layout by SpawnRPC. ScheduleId=" + scheduleId + ", Attempt=" + attempt + ", Players=" + randomizedPlayers.Count + ", Applied=" + num + ", HorizontalPlayers=" + GetConfigInt(horizontalPlayersConfig, 10) + ", VerticalPlayers=" + GetConfigInt(verticalPlayersConfig, 2) + ", Slots=" + layoutPlan.Positions.Count + " | " + BuildContextSummary()); } catch (Exception ex) { LogError("Failure: TryApplyLayout | ScheduleId=" + scheduleId + " | " + BuildContextSummary() + "\n" + ex); } finally { layoutApplyInProgress = false; } } private static bool CanScheduleLayoutApply(out string reason) { if (enabledConfig == null || !enabledConfig.Value) { reason = "mod is disabled"; return false; } if (!SafeIsMasterClientOrSingleplayer()) { reason = "not host or singleplayer"; return false; } if ((Object)(object)LevelGenerator.Instance == (Object)null) { reason = "LevelGenerator.Instance is null"; return false; } if (!SafeCurrentLevelLooksArenaRace() && !SafeArenaRaceInstanceExists()) { reason = "current level is not Arena Race"; return false; } if (SafeLevelGenerated()) { reason = "level is already generated"; return false; } reason = "ready"; return true; } private static bool CanApplyLayoutNow(out string reason) { if (enabledConfig == null || !enabledConfig.Value) { reason = "mod is disabled"; return false; } if (!SafeIsMasterClientOrSingleplayer()) { reason = "not host or singleplayer"; return false; } if (!SafeCurrentLevelLooksArenaRace() && !SafeArenaRaceInstanceExists()) { reason = "current level is not Arena Race"; return false; } if (!SafeArenaRaceInstanceExists()) { reason = "ArenaRace.instance is null. This is not Arena Race, or Arena Race is not ready yet"; return false; } if (!SafeArenaRaceTrackSpawnOriginExists()) { reason = "ArenaRace.trackSpawnOrigin is null. Arena Race is not ready yet"; return false; } int playerCountSafe = GetPlayerCountSafe(); if (playerCountSafe <= 0) { reason = "no players in GameDirector.PlayerList"; return false; } reason = "ready"; return true; } private static List GetRandomizedPlayers() { List list = new List(); if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return list; } foreach (PlayerAvatar player in GameDirector.instance.PlayerList) { if ((Object)(object)player != (Object)null && (Object)(object)((Component)player).gameObject != (Object)null) { list.Add(player); } } return ShufflePlayers(list); } private static LayoutPlan BuildLayoutPlan(List players) { //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_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) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_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_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_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_0117: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_011b: Unknown result type (might be due to invalid IL or missing references) //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) //IL_0128: Unknown result type (might be due to invalid IL or missing references) //IL_012d: Unknown result type (might be due to invalid IL or missing references) //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0136: Unknown result type (might be due to invalid IL or missing references) //IL_0180: Unknown result type (might be due to invalid IL or missing references) LayoutPlan layoutPlan = new LayoutPlan(); if (players == null || players.Count == 0) { return layoutPlan; } Vector3 val = GetVanillaCenter(players) + Vector3.up * 5f; Vector3 courseForward = GetCourseForward(); Vector3 val2 = Vector3.Cross(Vector3.up, courseForward); Vector3 val3 = ((Vector3)(ref val2)).normalized; if (((Vector3)(ref val3)).sqrMagnitude < 0.0001f) { val3 = Vector3.right; } int num = Mathf.Clamp((horizontalPlayersConfig != null) ? horizontalPlayersConfig.Value : 10, 1, 20); int num2 = Mathf.Clamp((verticalPlayersConfig != null) ? verticalPlayersConfig.Value : 2, 1, 20); int num3 = Mathf.CeilToInt((float)players.Count / (float)Mathf.Max(1, num)); num2 = Mathf.Max(num2, num3); List list = new List(); for (int i = 0; i < num2; i++) { for (int j = 0; j < num; j++) { float num4 = ((float)j - ((float)num - 1f) * 0.5f) * 0.8f; float num5 = 0f - ((float)i * 3f + 10f); Vector3 item = val + val3 * num4 + courseForward * num5; list.Add(item); } } list = ShufflePositions(list); for (int k = 0; k < players.Count && k < list.Count; k++) { layoutPlan.Positions.Add(list[k]); } return layoutPlan; } private static List ShufflePositions(List positions) { //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_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) List list = new List(positions); Random random = new Random(Guid.NewGuid().GetHashCode() ^ Environment.TickCount ^ list.Count); for (int num = list.Count - 1; num > 0; num--) { int index = random.Next(num + 1); Vector3 value = list[num]; list[num] = list[index]; list[index] = value; } return list; } private static int ApplyLayout(List players, LayoutPlan plan) { //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_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_0058: 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) int num = 0; int num2 = Mathf.Min(players.Count, plan.Positions.Count); for (int i = 0; i < num2; i++) { PlayerAvatar val = players[i]; if ((Object)(object)val == (Object)null) { continue; } try { Vector3 position = plan.Positions[i]; Quaternion rotation = ((Component)val).transform.rotation; if (TryApplySpawnPositionByRpc(val, position, rotation, i)) { num++; } } catch (Exception ex) { LogError("Failure: ApplyLayout player index " + i + "\n" + ex); } } return num; } private static bool TryApplySpawnPositionByRpc(PlayerAvatar player, Vector3 position, Quaternion rotation, int index) { //IL_0096: 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_00aa: Unknown result type (might be due to invalid IL or missing references) //IL_00b0: Unknown result type (might be due to invalid IL or missing references) //IL_0135: Unknown result type (might be due to invalid IL or missing references) //IL_013e: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)player == (Object)null) { LogWarning("Skipped SpawnRPC apply: player is null. Index=" + index); return false; } try { if ((Object)(object)GameManager.instance != (Object)null && GameManager.instance.gameMode == 0) { if (playerAvatarSpawnRPCMethod == null) { LogWarning("Skipped SpawnRPC apply: SpawnRPC method was not found. Index=" + index + ", Player=" + GetPlayerDebugName(player)); return false; } playerAvatarSpawnRPCMethod.Invoke(player, new object[3] { position, rotation, (object)default(PhotonMessageInfo) }); return true; } if ((Object)(object)player.photonView == (Object)null) { player.photonView = ((Component)player).GetComponent(); } if ((Object)(object)player.photonView == (Object)null) { LogWarning("Skipped SpawnRPC apply: PhotonView is null. Index=" + index + ", Player=" + GetPlayerDebugName(player)); return false; } player.photonView.RPC("SpawnRPC", (RpcTarget)0, new object[2] { position, rotation }); return true; } catch (Exception ex) { LogError("Failure: TryApplySpawnPositionByRpc | Index=" + index + ", Player=" + GetPlayerDebugName(player) + "\n" + ex); return false; } } private static string GetPlayerDebugName(PlayerAvatar player) { try { if ((Object)(object)player == (Object)null) { return "null"; } if (!string.IsNullOrEmpty(((Object)player).name)) { return ((Object)player).name; } return "Unknown"; } catch { return "Unknown"; } } private static Vector3 GetVanillaCenter(List players) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_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_007d: Unknown result type (might be due to invalid IL or missing references) Vector3 val = Vector3.zero; int num = 0; foreach (PlayerAvatar player in players) { if (!((Object)(object)player == (Object)null)) { val += ((Component)player).transform.position; num++; } } if (num == 0) { return Vector3.zero; } return val / (float)num; } private static Vector3 GetCourseForward() { //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_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_0076: 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 forward = Vector3.forward; try { if ((Object)(object)ArenaRace.instance != (Object)null && (Object)(object)ArenaRace.instance.trackSpawnOrigin != (Object)null) { forward = ArenaRace.instance.trackSpawnOrigin.forward; } } catch { } forward.y = 0f; if (((Vector3)(ref forward)).sqrMagnitude < 0.0001f) { forward = Vector3.forward; } return ((Vector3)(ref forward)).normalized; } private static List ShufflePlayers(List players) { List list = new List(players); Random random = new Random(Guid.NewGuid().GetHashCode() ^ Environment.TickCount); for (int num = list.Count - 1; num > 0; num--) { int index = random.Next(num + 1); PlayerAvatar value = list[num]; list[num] = list[index]; list[index] = value; } return list; } private static void ApplyStartBoostOnce(ArenaRace arenaRace) { if ((Object)(object)arenaRace == (Object)null || enabledConfig == null || !enabledConfig.Value || startBoostEnabledConfig == null || !startBoostEnabledConfig.Value || !SafeIsMasterClientOrSingleplayer()) { return; } if ((Object)(object)arenaRace == (Object)null && !SafeRunIsArena()) { LogWarning("Skipped start boost: Arena Race was not detected | " + BuildContextSummary()); return; } int instanceID = ((Object)arenaRace).GetInstanceID(); if (lastStartBoostArenaRaceInstanceId == instanceID) { return; } lastStartBoostArenaRaceInstanceId = instanceID; List arenaRaceVehicles = GetArenaRaceVehicles(arenaRace); if (arenaRaceVehicles.Count == 0) { LogWarning("Skipped start boost: no Arena Race vehicles found | " + BuildContextSummary()); return; } int num = 0; foreach (ItemVehicle item in arenaRaceVehicles) { if (ApplyStartBoostToVehicle(arenaRace, item)) { num++; } } LogInfo("Applied start boost. Vehicles=" + arenaRaceVehicles.Count + ", Applied=" + num + ", Multiplier=" + GetConfigFloat(startBoostMultiplierConfig, 10f)); } private static List GetArenaRaceVehicles(ArenaRace arenaRace) { List list = new List(); if ((Object)(object)arenaRace == (Object)null) { return list; } try { if (arenaRacePlayerVehicleMapField != null) { object value = arenaRacePlayerVehicleMapField.GetValue(arenaRace); if (value is Dictionary dictionary) { foreach (KeyValuePair item in dictionary) { if ((Object)(object)item.Value != (Object)null && !list.Contains(item.Value)) { list.Add(item.Value); } } } } } catch { } try { if (list.Count == 0 && arenaRaceVehiclesField != null) { object value2 = arenaRaceVehiclesField.GetValue(arenaRace); if (value2 is List list2) { foreach (ItemVehicle item2 in list2) { if ((Object)(object)item2 != (Object)null && !list.Contains(item2)) { list.Add(item2); } } } } } catch { } return list; } private static bool ApplyStartBoostToVehicle(ArenaRace arenaRace, ItemVehicle vehicle) { //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0092: 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_00b7: 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_0127: 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) if ((Object)(object)arenaRace == (Object)null || (Object)(object)vehicle == (Object)null) { return false; } if (itemVehicleOverrideYawMethod == null) { return false; } float driftBoostLevel3ForwardBoost = vehicle.driftBoostLevel3ForwardBoost; float driftBoostLevel3SpeedBoostMultiplier = vehicle.driftBoostLevel3SpeedBoostMultiplier; try { float num = ((startBoostMultiplierConfig != null) ? startBoostMultiplierConfig.Value : 10f); float num2 = Mathf.Clamp(num, 0f, 100f); vehicle.driftBoostLevel3ForwardBoost = driftBoostLevel3ForwardBoost * num2; vehicle.driftBoostLevel3SpeedBoostMultiplier = driftBoostLevel3SpeedBoostMultiplier * num2; Vector3 startBoostForward = GetStartBoostForward(arenaRace, vehicle); float num3 = Mathf.Asin(Mathf.Clamp(startBoostForward.y, -1f, 1f)) * 57.29578f; Vector3 val = startBoostForward; val.y = 0f; if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = ((Component)vehicle).transform.forward; val.y = 0f; } if (((Vector3)(ref val)).sqrMagnitude < 0.0001f) { val = Vector3.forward; } ((Vector3)(ref val)).Normalize(); itemVehicleOverrideYawMethod.Invoke(vehicle, new object[3] { val, 0.25f, 3 }); if (itemVehicleOverridePitchMethod != null) { itemVehicleOverridePitchMethod.Invoke(vehicle, new object[2] { num3, 1f }); } return true; } catch (Exception ex) { LogError("Failure: ApplyStartBoostToVehicle\n" + ex); return false; } finally { vehicle.driftBoostLevel3ForwardBoost = driftBoostLevel3ForwardBoost; vehicle.driftBoostLevel3SpeedBoostMultiplier = driftBoostLevel3SpeedBoostMultiplier; } } private static Vector3 GetStartBoostForward(ArenaRace arenaRace, ItemVehicle vehicle) { //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_0057: 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_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) try { if ((Object)(object)arenaRace != (Object)null && (Object)(object)arenaRace.trackSpawnOrigin != (Object)null) { return arenaRace.trackSpawnOrigin.forward; } if ((Object)(object)vehicle != (Object)null) { return ((Component)vehicle).transform.forward; } } catch { } return Vector3.forward; } private static bool SafeIsMasterClientOrSingleplayer() { try { return SemiFunc.IsMasterClientOrSingleplayer(); } catch { return false; } } private static bool SafeCurrentLevelLooksArenaRace() { try { if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null) { return false; } string name = ((Object)RunManager.instance.levelCurrent).name; if (string.IsNullOrEmpty(name)) { return false; } return name.IndexOf("Arena Race", StringComparison.OrdinalIgnoreCase) >= 0; } catch { return false; } } private static string SafeCurrentLevelName() { try { if ((Object)(object)RunManager.instance == (Object)null || (Object)(object)RunManager.instance.levelCurrent == (Object)null) { return "null"; } return ((Object)RunManager.instance.levelCurrent).name ?? "null"; } catch { return "Unknown"; } } private static bool SafeArenaRaceInstanceExists() { try { return (Object)(object)ArenaRace.instance != (Object)null; } catch { return false; } } private static bool SafeArenaRaceTrackSpawnOriginExists() { try { return (Object)(object)ArenaRace.instance != (Object)null && (Object)(object)ArenaRace.instance.trackSpawnOrigin != (Object)null; } catch { return false; } } private static bool SafeRunIsArena() { try { return SemiFunc.RunIsArena(); } catch { return false; } } private static bool SafeLevelGenerated() { try { return (Object)(object)LevelGenerator.Instance != (Object)null && LevelGenerator.Instance.Generated; } catch { return false; } } private static string BuildContextSummary() { bool configBool = GetConfigBool(enabledConfig, defaultValue: false); bool flag = SafeIsMasterClientOrSingleplayer(); bool flag2 = (Object)(object)LevelGenerator.Instance != (Object)null; bool flag3 = SafeLevelGenerated(); string text = SafeCurrentLevelName(); bool flag4 = SafeCurrentLevelLooksArenaRace(); bool flag5 = SafeArenaRaceInstanceExists(); bool flag6 = SafeArenaRaceTrackSpawnOriginExists(); bool flag7 = SafeRunIsArena(); int playerCountSafe = GetPlayerCountSafe(); int spawnPointCountSafe = GetSpawnPointCountSafe(); bool flag8 = SafeTruckSafetySpawnPointExists(); return "Enabled=" + configBool + ", HostOrSingleplayer=" + flag + ", LevelGenerator=" + flag2 + ", LevelGenerated=" + flag3 + ", CurrentLevel=" + text + ", CurrentLevelIsArenaRace=" + flag4 + ", ArenaRaceInstance=" + flag5 + ", ArenaRaceTrackSpawnOrigin=" + flag6 + ", RunIsArena=" + flag7 + ", PlayerCount=" + playerCountSafe + ", SpawnPointCount=" + spawnPointCountSafe + ", TruckSafetySpawnPoint=" + flag8; } private static int GetPlayerCountSafe() { try { if ((Object)(object)GameDirector.instance == (Object)null || GameDirector.instance.PlayerList == null) { return 0; } return GameDirector.instance.PlayerList.Count; } catch { return -1; } } private static int GetSpawnPointCountSafe() { try { SpawnPoint[] array = Object.FindObjectsOfType(); return (array != null) ? array.Length : 0; } catch { return -1; } } private static bool SafeTruckSafetySpawnPointExists() { try { return (Object)(object)TruckSafetySpawnPoint.instance != (Object)null; } catch { return false; } } private static bool GetConfigBool(ConfigEntry config, bool defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static int GetConfigInt(ConfigEntry config, int defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static float GetConfigFloat(ConfigEntry config, float defaultValue) { try { return config?.Value ?? defaultValue; } catch { return defaultValue; } } private static void LogInfo(string message) { if (logSource != null) { logSource.LogInfo((object)message); } } private static void LogWarning(string message) { if (logSource != null) { logSource.LogWarning((object)message); } } private static void LogError(string message) { if (logSource != null) { logSource.LogError((object)message); } } } }