Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of ValheimBattleRoyale v0.3.14
ValheimBattleRoyale.dll
Decompiled 7 hours agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using BepInEx; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("ValheimBattleRoyale")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ValheimBattleRoyale")] [assembly: AssemblyCopyright("Copyright © 2026")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("75C3A508-4CBA-494A-B957-1B0C9E976E0B")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyVersion("1.0.0.0")] namespace ValheimBattleRoyale; [BepInPlugin("com.xtasy.ValheimBattleRoyale", "Valheim Battle Royale", "0.3.14")] public sealed class ValheimBattleRoyalePlugin : BaseUnityPlugin { public const string GUID = "com.xtasy.ValheimBattleRoyale"; public const string NAME = "Valheim Battle Royale"; public const string VERSION = "0.3.14"; internal static ValheimBattleRoyalePlugin Instance; internal static ManualLogSource Log; internal ConfigEntry<KeyboardShortcut> StartHotkey; internal ConfigEntry<float> StartCountdown; internal ConfigEntry<float> InitialRadius; internal ConfigEntry<float> NextRadiusMultiplier; internal ConfigEntry<float> MinimumRadius; internal ConfigEntry<float> WaitBeforeShrink; internal ConfigEntry<float> ShrinkDuration; internal ConfigEntry<float> OutsideDamage; internal ConfigEntry<float> DamageInterval; internal ConfigEntry<bool> RequireNextInsideCurrent; internal ConfigEntry<bool> ShowHud; private Harmony _harmony; private FileSystemWatcher _watcher; private float _reloadAt = -1f; private float _nextDamageAt; private double _nextServerDamageAt; private Texture2D _whiteTexture; private bool _rpcRegistered; private GameObject _hudRoot; private TextMeshProUGUI _hudTitle; private TextMeshProUGUI _hudTimer; private TextMeshProUGUI _hudDanger; private static TMP_FontAsset _valheimNorseBold; private static bool _valheimNorseBoldSearched; private static string _selectedLanguage; private static float _nextLanguageProbeAt; private const string RpcRequest = "XBR_Request"; private const string RpcState = "XBR_State"; private const string RpcSnapshotRequest = "XBR_SnapshotRequest"; private const string RpcZoneDamage = "XBR_ZoneDamage"; private static StatusEffect _zoneFireVisual; private void Awake() { //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0032: 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_0057: Expected O, but got Unknown Instance = this; Log = ((BaseUnityPlugin)this).Logger; BindConfig(); SetupConfigWatcher(); _whiteTexture = new Texture2D(1, 1); _whiteTexture.SetPixel(0, 0, Color.white); _whiteTexture.Apply(); _harmony = new Harmony("com.xtasy.ValheimBattleRoyale"); _harmony.PatchAll(); Log.LogInfo((object)"Valheim Battle Royale 0.3.14 loaded."); } private void OnDestroy() { if ((Object)(object)_hudRoot != (Object)null) { Object.Destroy((Object)(object)_hudRoot); _hudRoot = null; } if ((Object)(object)_whiteTexture != (Object)null) { Object.Destroy((Object)(object)_whiteTexture); _whiteTexture = null; } if (_watcher != null) { _watcher.Dispose(); _watcher = null; } if (_harmony != null) { _harmony.UnpatchSelf(); } Instance = null; } private void BindConfig() { //IL_001b: Unknown result type (might be due to invalid IL or missing references) StartHotkey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Controls", "StartHotkey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), "Start/stop match request from an admin client."); StartCountdown = ((BaseUnityPlugin)this).Config.Bind<float>("Match", "StartCountdown", 10f, "Seconds between admin start and actual match start. Damage is disabled during this countdown."); InitialRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Zone", "InitialRadius", 3000f, "Initial safe-zone radius used by Shift+LeftClick / br zone when radius is omitted."); NextRadiusMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Zone", "NextRadiusMultiplier", 0.5f, "Next-zone radius as a multiplier of the current radius. 0.5 = 50%. Used when an explicit radius is not supplied."); MinimumRadius = ((BaseUnityPlugin)this).Config.Bind<float>("Zone", "MinimumRadius", 25f, "Minimum automatically calculated next-zone radius."); WaitBeforeShrink = ((BaseUnityPlugin)this).Config.Bind<float>("Zone", "WaitBeforeShrink", 300f, "Seconds from assigning the next safe zone until shrinking starts."); ShrinkDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Zone", "ShrinkDuration", 180f, "Seconds used to move/shrink from current zone to next zone."); RequireNextInsideCurrent = ((BaseUnityPlugin)this).Config.Bind<bool>("Zone", "RequireNextZoneInsideCurrent", true, "Reject a next circle that is not fully inside the current circle."); OutsideDamage = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "OutsideDamage", 10f, "Direct health removed per tick outside the current safe zone. Bypasses armor, blocking and elemental resistances."); DamageInterval = ((BaseUnityPlugin)this).Config.Bind<float>("Damage", "DamageInterval", 2f, "Seconds between damage ticks."); ShowHud = ((BaseUnityPlugin)this).Config.Bind<bool>("UI", "ShowHud", true, "Show match/zone/timer information on screen."); } private void SetupConfigWatcher() { string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath; _watcher = new FileSystemWatcher(Path.GetDirectoryName(configFilePath) ?? Paths.ConfigPath, Path.GetFileName(configFilePath)); _watcher.NotifyFilter = NotifyFilters.Size | NotifyFilters.LastWrite | NotifyFilters.CreationTime; _watcher.Changed += delegate { _reloadAt = Time.realtimeSinceStartup + 0.35f; }; _watcher.Created += delegate { _reloadAt = Time.realtimeSinceStartup + 0.35f; }; _watcher.Renamed += delegate { _reloadAt = Time.realtimeSinceStartup + 0.35f; }; _watcher.EnableRaisingEvents = true; } private unsafe void Update() { //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_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_00e4: 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) UpdateTmpHud(); if (_reloadAt > 0f && Time.realtimeSinceStartup >= _reloadAt) { _reloadAt = -1f; try { ((BaseUnityPlugin)this).Config.Reload(); Log.LogInfo((object)"Config reloaded on the fly."); } catch (Exception ex) { Log.LogError((object)("Config reload failed: " + ex)); } } TryRegisterRpc(); if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null) { return; } if ((Object)(object)Player.m_localPlayer != (Object)null && !IsTextInputActive()) { KeyboardShortcut value = StartHotkey.Value; if (((KeyboardShortcut)(ref value)).IsDown()) { ManualLogSource log = Log; value = StartHotkey.Value; log.LogInfo((object)("Start hotkey pressed: " + ((object)(*(KeyboardShortcut*)(&value))/*cast due to .constrained prefix*/).ToString())); SendRequest("toggle"); } } if (ZNet.instance.IsServer()) { ApplyServerDamage(); } else { ApplyLocalZoneVisual(); } } private void TryRegisterRpc() { if (!_rpcRegistered && ZRoutedRpc.instance != null) { ZRoutedRpc.instance.Register<ZPackage>("XBR_Request", (Action<long, ZPackage>)RPC_Request); ZRoutedRpc.instance.Register<ZPackage>("XBR_State", (Action<long, ZPackage>)RPC_State); ZRoutedRpc.instance.Register("XBR_SnapshotRequest", (Action<long>)RPC_SnapshotRequest); ZRoutedRpc.instance.Register<float>("XBR_ZoneDamage", (Action<long, float>)RPC_ZoneDamage); _rpcRegistered = true; if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer()) { ZRoutedRpc.instance.InvokeRoutedRPC("XBR_SnapshotRequest", Array.Empty<object>()); } } } internal void ResetRpcRegistration() { _rpcRegistered = false; } private static bool IsTextInputActive() { if ((Object)(object)Console.instance != (Object)null && Console.IsVisible()) { return true; } if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus()) { return true; } return false; } internal void SendRequest(string action, Vector3 pos = default(Vector3), float radius = 0f) { //IL_0038: 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_0065: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown //IL_0073: Unknown result type (might be due to invalid IL or missing references) if (ZRoutedRpc.instance == null) { Log.LogWarning((object)("Cannot send BR request '" + action + "': ZRoutedRpc is not ready.")); return; } Log.LogInfo((object)$"Sending BR request: action={action}, pos=({pos.x:F0},{pos.z:F0}), radius={radius:F0}"); ZPackage val = new ZPackage(); val.Write(action); val.Write(pos); val.Write(radius); ZRoutedRpc.instance.InvokeRoutedRPC("XBR_Request", new object[1] { val }); } private void RPC_Request(long sender, ZPackage pkg) { //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_0073: 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_01be: Unknown result type (might be due to invalid IL or missing references) //IL_01b4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer()) { return; } if (!IsAuthorized(sender)) { Log.LogWarning((object)("Rejected Battle Royale control request from non-admin peer " + sender)); return; } string text = pkg.ReadString(); Vector3 val = pkg.ReadVector3(); float num = pkg.ReadSingle(); Log.LogInfo((object)$"Server received BR request from {sender}: action={text}, pos=({val.x:F0},{val.z:F0}), radius={num:F0}"); switch (text) { case "toggle": if (ZoneState.Running || ZoneState.Starting) { StopMatch(); } else { StartMatch(); } break; case "start": StartMatch(); break; case "stop": StopMatch(); break; case "zone": SetCurrentZone(val, num); break; case "next": SetNextZone(val, num); break; case "cancelnext": ZoneState.HasNext = false; ZoneState.Phase = ZonePhase.Idle; break; case "cancelzone": CancelAssignedZone(); break; } BroadcastState(); } private void StartMatch() { if (!ZoneState.HasCurrent) { Log.LogWarning((object)"Cannot start Battle Royale: current safe zone is not set."); return; } ZoneState.Running = false; ZoneState.Starting = true; ZoneState.MatchStartAt = ServerTime() + (double)Mathf.Max(0f, StartCountdown.Value); Log.LogInfo((object)$"Battle Royale start countdown: {Mathf.Max(0f, StartCountdown.Value):F0}s"); } private void StopMatch() { ZoneState.Running = false; ZoneState.Starting = false; ZoneState.Phase = ZonePhase.Idle; Log.LogInfo((object)"Battle Royale stopped."); } private bool IsAuthorized(long sender) { if (sender == ZNet.GetUID()) { return true; } ZNetPeer peer = ZNet.instance.GetPeer(sender); if (peer == null || peer.m_rpc == null || peer.m_rpc.GetSocket() == null) { return false; } string hostName = peer.m_rpc.GetSocket().GetHostName(); if (!(AccessTools.Field(typeof(ZNet), "m_adminList")?.GetValue(ZNet.instance) is IEnumerable enumerable)) { return false; } foreach (object item in enumerable) { if (item != null && string.Equals(item.ToString(), hostName, StringComparison.OrdinalIgnoreCase)) { return true; } } return false; } private void CancelAssignedZone() { //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) if (ZoneState.Phase == ZonePhase.Shrinking) { Log.LogWarning((object)"Cannot cancel a zone while shrinking is in progress."); } else if (ZoneState.HasNext) { if (ZoneState.Phase == ZonePhase.Shrinking) { ZoneState.CurrentCenter = GetEffectiveCurrentCenter(); ZoneState.CurrentRadius = GetEffectiveCurrentRadius(); } ZoneState.HasNext = false; ZoneState.Phase = ZonePhase.Idle; Log.LogInfo((object)"Next zone cancelled."); } else if (ZoneState.HasCurrent) { ZoneState.HasCurrent = false; ZoneState.HasNext = false; ZoneState.Phase = ZonePhase.Idle; ZoneState.Running = false; ZoneState.Starting = false; Log.LogInfo((object)"Current/start zone cancelled."); } } private void SetCurrentZone(Vector3 pos, float radius) { //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_001b: 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_0057: Unknown result type (might be due to invalid IL or missing references) if (radius <= 0f) { radius = InitialRadius.Value; } ZoneState.CurrentCenter = Flat(pos); ZoneState.CurrentRadius = Mathf.Max(1f, radius); ZoneState.HasCurrent = true; ZoneState.HasNext = false; ZoneState.Phase = ZonePhase.Idle; Log.LogInfo((object)$"Current zone: X={pos.x:F0} Z={pos.z:F0} R={radius:F0}"); } private void SetNextZone(Vector3 pos, float radius) { //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_009c: 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_00ed: 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_013d: 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_01b6: 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_01fa: Unknown result type (might be due to invalid IL or missing references) //IL_01ff: Unknown result type (might be due to invalid IL or missing references) //IL_0223: Unknown result type (might be due to invalid IL or missing references) //IL_022e: Unknown result type (might be due to invalid IL or missing references) if (!ZoneState.HasCurrent) { Log.LogWarning((object)"Set current zone first."); return; } if (ZoneState.Phase == ZonePhase.Shrinking) { Log.LogWarning((object)"Cannot assign or move the next zone while shrinking is in progress."); return; } bool hasNext = ZoneState.HasNext; if (radius <= 0f) { if (hasNext) { radius = ZoneState.NextRadius; } else { float num = Mathf.Clamp(NextRadiusMultiplier.Value, 0.01f, 1f); radius = Mathf.Max(Mathf.Max(1f, MinimumRadius.Value), ZoneState.CurrentRadius * num); } } else { radius = Mathf.Max(1f, radius); } pos = Flat(pos); if (RequireNextInsideCurrent.Value) { float num2 = DistanceXZ(ZoneState.CurrentCenter, pos); if (num2 + radius > ZoneState.CurrentRadius) { Log.LogWarning((object)$"Next zone rejected: distance {num2:F0} + radius {radius:F0} > current radius {ZoneState.CurrentRadius:F0}."); return; } } ZoneState.NextCenter = pos; ZoneState.NextRadius = radius; ZoneState.HasNext = true; if (!hasNext) { ZoneState.Phase = ZonePhase.Waiting; ZoneState.PhaseStartedAt = ServerTime(); ZoneState.WaitSecondsAtAssignment = Mathf.Max(0f, WaitBeforeShrink.Value); Log.LogInfo((object)$"Next zone: X={pos.x:F0} Z={pos.z:F0} R={radius:F0}; wait={ZoneState.WaitSecondsAtAssignment:F0}s"); } else if (ZoneState.Phase == ZonePhase.Waiting) { ZoneState.PhaseStartedAt = ServerTime(); ZoneState.WaitSecondsAtAssignment = Mathf.Max(0f, WaitBeforeShrink.Value); Log.LogInfo((object)$"Next zone moved: X={pos.x:F0} Z={pos.z:F0} R={radius:F0}; wait timer restarted ({ZoneState.WaitSecondsAtAssignment:F0}s)"); } else if (ZoneState.Phase == ZonePhase.Shrinking) { ZoneState.ShrinkFromCenter = GetEffectiveCurrentCenter(); ZoneState.ShrinkFromRadius = GetEffectiveCurrentRadius(); ZoneState.PhaseStartedAt = ServerTime(); Log.LogInfo((object)$"Next zone moved during shrinking: X={pos.x:F0} Z={pos.z:F0} R={radius:F0}; shrink timer restarted"); } } private void FixedUpdate() { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00f5: 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_009c: 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_0122: 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) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !ZoneState.HasCurrent) { return; } double num = ServerTime(); if (ZoneState.Starting && num >= ZoneState.MatchStartAt) { ZoneState.Starting = false; ZoneState.Running = true; Log.LogInfo((object)"Battle Royale started."); BroadcastState(); } if (!ZoneState.Running) { return; } if (ZoneState.Phase == ZonePhase.Waiting && ZoneState.HasNext) { if (num - ZoneState.PhaseStartedAt >= (double)Mathf.Max(0f, WaitBeforeShrink.Value)) { ZoneState.Phase = ZonePhase.Shrinking; ZoneState.PhaseStartedAt = num; ZoneState.ShrinkFromCenter = ZoneState.CurrentCenter; ZoneState.ShrinkFromRadius = ZoneState.CurrentRadius; BroadcastState(); } } else if (ZoneState.Phase == ZonePhase.Shrinking && ZoneState.HasNext) { float num2 = Mathf.Max(0.01f, ShrinkDuration.Value); float num3 = Mathf.Clamp01((float)((num - ZoneState.PhaseStartedAt) / (double)num2)); ZoneState.CurrentCenter = Vector3.Lerp(ZoneState.ShrinkFromCenter, ZoneState.NextCenter, num3); ZoneState.CurrentRadius = Mathf.Lerp(ZoneState.ShrinkFromRadius, ZoneState.NextRadius, num3); if (num3 >= 1f) { ZoneState.CurrentCenter = ZoneState.NextCenter; ZoneState.CurrentRadius = ZoneState.NextRadius; ZoneState.HasNext = false; ZoneState.Phase = ZonePhase.Idle; BroadcastState(); } } } private void ApplyServerDamage() { //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_00c9: 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) if ((Object)(object)ZNet.instance == (Object)null || !ZNet.instance.IsServer() || !ZoneState.Running || ZoneState.Starting || !ZoneState.HasCurrent) { return; } double num = ServerTime(); if (num < _nextServerDamageAt) { return; } _nextServerDamageAt = num + Math.Max(0.1, DamageInterval.Value); float num2 = Mathf.Max(0f, OutsideDamage.Value); if (num2 <= 0f) { return; } Vector3 effectiveCurrentCenter = GetEffectiveCurrentCenter(); float effectiveCurrentRadius = GetEffectiveCurrentRadius(); List<Player> allPlayers = Player.GetAllPlayers(); if (allPlayers == null) { return; } foreach (Player item in allPlayers) { if (!((Object)(object)item == (Object)null) && !((Character)item).IsDead() && !(DistanceXZ(((Component)item).transform.position, effectiveCurrentCenter) <= effectiveCurrentRadius)) { SendZoneDamageToOwner(item, num2); } } } private static void SendZoneDamageToOwner(Player player, float damage) { if (!((Object)(object)player == (Object)null) && !(damage <= 0f) && ZRoutedRpc.instance != null) { long playerOwnerPeerId = GetPlayerOwnerPeerId(player); if (playerOwnerPeerId == 0L) { Log.LogWarning((object)"Cannot apply zone damage: player owner peer ID was not resolved."); return; } ZRoutedRpc.instance.InvokeRoutedRPC(playerOwnerPeerId, "XBR_ZoneDamage", new object[1] { damage }); } } private static long GetPlayerOwnerPeerId(Player player) { try { object obj = AccessTools.Field(typeof(Character), "m_nview")?.GetValue(player); if (obj == null) { return 0L; } object obj2 = AccessTools.Method(obj.GetType(), "GetZDO", Type.EmptyTypes, (Type[])null)?.Invoke(obj, null); if (obj2 == null) { return 0L; } object obj3 = AccessTools.Method(obj2.GetType(), "GetOwner", Type.EmptyTypes, (Type[])null)?.Invoke(obj2, null); return (obj3 == null) ? 0 : Convert.ToInt64(obj3, CultureInfo.InvariantCulture); } catch (Exception ex) { Log.LogWarning((object)("Failed to resolve player owner for zone damage: " + ex.Message)); return 0L; } } private void RPC_ZoneDamage(long sender, float damage) { if ((Object)(object)ZNet.instance == (Object)null || ZRoutedRpc.instance == null || (Object)(object)Player.m_localPlayer == (Object)null) { return; } if (!ZNet.instance.IsServer()) { ZNetPeer serverPeer = ZNet.instance.GetServerPeer(); if (serverPeer == null || sender != serverPeer.m_uid) { Log.LogWarning((object)("Rejected forged Battle Royale zone damage RPC from peer " + sender)); return; } } ApplyAuthorizedZoneDamage(Player.m_localPlayer, Mathf.Max(0f, damage)); } private static void ApplyAuthorizedZoneDamage(Player player, float damage) { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown //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_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) if (!((Object)(object)player == (Object)null) && !(damage <= 0f) && !((Character)player).IsDead()) { float health = ((Character)player).GetHealth(); if (health > damage) { ((Character)player).SetHealth(health - damage); return; } HitData val = new HitData(); val.m_damage.m_damage = Mathf.Max(1f, health + damage); val.m_point = ((Component)player).transform.position; val.m_dir = Vector3.zero; val.m_dodgeable = false; val.m_blockable = false; ((Character)player).Damage(val); } } private void ApplyLocalZoneVisual() { //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_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) if (ZoneState.Running && !ZoneState.Starting && ZoneState.HasCurrent && !((Object)(object)Player.m_localPlayer == (Object)null) && !(Time.time < _nextDamageAt)) { _nextDamageAt = Time.time + Mathf.Max(0.1f, DamageInterval.Value); Vector3 effectiveCurrentCenter = GetEffectiveCurrentCenter(); float effectiveCurrentRadius = GetEffectiveCurrentRadius(); if (!(DistanceXZ(((Component)Player.m_localPlayer).transform.position, effectiveCurrentCenter) <= effectiveCurrentRadius)) { EnsureZoneFireVisual(Player.m_localPlayer); } } } private static void EnsureZoneFireVisual(Player player) { if ((Object)(object)player == (Object)null || ((Character)player).GetSEMan() == null || (Object)(object)ObjectDB.instance == (Object)null) { return; } try { if ((Object)(object)_zoneFireVisual == (Object)null) { StatusEffect statusEffect = ObjectDB.instance.GetStatusEffect(StringExtensionMethods.GetStableHashCode("Burning")); if ((Object)(object)statusEffect == (Object)null) { Log.LogWarning((object)"Vanilla Burning status effect was not found; zone fire visual is unavailable."); return; } _zoneFireVisual = ScriptableObject.CreateInstance<StatusEffect>(); ((Object)_zoneFireVisual).name = "BR_ZoneFireVisual"; _zoneFireVisual.m_name = ""; _zoneFireVisual.m_tooltip = ""; _zoneFireVisual.m_ttl = Mathf.Max(0.5f, Instance.DamageInterval.Value + 0.35f); _zoneFireVisual.m_startEffects = statusEffect.m_startEffects; _zoneFireVisual.m_stopEffects = statusEffect.m_stopEffects; } _zoneFireVisual.m_ttl = Mathf.Max(0.5f, Instance.DamageInterval.Value + 0.35f); ((Character)player).GetSEMan().AddStatusEffect(_zoneFireVisual, true, 0, 0f, (short)(-1)); } catch (Exception ex) { Log.LogWarning((object)("Failed to apply cosmetic zone fire: " + ex.Message)); } } private void RPC_SnapshotRequest(long sender) { if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer()) { SendState(sender); } } private void BroadcastState() { SendState(0L); } private void SendState(long target) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Expected O, but got Unknown if (ZRoutedRpc.instance != null) { ZPackage val = new ZPackage(); ZoneState.Write(val); ZRoutedRpc.instance.InvokeRoutedRPC(target, "XBR_State", new object[1] { val }); } } private void RPC_State(long sender, ZPackage pkg) { if (!((Object)(object)ZNet.instance != (Object)null) || !ZNet.instance.IsServer() || sender == ZNet.GetUID()) { ZoneState.Read(pkg); } } internal static double ServerTime() { if (!((Object)(object)ZNet.instance != (Object)null)) { return Time.timeAsDouble; } return ZNet.instance.GetTimeSeconds(); } internal static float DistanceXZ(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_000d: 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) float num = a.x - b.x; float num2 = a.z - b.z; return Mathf.Sqrt(num * num + num2 * num2); } internal static Vector3 Flat(Vector3 v) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) v.y = 0f; return v; } internal Vector3 GetEffectiveCurrentCenter() { //IL_000f: 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_004b: Unknown result type (might be due to invalid IL or missing references) if (ZoneState.Phase != ZonePhase.Shrinking || !ZoneState.HasNext) { return ZoneState.CurrentCenter; } float num = Mathf.Max(0.01f, ShrinkDuration.Value); float num2 = Mathf.Clamp01((float)((ServerTime() - ZoneState.PhaseStartedAt) / (double)num)); return Vector3.Lerp(ZoneState.ShrinkFromCenter, ZoneState.NextCenter, num2); } internal float GetEffectiveCurrentRadius() { if (ZoneState.Phase != ZonePhase.Shrinking || !ZoneState.HasNext) { return ZoneState.CurrentRadius; } float num = Mathf.Max(0.01f, ShrinkDuration.Value); float num2 = Mathf.Clamp01((float)((ServerTime() - ZoneState.PhaseStartedAt) / (double)num)); return Mathf.Lerp(ZoneState.ShrinkFromRadius, ZoneState.NextRadius, num2); } private static bool IsRussianLanguage() { string selectedGameLanguage = GetSelectedGameLanguage(); if (!string.IsNullOrEmpty(selectedGameLanguage)) { if (!selectedGameLanguage.Equals("Russian", StringComparison.OrdinalIgnoreCase) && !selectedGameLanguage.Equals("Русский", StringComparison.OrdinalIgnoreCase)) { return selectedGameLanguage.StartsWith("ru", StringComparison.OrdinalIgnoreCase); } return true; } return false; } private static string GetSelectedGameLanguage() { //IL_0222: Unknown result type (might be due to invalid IL or missing references) //IL_0227: Unknown result type (might be due to invalid IL or missing references) if (!string.IsNullOrEmpty(_selectedLanguage) && Time.realtimeSinceStartup < _nextLanguageProbeAt) { return _selectedLanguage; } _nextLanguageProbeAt = Time.realtimeSinceStartup + 2f; try { Type[] types = typeof(Player).Assembly.GetTypes(); foreach (Type type in types) { MethodInfo method = type.GetMethod("GetSelectedLanguage", BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null); if (method == null || method.ReturnType != typeof(string)) { continue; } if (method.IsStatic) { string text = method.Invoke(null, null) as string; if (!string.IsNullOrEmpty(text)) { return _selectedLanguage = text; } continue; } object obj = null; FieldInfo[] fields = type.GetFields(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo in fields) { if (type.IsAssignableFrom(fieldInfo.FieldType)) { obj = fieldInfo.GetValue(null); if (obj != null) { break; } } } if (obj == null) { PropertyInfo[] properties = type.GetProperties(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (PropertyInfo propertyInfo in properties) { if (!type.IsAssignableFrom(propertyInfo.PropertyType) || propertyInfo.GetIndexParameters().Length != 0) { continue; } try { obj = propertyInfo.GetValue(null, null); if (obj != null) { break; } } catch { } } } if (obj == null && typeof(Object).IsAssignableFrom(type)) { Object[] array = Resources.FindObjectsOfTypeAll(type); if (array != null && array.Length != 0) { obj = array[0]; } } if (obj != null) { string text2 = method.Invoke(obj, null) as string; if (!string.IsNullOrEmpty(text2)) { return _selectedLanguage = text2; } } } } catch (Exception ex) { ManualLogSource log = Log; if (log != null) { log.LogDebug((object)("Valheim language API lookup failed: " + ex.Message)); } } string text3 = PlayerPrefs.GetString("language", ""); if (string.IsNullOrEmpty(text3)) { text3 = PlayerPrefs.GetString("Language", ""); } if (!string.IsNullOrEmpty(text3)) { return _selectedLanguage = text3; } return _selectedLanguage = ((object)Application.systemLanguage/*cast due to .constrained prefix*/).ToString(); } private static string Localize(string english, string russian) { if (!IsRussianLanguage()) { return english; } return russian; } private static TMP_FontAsset GetValheimNorseBold() { if ((Object)(object)_valheimNorseBold != (Object)null) { return _valheimNorseBold; } if (_valheimNorseBoldSearched) { return null; } _valheimNorseBoldSearched = true; try { TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>(); foreach (TMP_FontAsset val in array) { if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(((Object)val).name) && ((Object)val).name.Equals("Valheim-Norsebold", StringComparison.OrdinalIgnoreCase)) { _valheimNorseBold = val; ManualLogSource log = Log; if (log != null) { log.LogInfo((object)("TMP HUD font: " + ((Object)val).name)); } return val; } } ManualLogSource log2 = Log; if (log2 != null) { log2.LogWarning((object)"TMP font asset Valheim-Norsebold was not found."); } } catch (Exception ex) { ManualLogSource log3 = Log; if (log3 != null) { log3.LogWarning((object)("Failed to locate TMP Valheim-Norsebold: " + ex.Message)); } } return null; } private void EnsureTmpHud() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_001a: Expected O, but got Unknown //IL_00bc: Unknown result type (might be due to invalid IL or missing references) if (!((Object)(object)_hudRoot != (Object)null)) { GameObject val = new GameObject("XBR_TMP_HUD"); Object.DontDestroyOnLoad((Object)(object)val); Canvas obj = val.AddComponent<Canvas>(); obj.renderMode = (RenderMode)0; obj.sortingOrder = 200; val.AddComponent<CanvasScaler>(); ((Behaviour)val.AddComponent<GraphicRaycaster>()).enabled = false; _hudRoot = val; _hudTitle = CreateTmpText("Title", val.transform, 18f); _hudTimer = CreateTmpText("Timer", val.transform, 18f); _hudDanger = CreateTmpText("Danger", val.transform, 25f); ((Graphic)_hudDanger).color = new Color(1f, 0.35f, 0.15f, 1f); } } private static TextMeshProUGUI CreateTmpText(string name, Transform parent, float size) { //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_003d: Unknown result type (might be due to invalid IL or missing references) GameObject val = new GameObject(name); val.transform.SetParent(parent, false); TextMeshProUGUI obj = val.AddComponent<TextMeshProUGUI>(); ((TMP_Text)obj).font = GetValheimNorseBold(); ((TMP_Text)obj).fontSize = size; ((TMP_Text)obj).fontStyle = (FontStyles)1; ((TMP_Text)obj).alignment = (TextAlignmentOptions)514; ((Graphic)obj).color = Color.white; ((Graphic)obj).raycastTarget = false; ((TMP_Text)obj).textWrappingMode = (TextWrappingModes)0; return obj; } private static void SetScreenRect(RectTransform rt, Rect screenRect) { //IL_0001: 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_0017: 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_0050: Unknown result type (might be due to invalid IL or missing references) rt.anchorMin = Vector2.zero; rt.anchorMax = Vector2.zero; rt.pivot = Vector2.zero; rt.anchoredPosition = new Vector2(((Rect)(ref screenRect)).x, (float)Screen.height - ((Rect)(ref screenRect)).yMax); rt.sizeDelta = new Vector2(((Rect)(ref screenRect)).width, ((Rect)(ref screenRect)).height); } private void UpdateTmpHud() { //IL_01ed: 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_0260: Unknown result type (might be due to invalid IL or missing references) //IL_0266: Unknown result type (might be due to invalid IL or missing references) //IL_02c6: Unknown result type (might be due to invalid IL or missing references) if (!ShowHud.Value || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null) { if ((Object)(object)_hudRoot != (Object)null) { _hudRoot.SetActive(false); } return; } EnsureTmpHud(); _hudRoot.SetActive(true); double num = ServerTime(); string text = null; string text2 = null; if (ZoneState.Starting) { text = Localize("BATTLE ROYALE", "КОРОЛЕВСКАЯ БИТВА"); text2 = Localize("MATCH STARTS IN ", "МАТЧ НАЧНЁТСЯ ЧЕРЕЗ ") + FormatSeconds((float)Math.Max(0.0, ZoneState.MatchStartAt - num)); } else if (ZoneState.Running) { if (ZoneState.Phase == ZonePhase.Waiting && ZoneState.HasNext) { text = Localize("ZONE SHRINKS IN", "СУЖЕНИЕ ЗОНЫ ЧЕРЕЗ"); text2 = FormatSeconds(Mathf.Max(0f, WaitBeforeShrink.Value - (float)(num - ZoneState.PhaseStartedAt))); } else if (ZoneState.Phase == ZonePhase.Shrinking && ZoneState.HasNext) { text = Localize("ZONE IS SHRINKING", "ЗОНА СУЖАЕТСЯ"); text2 = FormatSeconds(Mathf.Max(0f, ShrinkDuration.Value - (float)(num - ZoneState.PhaseStartedAt))); } else { text = Localize("BATTLE ROYALE", "КОРОЛЕВСКАЯ БИТВА"); } } bool flag = !string.IsNullOrEmpty(text); ((Component)_hudTitle).gameObject.SetActive(flag); ((Component)_hudTimer).gameObject.SetActive(flag && !string.IsNullOrEmpty(text2)); if (flag) { if (!MinimapUpdatePatch.TryGetSmallMinimapScreenRect(Minimap.instance, out var screenRect)) { ((Rect)(ref screenRect))..ctor((float)Screen.width - 320f, 245f, 300f, 70f); } float num2 = ((Rect)(ref screenRect)).yMax + 8f; SetScreenRect(((TMP_Text)_hudTitle).rectTransform, new Rect(((Rect)(ref screenRect)).x, num2, ((Rect)(ref screenRect)).width, 28f)); SetScreenRect(((TMP_Text)_hudTimer).rectTransform, new Rect(((Rect)(ref screenRect)).x, num2 + 27f, ((Rect)(ref screenRect)).width, 34f)); ((TMP_Text)_hudTitle).text = text; ((TMP_Text)_hudTimer).text = text2 ?? ""; } bool flag2 = ZoneState.Running && ZoneState.HasCurrent && DistanceXZ(((Component)Player.m_localPlayer).transform.position, GetEffectiveCurrentCenter()) > GetEffectiveCurrentRadius(); ((Component)_hudDanger).gameObject.SetActive(flag2); if (flag2) { SetScreenRect(((TMP_Text)_hudDanger).rectTransform, new Rect((float)Screen.width / 2f - 350f, (float)Screen.height * 0.7f, 700f, 45f)); ((TMP_Text)_hudDanger).text = Localize("YOU ARE OUTSIDE THE SAFE ZONE!", "ВЫ ВНЕ БЕЗОПАСНОЙ ЗОНЫ!"); } } private static string FormatSeconds(float value) { int num = Mathf.CeilToInt(value); return (num / 60).ToString("00") + ":" + (num % 60).ToString("00"); } private void OnGUI() { if ((Object)(object)Minimap.instance != (Object)null) { MinimapUpdatePatch.DrawZoneCircles(Minimap.instance); } } internal static bool HandleCommand(Terminal terminal, string line) { //IL_00d7: 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_0167: 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) if ((Object)(object)Instance == (Object)null || string.IsNullOrWhiteSpace(line)) { return false; } string[] array = line.Trim().Split(new char[2] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); if (array.Length == 0 || !array[0].Equals("br", StringComparison.OrdinalIgnoreCase)) { return false; } try { if (array.Length == 1 || array[1].Equals("help", StringComparison.OrdinalIgnoreCase)) { terminal.AddString("br start | stop | toggle | status | zone <x> <z> [r] | next <x> <z> [r] | here [r] | nexthere [r] | cancelnext"); return true; } string text = array[1].ToLowerInvariant(); switch (text) { case "status": terminal.AddString(ZoneState.Describe()); return true; case "start": case "stop": case "toggle": case "cancelnext": Instance.SendRequest(text); return true; case "here": case "nexthere": { if ((Object)(object)Player.m_localPlayer == (Object)null) { terminal.AddString("No local player."); return true; } float radius2 = ((array.Length >= 3) ? ParseFloat(array[2]) : 0f); Instance.SendRequest((text == "here") ? "zone" : "next", ((Component)Player.m_localPlayer).transform.position, radius2); return true; } case "zone": case "next": { if (array.Length < 4) { terminal.AddString("Usage: br " + text + " <x> <z> [radius]"); return true; } float num = ParseFloat(array[2]); float num2 = ParseFloat(array[3]); float radius = ((array.Length >= 5) ? ParseFloat(array[4]) : 0f); Instance.SendRequest(text, new Vector3(num, 0f, num2), radius); return true; } default: terminal.AddString("Unknown BR command. Type: br help"); break; } } catch (Exception ex) { terminal.AddString("BR error: " + ex.Message); } return true; } private static float ParseFloat(string s) { if (!float.TryParse(s.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { throw new FormatException("Invalid number: " + s); } return result; } } internal enum ZonePhase { Idle, Waiting, Shrinking } internal static class ZoneState { internal static bool Running; internal static bool Starting; internal static bool HasCurrent; internal static bool HasNext; internal static Vector3 CurrentCenter; internal static Vector3 NextCenter; internal static Vector3 ShrinkFromCenter; internal static float CurrentRadius; internal static float NextRadius; internal static float ShrinkFromRadius; internal static float WaitSecondsAtAssignment; internal static ZonePhase Phase; internal static double PhaseStartedAt; internal static double MatchStartAt; internal static void Write(ZPackage p) { //IL_0038: 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_007a: Unknown result type (might be due to invalid IL or missing references) p.Write(Running); p.Write(Starting); p.Write(MatchStartAt); p.Write(HasCurrent); p.Write(HasNext); p.Write(CurrentCenter); p.Write(CurrentRadius); p.Write(NextCenter); p.Write(NextRadius); p.Write((int)Phase); p.Write(PhaseStartedAt); p.Write(ShrinkFromCenter); p.Write(ShrinkFromRadius); p.Write(WaitSecondsAtAssignment); } internal static void Read(ZPackage p) { //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_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_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) Running = p.ReadBool(); Starting = p.ReadBool(); MatchStartAt = p.ReadDouble(); HasCurrent = p.ReadBool(); HasNext = p.ReadBool(); CurrentCenter = p.ReadVector3(); CurrentRadius = p.ReadSingle(); NextCenter = p.ReadVector3(); NextRadius = p.ReadSingle(); Phase = (ZonePhase)p.ReadInt(); PhaseStartedAt = p.ReadDouble(); ShrinkFromCenter = p.ReadVector3(); ShrinkFromRadius = p.ReadSingle(); WaitSecondsAtAssignment = p.ReadSingle(); } internal static string Describe() { return string.Format("BR running={0}, starting={1}, phase={2}, current=({3:F0},{4:F0}) R={5:F0}, next={6}", Running, Starting, Phase, CurrentCenter.x, CurrentCenter.z, CurrentRadius, HasNext ? $"({NextCenter.x:F0},{NextCenter.z:F0}) R={NextRadius:F0}" : "none"); } } [HarmonyPatch(typeof(Terminal), "TryRunCommand", new Type[] { typeof(string), typeof(bool), typeof(bool) })] internal static class TerminalTryRunCommandPatch { private static bool Prefix(Terminal __instance, string text) { return !ValheimBattleRoyalePlugin.HandleCommand(__instance, text); } } [HarmonyPatch(typeof(Game), "Start")] internal static class GameStartPatch { private static void Postfix() { if ((Object)(object)ValheimBattleRoyalePlugin.Instance != (Object)null) { ValheimBattleRoyalePlugin.Instance.ResetRpcRegistration(); } } } [HarmonyPatch(typeof(Minimap), "Update")] internal static class MinimapUpdatePatch { private static readonly MethodInfo ScreenToWorldPoint = FindMethod("ScreenToWorldPoint", typeof(Vector3)); private static bool _shiftWasDown; private static readonly FieldInfo MapImageLargeField = AccessTools.Field(typeof(Minimap), "m_mapImageLarge"); private static readonly FieldInfo MapImageSmallField = AccessTools.Field(typeof(Minimap), "m_mapImageSmall"); private static readonly FieldInfo PixelSizeField = AccessTools.Field(typeof(Minimap), "m_pixelSize"); private static readonly FieldInfo TextureSizeField = AccessTools.Field(typeof(Minimap), "m_textureSize"); private static Texture2D _lineTex; private static bool _overlayErrorLogged; private static MethodInfo FindMethod(string name, params Type[] parameterTypes) { MethodInfo[] methods = typeof(Minimap).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!string.Equals(methodInfo.Name, name, StringComparison.Ordinal)) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length != parameterTypes.Length) { continue; } bool flag = true; for (int j = 0; j < parameters.Length; j++) { if (parameters[j].ParameterType != parameterTypes[j]) { flag = false; break; } } if (flag) { return methodInfo; } } return null; } private static MethodInfo FindCompatibleOneArgMethod(string name, Type argumentType) { MethodInfo[] methods = typeof(Minimap).GetMethods(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic); foreach (MethodInfo methodInfo in methods) { if (!string.Equals(methodInfo.Name, name, StringComparison.Ordinal)) { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if (parameters.Length == 1) { Type parameterType = parameters[0].ParameterType; if (argumentType == null || parameterType == argumentType || parameterType.IsAssignableFrom(argumentType)) { return methodInfo; } } } return null; } private static void Postfix(Minimap __instance) { //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_0031: Invalid comparison between Unknown and I4 //IL_00fb: 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_0110: 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_00bb: 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_013b: 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_01b8: 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_0194: Unknown result type (might be due to invalid IL or missing references) //IL_01a0: 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) ValheimBattleRoyalePlugin instance = ValheimBattleRoyalePlugin.Instance; if ((Object)(object)instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || ScreenToWorldPoint == null || (int)__instance.m_mode != 2) { return; } bool flag = Input.GetKey((KeyCode)304) || Input.GetKey((KeyCode)303); bool flag2 = Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305); bool mouseButtonDown = Input.GetMouseButtonDown(0); if (mouseButtonDown && flag2) { if (ZoneState.Phase == ZonePhase.Shrinking) { ValheimBattleRoyalePlugin.Log.LogInfo((object)"Map Ctrl+Click ignored: zone shrinking is already in progress."); } else { ValheimBattleRoyalePlugin.Log.LogInfo((object)(ZoneState.HasNext ? "Map Ctrl+Click: cancel next zone" : "Map Ctrl+Click: cancel current/start zone")); instance.SendRequest("cancelzone"); } } else if (mouseButtonDown && flag) { if (ZoneState.Phase == ZonePhase.Shrinking) { ValheimBattleRoyalePlugin.Log.LogInfo((object)"Map Shift+Click ignored: zone shrinking is already in progress."); return; } try { Vector3 val = (Vector3)ScreenToWorldPoint.Invoke(__instance, new object[1] { Input.mousePosition }); val.y = 0f; if (!ZoneState.HasCurrent) { ValheimBattleRoyalePlugin.Log.LogInfo((object)$"Map Shift+Click: initial zone at X={val.x:F0} Z={val.z:F0}"); instance.SendRequest("zone", val, instance.InitialRadius.Value); } else { float num = (ZoneState.HasNext ? ZoneState.NextRadius : 0f); ValheimBattleRoyalePlugin.Log.LogInfo((object)(ZoneState.HasNext ? $"Map Shift+Click: move next zone to X={val.x:F0} Z={val.z:F0}, keep R={num:F0}" : $"Map Shift+Click: next zone at X={val.x:F0} Z={val.z:F0} (automatic radius)")); instance.SendRequest("next", val, num); } } catch (Exception ex) { ValheimBattleRoyalePlugin.Log.LogError((object)("Map click conversion failed: " + ex)); } } _shiftWasDown = flag; } internal static void DrawZoneCircles(Minimap map) { //IL_006a: 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_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_00ab: 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_00ce: 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) if (!ZoneState.HasCurrent || (Object)(object)map == (Object)null) { return; } try { object activeMapImage = GetActiveMapImage(map); if (activeMapImage == null || !TryGetImageGeometry(activeMapImage, out var uvRect, out var screenRect)) { return; } float numericField = GetNumericField(PixelSizeField, map, 1f); float numericField2 = GetNumericField(TextureSizeField, map, 2048f); float num = numericField * numericField2; if (!(num <= 0.001f)) { Vector3 effectiveCurrentCenter = ValheimBattleRoyalePlugin.Instance.GetEffectiveCurrentCenter(); float effectiveCurrentRadius = ValheimBattleRoyalePlugin.Instance.GetEffectiveCurrentRadius(); DrawCircle(effectiveCurrentCenter, effectiveCurrentRadius, new Color(0.2f, 1f, 0.25f, 0.95f), uvRect, screenRect, num, 3f); if (ZoneState.HasNext) { DrawCircle(ZoneState.NextCenter, ZoneState.NextRadius, new Color(1f, 0.85f, 0.15f, 0.95f), uvRect, screenRect, num, 3f); } _overlayErrorLogged = false; } } catch (Exception ex) { if (!_overlayErrorLogged) { _overlayErrorLogged = true; ValheimBattleRoyalePlugin.Log.LogWarning((object)("Zone map overlay unavailable: " + ex)); } } } private static object GetActiveMapImage(Minimap map) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Invalid comparison between Unknown and I4 if ((int)map.m_mode == 2) { return MapImageLargeField?.GetValue(map); } return MapImageSmallField?.GetValue(map); } internal static bool TryGetSmallMinimapScreenRect(Minimap map, out Rect screenRect) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) screenRect = default(Rect); if ((Object)(object)map == (Object)null) { return false; } try { object obj = MapImageSmallField?.GetValue(map); if (obj == null) { return false; } Rect uvRect; return TryGetImageGeometry(obj, out uvRect, out screenRect); } catch { return false; } } private static float GetNumericField(FieldInfo field, object instance, float fallback) { if (field == null) { return fallback; } object value = field.GetValue(instance); if (value == null) { return fallback; } try { return Convert.ToSingle(value, CultureInfo.InvariantCulture); } catch { return fallback; } } private static bool TryGetImageGeometry(object image, out Rect uvRect, out Rect screenRect) { //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_0020: 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_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: 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_00db: 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_00fb: 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_014a: 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) uvRect = new Rect(0f, 0f, 1f, 1f); screenRect = default(Rect); PropertyInfo property = image.GetType().GetProperty("uvRect", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.PropertyType == typeof(Rect)) { uvRect = (Rect)property.GetValue(image, null); } Component val = (Component)((image is Component) ? image : null); if ((Object)(object)val == (Object)null) { return false; } Transform transform = val.transform; RectTransform val2 = (RectTransform)(object)((transform is RectTransform) ? transform : null); if ((Object)(object)val2 == (Object)null) { return false; } Vector3[] array = (Vector3[])(object)new Vector3[4]; val2.GetWorldCorners(array); float num = float.MaxValue; float num2 = float.MinValue; float num3 = float.MaxValue; float num4 = float.MinValue; for (int i = 0; i < array.Length; i++) { Vector3 val3 = Vector2.op_Implicit(RectTransformUtility.WorldToScreenPoint((Camera)null, array[i])); num = Mathf.Min(num, val3.x); num2 = Mathf.Max(num2, val3.x); num3 = Mathf.Min(num3, val3.y); num4 = Mathf.Max(num4, val3.y); } if (num2 <= num || num4 <= num3) { return false; } screenRect = new Rect(num, (float)Screen.height - num4, num2 - num, num4 - num3); return true; } private static Vector2 WorldToGui(Vector3 world, Rect uvRect, Rect screenRect, float worldSize) { //IL_0005: 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_0062: Unknown result type (might be due to invalid IL or missing references) float num = 0.5f + world.x / worldSize; float num2 = 0.5f + world.z / worldSize; float num3 = (num - ((Rect)(ref uvRect)).xMin) / ((Rect)(ref uvRect)).width; float num4 = (num2 - ((Rect)(ref uvRect)).yMin) / ((Rect)(ref uvRect)).height; return new Vector2(((Rect)(ref screenRect)).xMin + num3 * ((Rect)(ref screenRect)).width, ((Rect)(ref screenRect)).yMax - num4 * ((Rect)(ref screenRect)).height); } private static void DrawCircle(Vector3 center, float radius, Color color, Rect uvRect, Rect screenRect, float worldSize, float width) { //IL_0000: 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_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_0017: 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_003a: 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_005a: 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_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_0065: 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_0067: 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_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0072: Unknown result type (might be due to invalid IL or missing references) Vector2 a = WorldToGui(center + new Vector3(radius, 0f, 0f), uvRect, screenRect, worldSize); for (int i = 1; i <= 128; i++) { float num = (float)i * (float)Math.PI * 2f / 128f; Vector2 val = WorldToGui(center + new Vector3(Mathf.Cos(num) * radius, 0f, Mathf.Sin(num) * radius), uvRect, screenRect, worldSize); DrawClippedLine(a, val, color, width, screenRect); a = val; } } private static void DrawClippedLine(Vector2 a, Vector2 b, Color color, float width, Rect clip) { //IL_0000: 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_000f: 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_002d: 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_004b: 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_007a: 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_0069: Unknown result type (might be due to invalid IL or missing references) if ((!(a.x < ((Rect)(ref clip)).xMin) || !(b.x < ((Rect)(ref clip)).xMin)) && (!(a.x > ((Rect)(ref clip)).xMax) || !(b.x > ((Rect)(ref clip)).xMax)) && (!(a.y < ((Rect)(ref clip)).yMin) || !(b.y < ((Rect)(ref clip)).yMin)) && (!(a.y > ((Rect)(ref clip)).yMax) || !(b.y > ((Rect)(ref clip)).yMax))) { DrawLine(a, b, color, width); } } private static void DrawLine(Vector2 a, Vector2 b, Color color, float width) { //IL_0034: 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_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_000f: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Expected O, but got Unknown //IL_0020: 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_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_005c: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_0073: 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_007f: 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_00a4: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_lineTex == (Object)null) { _lineTex = new Texture2D(1, 1); _lineTex.SetPixel(0, 0, Color.white); _lineTex.Apply(); } Vector2 val = b - a; if (!(((Vector2)(ref val)).sqrMagnitude < 0.01f)) { Matrix4x4 matrix = GUI.matrix; Color color2 = GUI.color; GUI.color = color; GUIUtility.RotateAroundPivot(Mathf.Atan2(val.y, val.x) * 57.29578f, a); GUI.DrawTexture(new Rect(a.x, a.y - width * 0.5f, ((Vector2)(ref val)).magnitude, width), (Texture)(object)_lineTex); GUI.matrix = matrix; GUI.color = color2; } } }